c4dynamics 2.0.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- c4dynamics/__init__.py +240 -0
- c4dynamics/datasets/__init__.py +95 -0
- c4dynamics/datasets/_manager.py +596 -0
- c4dynamics/datasets/_registry.py +80 -0
- c4dynamics/detectors/__init__.py +37 -0
- c4dynamics/detectors/yolo3_opencv.py +686 -0
- c4dynamics/detectors/yolo3_tf.py +124 -0
- c4dynamics/eqm/__init__.py +324 -0
- c4dynamics/eqm/derivs.py +212 -0
- c4dynamics/eqm/integrate.py +359 -0
- c4dynamics/filters/__init__.py +1373 -0
- c4dynamics/filters/a.py +48 -0
- c4dynamics/filters/ekf.py +320 -0
- c4dynamics/filters/kalman.py +725 -0
- c4dynamics/filters/kalman_v0.py +1071 -0
- c4dynamics/filters/kalman_v1.py +821 -0
- c4dynamics/filters/lowpass.py +123 -0
- c4dynamics/filters/luenberger.py +97 -0
- c4dynamics/rotmat/__init__.py +141 -0
- c4dynamics/rotmat/animate.py +465 -0
- c4dynamics/rotmat/rotmat.py +351 -0
- c4dynamics/sensors/__init__.py +72 -0
- c4dynamics/sensors/lineofsight.py +78 -0
- c4dynamics/sensors/radar.py +740 -0
- c4dynamics/sensors/seeker.py +1030 -0
- c4dynamics/states/__init__.py +327 -0
- c4dynamics/states/lib/__init__.py +320 -0
- c4dynamics/states/lib/datapoint.py +660 -0
- c4dynamics/states/lib/pixelpoint.py +776 -0
- c4dynamics/states/lib/rigidbody.py +677 -0
- c4dynamics/states/state.py +1486 -0
- c4dynamics/utils/__init__.py +44 -0
- c4dynamics/utils/_struct.py +6 -0
- c4dynamics/utils/const.py +130 -0
- c4dynamics/utils/cprint.py +80 -0
- c4dynamics/utils/gen_gif.py +142 -0
- c4dynamics/utils/idx2keys.py +4 -0
- c4dynamics/utils/images_loader.py +63 -0
- c4dynamics/utils/math.py +136 -0
- c4dynamics/utils/plottools.py +140 -0
- c4dynamics/utils/plottracks.py +304 -0
- c4dynamics/utils/printpts.py +36 -0
- c4dynamics/utils/slides_gen.py +64 -0
- c4dynamics/utils/tictoc.py +167 -0
- c4dynamics/utils/video_gen.py +300 -0
- c4dynamics/utils/vidgen.py +182 -0
- c4dynamics-2.0.3.dist-info/METADATA +242 -0
- c4dynamics-2.0.3.dist-info/RECORD +50 -0
- c4dynamics-2.0.3.dist-info/WHEEL +5 -0
- c4dynamics-2.0.3.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
sys.path.append('.')
|
|
3
|
+
import time
|
|
4
|
+
_tic = 0.0
|
|
5
|
+
|
|
6
|
+
def tic():
|
|
7
|
+
'''
|
|
8
|
+
Starts stopwatch timer.
|
|
9
|
+
|
|
10
|
+
Inspired by `MATLAB's` tic toc, `tic()` records the current time to start measuring elapsed time.
|
|
11
|
+
When used in conjunction with `toc()` serves as a stopwatch
|
|
12
|
+
timer to measure the time interval between two events.
|
|
13
|
+
|
|
14
|
+
Returns
|
|
15
|
+
-------
|
|
16
|
+
out : float
|
|
17
|
+
The recorded start time.
|
|
18
|
+
|
|
19
|
+
Examples
|
|
20
|
+
--------
|
|
21
|
+
|
|
22
|
+
.. code::
|
|
23
|
+
|
|
24
|
+
>>> import c4dynamics as c4d
|
|
25
|
+
>>> import numpy as np
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
.. code::
|
|
29
|
+
|
|
30
|
+
>>> N = 10000
|
|
31
|
+
>>> tic() # doctest: +IGNORE_OUTPUT
|
|
32
|
+
>>> a = np.ones((1, 3))
|
|
33
|
+
>>> for i in range(N - 1):
|
|
34
|
+
... a = np.concatenate((a, np.ones((1, 3))))
|
|
35
|
+
>>> t1 = toc() # doctest: +IGNORE_OUTPUT
|
|
36
|
+
>>> c4d.cprint('numpy concat: ' + str(1000 * t1) + ' ms', 'r') # doctest: +IGNORE_OUTPUT
|
|
37
|
+
numpy concat: 40.0 ms
|
|
38
|
+
|
|
39
|
+
.. code::
|
|
40
|
+
|
|
41
|
+
>>> tic() # doctest: +IGNORE_OUTPUT
|
|
42
|
+
>>> a = np.zeros((N, 3))
|
|
43
|
+
>>> for i in range(N):
|
|
44
|
+
... a[i, :] = np.ones((1, 3))
|
|
45
|
+
>>> t2 = toc() # doctest: +IGNORE_OUTPUT
|
|
46
|
+
>>> c4d.cprint('numpy predefined: ' + str(1000 * t2) + ' ms', 'g') # doctest: +IGNORE_OUTPUT
|
|
47
|
+
numpy predefined: 3.0 ms
|
|
48
|
+
|
|
49
|
+
.. code::
|
|
50
|
+
|
|
51
|
+
>>> tic()# doctest: +IGNORE_OUTPUT
|
|
52
|
+
>>> a = []
|
|
53
|
+
>>> for i in range(N):
|
|
54
|
+
... a.append([1, 1, 1])
|
|
55
|
+
>>> a = np.array(a)
|
|
56
|
+
>>> t3 = toc()# doctest: +IGNORE_OUTPUT
|
|
57
|
+
>>> c4d.cprint('list to numpy: ' + str(1000 * t3) + ' ms', 'y') # doctest: +IGNORE_OUTPUT
|
|
58
|
+
list to numpy: 0.0 ms
|
|
59
|
+
|
|
60
|
+
'''
|
|
61
|
+
|
|
62
|
+
global _tic
|
|
63
|
+
_tic = time.time()
|
|
64
|
+
return _tic
|
|
65
|
+
|
|
66
|
+
def toc(show = True):
|
|
67
|
+
'''
|
|
68
|
+
|
|
69
|
+
Stops the stopwatch timer and reads the elapsed time.
|
|
70
|
+
|
|
71
|
+
Measures the elapsed time since the last call to `tic()` and prints the result in seconds.
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
Returns
|
|
75
|
+
-------
|
|
76
|
+
out : float
|
|
77
|
+
Elapsed time in seconds.
|
|
78
|
+
|
|
79
|
+
Examples
|
|
80
|
+
--------
|
|
81
|
+
|
|
82
|
+
.. code::
|
|
83
|
+
|
|
84
|
+
>>> import c4dynamics as c4d
|
|
85
|
+
>>> import numpy as np
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
.. code::
|
|
89
|
+
|
|
90
|
+
>>> N = 10000
|
|
91
|
+
>>> tic() # doctest: +IGNORE_OUTPUT
|
|
92
|
+
>>> a = np.ones((1, 3))
|
|
93
|
+
>>> for i in range(N - 1):
|
|
94
|
+
... a = np.concatenate((a, np.ones((1, 3))))
|
|
95
|
+
>>> t1 = toc() # doctest: +IGNORE_OUTPUT
|
|
96
|
+
>>> c4d.cprint('numpy concat: ' + str(1000 * t1) + ' ms', 'r') # doctest: +IGNORE_OUTPUT
|
|
97
|
+
numpy concat: 31.0 ms
|
|
98
|
+
|
|
99
|
+
.. code::
|
|
100
|
+
|
|
101
|
+
>>> tic() # doctest: +IGNORE_OUTPUT
|
|
102
|
+
>>> a = np.zeros((N, 3))
|
|
103
|
+
>>> for i in range(N):
|
|
104
|
+
... a[i, :] = np.ones((1, 3))
|
|
105
|
+
>>> t2 = toc() # doctest: +IGNORE_OUTPUT
|
|
106
|
+
>>> c4d.cprint('numpy predefined: ' + str(1000 * t2) + ' ms', 'g') # doctest: +IGNORE_OUTPUT
|
|
107
|
+
numpy predefined: 15.0 ms
|
|
108
|
+
|
|
109
|
+
.. code::
|
|
110
|
+
|
|
111
|
+
>>> tic() # doctest: +IGNORE_OUTPUT
|
|
112
|
+
>>> a = []
|
|
113
|
+
>>> for i in range(N):
|
|
114
|
+
... a.append([1, 1, 1])
|
|
115
|
+
>>> a = np.array(a)
|
|
116
|
+
>>> t3 = toc() # doctest: +IGNORE_OUTPUT
|
|
117
|
+
>>> c4d.cprint('list to numpy: ' + str(1000 * t3) + ' ms', 'y') # doctest: +IGNORE_OUTPUT
|
|
118
|
+
list to numpy: 0.0 ms
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
'''
|
|
122
|
+
|
|
123
|
+
global _tic
|
|
124
|
+
dt = time.time() - _tic
|
|
125
|
+
if show: print(f'{dt:.3f}')
|
|
126
|
+
return dt
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
# tic():
|
|
131
|
+
|
|
132
|
+
# Records the current time to start measuring elapsed time.
|
|
133
|
+
|
|
134
|
+
# Returns:
|
|
135
|
+
# float: The recorded start time.
|
|
136
|
+
|
|
137
|
+
# toc():
|
|
138
|
+
|
|
139
|
+
# Measures the elapsed time since the last call to `tic()` and prints the result in seconds.
|
|
140
|
+
|
|
141
|
+
# Returns:
|
|
142
|
+
# float: The elapsed time in seconds.
|
|
143
|
+
|
|
144
|
+
if __name__ == "__main__":
|
|
145
|
+
|
|
146
|
+
import doctest, contextlib, os
|
|
147
|
+
from c4dynamics import IgnoreOutputChecker, cprint
|
|
148
|
+
|
|
149
|
+
# Register the custom OutputChecker
|
|
150
|
+
doctest.OutputChecker = IgnoreOutputChecker
|
|
151
|
+
|
|
152
|
+
tofile = False
|
|
153
|
+
optionflags = doctest.FAIL_FAST
|
|
154
|
+
|
|
155
|
+
if tofile:
|
|
156
|
+
with open(os.path.join('tests', '_out', 'output.txt'), 'w') as f:
|
|
157
|
+
with contextlib.redirect_stdout(f), contextlib.redirect_stderr(f):
|
|
158
|
+
result = doctest.testmod(optionflags = optionflags)
|
|
159
|
+
else:
|
|
160
|
+
result = doctest.testmod(optionflags = optionflags)
|
|
161
|
+
|
|
162
|
+
if result.failed == 0:
|
|
163
|
+
cprint(os.path.basename(__file__) + ": all tests passed!", 'g')
|
|
164
|
+
else:
|
|
165
|
+
print(f"{result.failed}")
|
|
166
|
+
|
|
167
|
+
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
# type: ignore
|
|
2
|
+
# # The following environment is selected:
|
|
3
|
+
# \\192.168.1.244\d\gh_repo\c4dynamics\.venv\Scripts\python.exe
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
'''
|
|
7
|
+
working plan:
|
|
8
|
+
after proving the algo on synthetis videos i made manually here:
|
|
9
|
+
take 2 or 3 types of motion videos:
|
|
10
|
+
linear, parabole, sinsuidal
|
|
11
|
+
and show performances with c4dynamics.
|
|
12
|
+
show improvemnet for better dynamics modelling.
|
|
13
|
+
|
|
14
|
+
'''
|
|
15
|
+
import os, sys
|
|
16
|
+
import socket
|
|
17
|
+
import cv2
|
|
18
|
+
import numpy as np
|
|
19
|
+
from enum import Enum
|
|
20
|
+
print(os.getcwd())
|
|
21
|
+
# import c4dynamics as c4d
|
|
22
|
+
# if socket.gethostname() != 'ZivMeri-PC':
|
|
23
|
+
# os.chdir(os.path.join('\\\\192.168.1.244', 'd', 'gh_repo', 'c4dynamics'))
|
|
24
|
+
print(sys.executable)
|
|
25
|
+
# https://github.com/microsoft/debugpy/issues/1231
|
|
26
|
+
|
|
27
|
+
FRAMEWIDTH = 1280
|
|
28
|
+
FRAMEHEIGHT = 720
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class Im_saveshow(Enum):
|
|
33
|
+
SHOW = 1
|
|
34
|
+
SAVE = 2
|
|
35
|
+
SAVESHOW = 3
|
|
36
|
+
|
|
37
|
+
class Motion_Type(Enum):
|
|
38
|
+
LINEAR = 1
|
|
39
|
+
PARABOLE = 2
|
|
40
|
+
SINE = 3
|
|
41
|
+
|
|
42
|
+
def rotateimage(image, angle0, angle1):
|
|
43
|
+
# Define the angle of rotation (in degrees)
|
|
44
|
+
# angle = -90 # Change this value as needed
|
|
45
|
+
|
|
46
|
+
# dangle = pathangle - current_rotation
|
|
47
|
+
|
|
48
|
+
# # Get the dimensions of the image
|
|
49
|
+
# height, width = image.shape[:2]
|
|
50
|
+
|
|
51
|
+
# rotation_matrix = cv2.getRotationMatrix2D((image.shape[1] / 2, image.shape[0] / 2), angle, 1)
|
|
52
|
+
# # Calculate the new dimensions of the rotated image to prevent trimming
|
|
53
|
+
# cos_theta = np.abs(rotation_matrix[0, 0])
|
|
54
|
+
# sin_theta = np.abs(rotation_matrix[0, 1])
|
|
55
|
+
# new_width = int((height * sin_theta) + (width * cos_theta))
|
|
56
|
+
# new_height = int((height * cos_theta) + (width * sin_theta))
|
|
57
|
+
|
|
58
|
+
# # Adjust the rotation matrix for translation to keep the entire image visible
|
|
59
|
+
# rotation_matrix[0, 2] += (new_width / 2) - (width / 2)
|
|
60
|
+
# rotation_matrix[1, 2] += (new_height / 2) - (height / 2)
|
|
61
|
+
# Calculate the rotation matrix
|
|
62
|
+
|
|
63
|
+
dangle = angle0 - angle1
|
|
64
|
+
|
|
65
|
+
# Get the dimensions of the image
|
|
66
|
+
height, width = image.shape[:2]
|
|
67
|
+
|
|
68
|
+
delta_rotation_matrix = cv2.getRotationMatrix2D((width / 2, height / 2), dangle, 1)
|
|
69
|
+
angle_rotation_matrix = cv2.getRotationMatrix2D((width / 2, height / 2), dangle, 1)
|
|
70
|
+
# Calculate the new dimensions of the rotated image to prevent trimming
|
|
71
|
+
cos_theta = np.abs(angle_rotation_matrix[0, 0])
|
|
72
|
+
sin_theta = np.abs(angle_rotation_matrix[0, 1])
|
|
73
|
+
new_width = int((height * sin_theta) + (width * cos_theta))
|
|
74
|
+
new_height = int((height * cos_theta) + (width * sin_theta))
|
|
75
|
+
|
|
76
|
+
# Adjust the rotation matrix for translation to keep the entire image visible
|
|
77
|
+
delta_rotation_matrix[0, 2] += (new_width / 2) - (width / 2)
|
|
78
|
+
delta_rotation_matrix[1, 2] += (new_height / 2) - (height / 2)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
# Perform the rotation using warpAffine
|
|
82
|
+
return cv2.warpAffine(image, delta_rotation_matrix, (new_width, new_height))
|
|
83
|
+
|
|
84
|
+
# # Display the original and rotated images (optional)
|
|
85
|
+
# cv2.imshow('Original Image', image)
|
|
86
|
+
# cv2.imshow('Rotated Image', rotated_image)
|
|
87
|
+
# cv2.waitKey(0)
|
|
88
|
+
# cv2.destroyAllWindows()
|
|
89
|
+
|
|
90
|
+
# # Save the rotated image
|
|
91
|
+
# cv2.imwrite('path_to_save_rotated_image.jpg', rotated_image)
|
|
92
|
+
|
|
93
|
+
# return rotated_image
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def animate(objpath, x0 = 0, y0 = 0
|
|
98
|
+
, scaling = 1, rotate = False, pathangle = None
|
|
99
|
+
, motion = Motion_Type.LINEAR, saveshow = Im_saveshow.SAVESHOW.value):
|
|
100
|
+
|
|
101
|
+
''' make a linear moving object video '''
|
|
102
|
+
|
|
103
|
+
# Define the dimensions of the video frame
|
|
104
|
+
saveon = any(x for x in [Im_saveshow.SAVESHOW.value, Im_saveshow.SAVE.value] if x == saveshow)
|
|
105
|
+
showon = any(x for x in [Im_saveshow.SAVESHOW.value, Im_saveshow.SHOW.value] if x == saveshow)
|
|
106
|
+
|
|
107
|
+
out = cv2.VideoWriter(os.path.join(os.getcwd(), 'examples', 'resources'
|
|
108
|
+
, motion.name + '_' + os.path.basename(objpath)[:-4]
|
|
109
|
+
+ str(int(x0)) + str(int(y0)) + '.mp4')
|
|
110
|
+
, cv2.VideoWriter_fourcc(*'mp4v')
|
|
111
|
+
, 30.0, (FRAMEWIDTH, FRAMEHEIGHT))
|
|
112
|
+
|
|
113
|
+
# Load the im_object you want to move
|
|
114
|
+
im_object = cv2.imread(objpath, cv2.IMREAD_UNCHANGED)
|
|
115
|
+
|
|
116
|
+
video_duration = 1
|
|
117
|
+
|
|
118
|
+
if pathangle is None:
|
|
119
|
+
if motion == Motion_Type.LINEAR:
|
|
120
|
+
pathangle = 0
|
|
121
|
+
elif motion == Motion_Type.PARABOLE:
|
|
122
|
+
pathangle = 45
|
|
123
|
+
video_duration = 1.5
|
|
124
|
+
elif motion == Motion_Type.SINE:
|
|
125
|
+
pathangle = 0
|
|
126
|
+
video_duration = 2
|
|
127
|
+
|
|
128
|
+
num_frames = int(30 * video_duration)
|
|
129
|
+
|
|
130
|
+
# im_object = rotateimage(im_object, -pathangle * rotate)
|
|
131
|
+
im_object = cv2.resize(im_object, tuple(reversed(tuple(int(scaling * i) for i in im_object.shape[:2]))))
|
|
132
|
+
im_object = rotateimage(im_object, 0, pathangle * rotate)
|
|
133
|
+
|
|
134
|
+
im_object_height, im_object_width, _ = im_object.shape
|
|
135
|
+
|
|
136
|
+
# Ensure the im_object has 3 channels (remove alpha channel)
|
|
137
|
+
im_object = im_object[:, :, :3]
|
|
138
|
+
|
|
139
|
+
# Define initial position and velocity of the im_object
|
|
140
|
+
# change to center of image
|
|
141
|
+
x_pos = int(x0 - im_object_width / 2)
|
|
142
|
+
y_pos = int(y0 - im_object_height / 2)
|
|
143
|
+
|
|
144
|
+
vtotal_diag = np.sqrt(FRAMEHEIGHT**2 + FRAMEHEIGHT**2) / 30
|
|
145
|
+
x_velocity = int(vtotal_diag * np.cos(pathangle * np.pi / 180)) # int(FRAMEWIDTH / 30) # Adjust velocity based on frame width
|
|
146
|
+
y_velocity = int(vtotal_diag * np.sin(pathangle * np.pi / 180)) # int(FRAMEHEIGHT / 30) # Adjust velocity based on frame width
|
|
147
|
+
|
|
148
|
+
# Define the duration of the video in seconds
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
# Generate the frames for the video
|
|
152
|
+
for fi in range(num_frames):
|
|
153
|
+
# Create a black background frame
|
|
154
|
+
frame = np.zeros((FRAMEHEIGHT, FRAMEWIDTH, 3), dtype = np.uint8)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
# Calculate the region to overlay the im_object on the frame
|
|
158
|
+
|
|
159
|
+
if x_pos >= 0 and x_pos + im_object_width < FRAMEWIDTH:
|
|
160
|
+
''' simplest. all in '''
|
|
161
|
+
TO_start_col = x_pos
|
|
162
|
+
TO_end_col = x_pos + im_object_width
|
|
163
|
+
FROM_start_col = 0
|
|
164
|
+
FROM_end_col = im_object_width
|
|
165
|
+
|
|
166
|
+
elif x_pos < 0:
|
|
167
|
+
''' pixels covered from left '''
|
|
168
|
+
TO_start_col = 0
|
|
169
|
+
TO_end_col = x_pos + im_object_width
|
|
170
|
+
FROM_start_col = -x_pos
|
|
171
|
+
FROM_end_col = im_object_width
|
|
172
|
+
|
|
173
|
+
elif x_pos + im_object_width >= FRAMEWIDTH:
|
|
174
|
+
''' pixels covered from right '''
|
|
175
|
+
TO_start_col = x_pos
|
|
176
|
+
TO_end_col = FRAMEWIDTH
|
|
177
|
+
FROM_start_col = 0
|
|
178
|
+
FROM_end_col = max(FRAMEWIDTH - x_pos, 0)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
if y_pos >= 0 and y_pos + im_object_height < FRAMEHEIGHT:
|
|
182
|
+
''' simplest. all in '''
|
|
183
|
+
TO_start_row = y_pos
|
|
184
|
+
TO_end_row = y_pos + im_object_height
|
|
185
|
+
FROM_start_row = 0
|
|
186
|
+
FROM_end_row = im_object_height
|
|
187
|
+
|
|
188
|
+
elif y_pos < 0:
|
|
189
|
+
''' pixels covered from top '''
|
|
190
|
+
TO_start_row = 0
|
|
191
|
+
TO_end_row = max(y_pos + im_object_height, 0)
|
|
192
|
+
FROM_start_row = -y_pos
|
|
193
|
+
FROM_end_row = im_object_height
|
|
194
|
+
|
|
195
|
+
elif y_pos + im_object_height >= FRAMEHEIGHT:
|
|
196
|
+
''' pixels covered from bottom '''
|
|
197
|
+
TO_start_row = y_pos
|
|
198
|
+
TO_end_row = FRAMEHEIGHT
|
|
199
|
+
FROM_start_row = 0
|
|
200
|
+
FROM_end_row = max(FRAMEHEIGHT - y_pos, 0)
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
fromshape = im_object[FROM_start_row : FROM_end_row, FROM_start_col : FROM_end_col].shape
|
|
204
|
+
toshape = frame[TO_start_row : TO_end_row, TO_start_col : TO_end_col].shape
|
|
205
|
+
|
|
206
|
+
frame[TO_start_row : TO_end_row, TO_start_col : TO_end_col] = (
|
|
207
|
+
im_object[FROM_start_row : FROM_end_row, FROM_start_col : FROM_end_col]
|
|
208
|
+
).astype(np.uint8)
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
# current_rotation = 0
|
|
213
|
+
|
|
214
|
+
if motion == Motion_Type.LINEAR:
|
|
215
|
+
pass
|
|
216
|
+
|
|
217
|
+
elif motion == Motion_Type.PARABOLE:
|
|
218
|
+
# parabole
|
|
219
|
+
# f / num_frames # when this is 1/2 i want pathangle to be zero.
|
|
220
|
+
# when 1 to be 45.
|
|
221
|
+
# nameyly in full circly to change by 90.
|
|
222
|
+
# xdegrees per f.
|
|
223
|
+
# -90deg in numframes.
|
|
224
|
+
# x = -90 / nframe
|
|
225
|
+
pathangle -= 90 / num_frames
|
|
226
|
+
x_velocity = int(vtotal_diag * np.cos(pathangle * np.pi / 180)) # int(FRAMEWIDTH / 30) # Adjust velocity based on frame width
|
|
227
|
+
y_velocity = int(vtotal_diag * np.sin(pathangle * np.pi / 180)) # int(FRAMEHEIGHT / 30) # Adjust velocity based on frame width
|
|
228
|
+
|
|
229
|
+
elif motion == Motion_Type.SINE:
|
|
230
|
+
# sinusidly
|
|
231
|
+
# all frames: 2 * pi
|
|
232
|
+
# fi numframes
|
|
233
|
+
# path angle 0 to 360 at numframes.
|
|
234
|
+
# one frame 360/nframe
|
|
235
|
+
pathangle = 90 * np.cos(3 * fi / num_frames * 2 * np.pi)
|
|
236
|
+
x_velocity = int(vtotal_diag * np.cos(pathangle * np.pi / 180)) # int(FRAMEWIDTH / 30) # Adjust velocity based on frame width
|
|
237
|
+
y_velocity = int(vtotal_diag * np.sin(pathangle * np.pi / 180)) # int(FRAMEHEIGHT / 30) # Adjust velocity based on frame width
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
# im_object = rotateimage(im_object, current_rotation, pathangle)
|
|
242
|
+
# print(f'{fi:5.0f} {pathangle} {x_velocity} {y_velocity}')
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
x_pos += x_velocity
|
|
246
|
+
y_pos += y_velocity
|
|
247
|
+
|
|
248
|
+
# Write the frame to the video file
|
|
249
|
+
|
|
250
|
+
if saveon:
|
|
251
|
+
out.write(frame)
|
|
252
|
+
if showon:
|
|
253
|
+
cv2.imshow('im_object', frame)
|
|
254
|
+
cv2.waitKey(300)
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
# Release the VideoWriter object and close all windows
|
|
259
|
+
out.release()
|
|
260
|
+
cv2.destroyAllWindows()
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
# class Im_saveshow(Enum):
|
|
265
|
+
# SHOW = 1
|
|
266
|
+
# SAVE = 2
|
|
267
|
+
# SAVESHOW = 3
|
|
268
|
+
|
|
269
|
+
objpath = os.path.join(os.getcwd(), 'examples', 'resources', 'car.png')
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
for runcase in range(1, 6):
|
|
273
|
+
|
|
274
|
+
if runcase == 1:
|
|
275
|
+
''' linear 1: left to right '''
|
|
276
|
+
animate(objpath = objpath, motion = Motion_Type.LINEAR
|
|
277
|
+
, x0 = 0, y0 = FRAMEHEIGHT / 2, scaling = .5, rotate = True)
|
|
278
|
+
|
|
279
|
+
elif runcase == 2:
|
|
280
|
+
''' linear 2: top to bottom '''
|
|
281
|
+
animate(objpath = objpath, motion = Motion_Type.LINEAR
|
|
282
|
+
, x0 = FRAMEWIDTH / 2, y0 = 0, scaling = .5, rotate = True
|
|
283
|
+
, pathangle = 90)
|
|
284
|
+
|
|
285
|
+
elif runcase == 3:
|
|
286
|
+
''' linear 3: top left to bottom right '''
|
|
287
|
+
animate(objpath = objpath, motion = Motion_Type.LINEAR
|
|
288
|
+
, x0 = 0, y0 = 0, scaling = .5, rotate = True
|
|
289
|
+
, pathangle = np.arctan(FRAMEHEIGHT / FRAMEWIDTH) * 180 / np.pi)
|
|
290
|
+
|
|
291
|
+
elif runcase == 4:
|
|
292
|
+
''' parabole 1: top left to top right '''
|
|
293
|
+
animate(objpath = objpath, motion = Motion_Type.PARABOLE, x0 = 0, y0 = 0, scaling = .5)
|
|
294
|
+
|
|
295
|
+
elif runcase == 5:
|
|
296
|
+
''' sinusoid 1: left to right '''
|
|
297
|
+
animate(objpath = objpath, motion = Motion_Type.SINE, x0 = 0, y0 = FRAMEHEIGHT / 2, scaling = .5)
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import sys, os, re
|
|
2
|
+
# print(sys.version)
|
|
3
|
+
import natsort
|
|
4
|
+
|
|
5
|
+
from pptx import Presentation
|
|
6
|
+
from pptx.util import Inches
|
|
7
|
+
from pptx.enum.shapes import MSO_SHAPE_TYPE
|
|
8
|
+
|
|
9
|
+
from lxml import etree
|
|
10
|
+
import tkinter as tk
|
|
11
|
+
from tkinter import filedialog
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
edit_existing = True # False #
|
|
19
|
+
imfol = 'cars2_short/accsize2model' # 'cars2_short/velmodel' #
|
|
20
|
+
delimages = False
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# Path to the folder containing images
|
|
30
|
+
folder_path = os.path.join('D:/', 'Dropbox', 'c4dynamics', 'examples', '_out', imfol)
|
|
31
|
+
# print(folder_path)
|
|
32
|
+
# Create a PowerPoint presentation object
|
|
33
|
+
|
|
34
|
+
if edit_existing:
|
|
35
|
+
root = tk.Tk()
|
|
36
|
+
root.withdraw() # Hide the root window
|
|
37
|
+
|
|
38
|
+
# Bring the root window to the front
|
|
39
|
+
root.lift()
|
|
40
|
+
root.attributes("-topmost", True)
|
|
41
|
+
root.after_idle(root.attributes, '-topmost', False)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
# Open a file dialog to select the PowerPoint file
|
|
45
|
+
pptfile = filedialog.askopenfilename(
|
|
46
|
+
title="Select PowerPoint File",
|
|
47
|
+
filetypes=[("PowerPoint files", "*.pptx")]
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
else:
|
|
51
|
+
pptfile = None
|
|
52
|
+
|
|
53
|
+
prs = Presentation(pptfile)
|
|
54
|
+
prs.slide_width = Inches(20)
|
|
55
|
+
prs.slide_height = Inches(11.25)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
namespace = {
|
|
59
|
+
'p': 'http://schemas.openxmlformats.org/presentationml/2006/main'
|
|
60
|
+
}
|
|
61
|
+
advance_after = 33 # msec
|
|
62
|
+
duration = 10 # msec
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
pattern = re.compile(r'\d+.*\.png$')
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
filelist = natsort.natsorted(os.listdir(folder_path))
|
|
69
|
+
# imgfiles = [f for f in dirfiles if f.lower().endswith(('.png', '.jpg', '.jpeg', 'bmp', '.tiff'))]
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
# Loop through each file in the folder
|
|
73
|
+
cnt = 0
|
|
74
|
+
for file_name in filelist:
|
|
75
|
+
if pattern.match(file_name):
|
|
76
|
+
print(file_name)
|
|
77
|
+
# if cnt > 10: break
|
|
78
|
+
|
|
79
|
+
if edit_existing:
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
slide = prs.slides[cnt]
|
|
83
|
+
|
|
84
|
+
shapes_to_remove = []
|
|
85
|
+
|
|
86
|
+
for shape in slide.shapes:
|
|
87
|
+
# if shape.shape_type == MSO_SHAPE_TYPE.AUTO_SHAPE:
|
|
88
|
+
# print(' - AutoShape.')
|
|
89
|
+
# elif shape.shape_type == MSO_SHAPE_TYPE.CHART:
|
|
90
|
+
# print(' - Chart.')
|
|
91
|
+
# elif shape.shape_type == MSO_SHAPE_TYPE.FREEFORM:
|
|
92
|
+
# print(' - Freeform.')
|
|
93
|
+
# elif shape.shape_type == MSO_SHAPE_TYPE.GROUP:
|
|
94
|
+
# print(' - Group.')
|
|
95
|
+
# elif shape.shape_type == MSO_SHAPE_TYPE.PICTURE:
|
|
96
|
+
# print(' - Picture.')
|
|
97
|
+
# elif shape.shape_type == MSO_SHAPE_TYPE.PLACEHOLDER:
|
|
98
|
+
# print(' - Placeholder.')
|
|
99
|
+
# elif shape.shape_type == MSO_SHAPE_TYPE.TABLE:
|
|
100
|
+
# print(' - Table.')
|
|
101
|
+
# elif shape.shape_type == MSO_SHAPE_TYPE.TEXT_BOX:
|
|
102
|
+
# print(' - Text Box.')
|
|
103
|
+
# else:
|
|
104
|
+
# print(' - This is another type of shape.')
|
|
105
|
+
|
|
106
|
+
# print(shape.shape_type.value)
|
|
107
|
+
if shape.shape_type == 13:
|
|
108
|
+
shapes_to_remove.append(shape)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
for shape in shapes_to_remove:
|
|
114
|
+
sp = shape._element
|
|
115
|
+
sp.getparent().remove(sp)
|
|
116
|
+
# if shape.shape_type == MSO_SHAPE_TYPE.AUTO_SHAPE:
|
|
117
|
+
# print(' - AutoShape removed.')
|
|
118
|
+
# elif shape.shape_type == MSO_SHAPE_TYPE.CHART:
|
|
119
|
+
# print(' - Chart removed.')
|
|
120
|
+
# elif shape.shape_type == MSO_SHAPE_TYPE.FREEFORM:
|
|
121
|
+
# print(' - Freeform removed.')
|
|
122
|
+
# elif shape.shape_type == MSO_SHAPE_TYPE.GROUP:
|
|
123
|
+
# print(' - Group removed.')
|
|
124
|
+
# elif shape.shape_type == MSO_SHAPE_TYPE.PICTURE:
|
|
125
|
+
# print(' - Picture removed.')
|
|
126
|
+
# elif shape.shape_type == MSO_SHAPE_TYPE.PLACEHOLDER:
|
|
127
|
+
# print(' - Placeholder removed.')
|
|
128
|
+
# elif shape.shape_type == MSO_SHAPE_TYPE.TABLE:
|
|
129
|
+
# print(' - Table removed.')
|
|
130
|
+
# elif shape.shape_type == MSO_SHAPE_TYPE.TEXT_BOX:
|
|
131
|
+
# print(' - Text Box removed.')
|
|
132
|
+
# else:
|
|
133
|
+
# print(' - a shape removed')
|
|
134
|
+
# print(shape.shape_type.value, end = '')
|
|
135
|
+
# print('removed')
|
|
136
|
+
|
|
137
|
+
else:
|
|
138
|
+
# Add a slide
|
|
139
|
+
slide = prs.slides.add_slide(prs.slide_layouts[6])
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
# Define the path to the image file
|
|
143
|
+
img_path = os.path.join(folder_path, file_name)
|
|
144
|
+
# Add the image to the slide
|
|
145
|
+
picture = slide.shapes.add_picture(img_path, Inches(0), Inches(0), width=prs.slide_width, height=prs.slide_height)
|
|
146
|
+
# slide.shapes._spTree.remove(picture._element) # Temporarily remove the picture element
|
|
147
|
+
slide.shapes._spTree.insert(2, picture._element) # Re-insert it at the back
|
|
148
|
+
|
|
149
|
+
# set_slide_timing(slide, duration=0.01, advance_after=0.03)
|
|
150
|
+
# Namespaces required for the XML elements
|
|
151
|
+
|
|
152
|
+
# Access the slide's XML
|
|
153
|
+
slide_xml = slide._element
|
|
154
|
+
|
|
155
|
+
# Create timing and transition elements
|
|
156
|
+
timing = etree.SubElement(slide_xml, '{http://schemas.openxmlformats.org/presentationml/2006/main}timing')
|
|
157
|
+
|
|
158
|
+
# Duration of the transition (in milliseconds)
|
|
159
|
+
transition = etree.SubElement(slide_xml, '{http://schemas.openxmlformats.org/presentationml/2006/main}transition')
|
|
160
|
+
transition.set('dur', str(int(duration * 1000)))
|
|
161
|
+
|
|
162
|
+
# Set advance timing (in milliseconds)
|
|
163
|
+
advance = etree.SubElement(timing, '{http://schemas.openxmlformats.org/presentationml/2006/main}advAfter')
|
|
164
|
+
advance.text = str(int(advance_after * 1000))
|
|
165
|
+
|
|
166
|
+
cnt += 1
|
|
167
|
+
|
|
168
|
+
# Save the presentation
|
|
169
|
+
outfile = pptfile if pptfile else os.path.join(folder_path, os.path.basename(folder_path) + '.pptx')
|
|
170
|
+
try:
|
|
171
|
+
prs.save(outfile)
|
|
172
|
+
print('saved ' + outfile)
|
|
173
|
+
except PermissionError:
|
|
174
|
+
prs.save(outfile[:-5] + '_v1' + '.pptx')
|
|
175
|
+
print('saved ' + outfile[:-5] + '_v1' + '.pptx')
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
if delimages:
|
|
179
|
+
for file_name in filelist:
|
|
180
|
+
if pattern.match(file_name):
|
|
181
|
+
os.remove(os.path.join(folder_path, file_name))
|
|
182
|
+
|