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.
Files changed (50) hide show
  1. c4dynamics/__init__.py +240 -0
  2. c4dynamics/datasets/__init__.py +95 -0
  3. c4dynamics/datasets/_manager.py +596 -0
  4. c4dynamics/datasets/_registry.py +80 -0
  5. c4dynamics/detectors/__init__.py +37 -0
  6. c4dynamics/detectors/yolo3_opencv.py +686 -0
  7. c4dynamics/detectors/yolo3_tf.py +124 -0
  8. c4dynamics/eqm/__init__.py +324 -0
  9. c4dynamics/eqm/derivs.py +212 -0
  10. c4dynamics/eqm/integrate.py +359 -0
  11. c4dynamics/filters/__init__.py +1373 -0
  12. c4dynamics/filters/a.py +48 -0
  13. c4dynamics/filters/ekf.py +320 -0
  14. c4dynamics/filters/kalman.py +725 -0
  15. c4dynamics/filters/kalman_v0.py +1071 -0
  16. c4dynamics/filters/kalman_v1.py +821 -0
  17. c4dynamics/filters/lowpass.py +123 -0
  18. c4dynamics/filters/luenberger.py +97 -0
  19. c4dynamics/rotmat/__init__.py +141 -0
  20. c4dynamics/rotmat/animate.py +465 -0
  21. c4dynamics/rotmat/rotmat.py +351 -0
  22. c4dynamics/sensors/__init__.py +72 -0
  23. c4dynamics/sensors/lineofsight.py +78 -0
  24. c4dynamics/sensors/radar.py +740 -0
  25. c4dynamics/sensors/seeker.py +1030 -0
  26. c4dynamics/states/__init__.py +327 -0
  27. c4dynamics/states/lib/__init__.py +320 -0
  28. c4dynamics/states/lib/datapoint.py +660 -0
  29. c4dynamics/states/lib/pixelpoint.py +776 -0
  30. c4dynamics/states/lib/rigidbody.py +677 -0
  31. c4dynamics/states/state.py +1486 -0
  32. c4dynamics/utils/__init__.py +44 -0
  33. c4dynamics/utils/_struct.py +6 -0
  34. c4dynamics/utils/const.py +130 -0
  35. c4dynamics/utils/cprint.py +80 -0
  36. c4dynamics/utils/gen_gif.py +142 -0
  37. c4dynamics/utils/idx2keys.py +4 -0
  38. c4dynamics/utils/images_loader.py +63 -0
  39. c4dynamics/utils/math.py +136 -0
  40. c4dynamics/utils/plottools.py +140 -0
  41. c4dynamics/utils/plottracks.py +304 -0
  42. c4dynamics/utils/printpts.py +36 -0
  43. c4dynamics/utils/slides_gen.py +64 -0
  44. c4dynamics/utils/tictoc.py +167 -0
  45. c4dynamics/utils/video_gen.py +300 -0
  46. c4dynamics/utils/vidgen.py +182 -0
  47. c4dynamics-2.0.3.dist-info/METADATA +242 -0
  48. c4dynamics-2.0.3.dist-info/RECORD +50 -0
  49. c4dynamics-2.0.3.dist-info/WHEEL +5 -0
  50. 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
+