dynamo-figures 0.3.2__tar.gz

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 (26) hide show
  1. dynamo_figures-0.3.2/PKG-INFO +139 -0
  2. dynamo_figures-0.3.2/README.md +116 -0
  3. dynamo_figures-0.3.2/pyproject.toml +48 -0
  4. dynamo_figures-0.3.2/setup.cfg +4 -0
  5. dynamo_figures-0.3.2/src/dynamo_figures/__init__.py +13 -0
  6. dynamo_figures-0.3.2/src/dynamo_figures/__main__.py +6 -0
  7. dynamo_figures-0.3.2/src/dynamo_figures/blur_faces/__init__.py +18 -0
  8. dynamo_figures-0.3.2/src/dynamo_figures/blur_faces/__main__.py +6 -0
  9. dynamo_figures-0.3.2/src/dynamo_figures/blur_faces/cli.py +150 -0
  10. dynamo_figures-0.3.2/src/dynamo_figures/blur_faces/core.py +277 -0
  11. dynamo_figures-0.3.2/src/dynamo_figures/blur_faces/detectors.py +220 -0
  12. dynamo_figures-0.3.2/src/dynamo_figures/blur_faces/models/face_detection_yunet_2023mar.onnx +0 -0
  13. dynamo_figures-0.3.2/src/dynamo_figures/blur_faces/obscure.py +115 -0
  14. dynamo_figures-0.3.2/src/dynamo_figures/blur_faces/tracking.py +125 -0
  15. dynamo_figures-0.3.2/src/dynamo_figures/blur_faces/video_io.py +153 -0
  16. dynamo_figures-0.3.2/src/dynamo_figures/composite_image.py +233 -0
  17. dynamo_figures-0.3.2/src/dynamo_figures/pic_from_video.py +217 -0
  18. dynamo_figures-0.3.2/src/dynamo_figures/qr_code.py +349 -0
  19. dynamo_figures-0.3.2/src/dynamo_figures/tex2img.py +409 -0
  20. dynamo_figures-0.3.2/src/dynamo_figures/video_to_gif.py +453 -0
  21. dynamo_figures-0.3.2/src/dynamo_figures.egg-info/PKG-INFO +139 -0
  22. dynamo_figures-0.3.2/src/dynamo_figures.egg-info/SOURCES.txt +24 -0
  23. dynamo_figures-0.3.2/src/dynamo_figures.egg-info/dependency_links.txt +1 -0
  24. dynamo_figures-0.3.2/src/dynamo_figures.egg-info/entry_points.txt +7 -0
  25. dynamo_figures-0.3.2/src/dynamo_figures.egg-info/requires.txt +21 -0
  26. dynamo_figures-0.3.2/src/dynamo_figures.egg-info/top_level.txt +1 -0
@@ -0,0 +1,139 @@
1
+ Metadata-Version: 2.4
2
+ Name: dynamo-figures
3
+ Version: 0.3.2
4
+ Summary: A Python package for figure generation
5
+ Author: Dynamic Mobility Lab at Georgia Tech
6
+ Author-email: Neil Janwani <njanwani@gatech.edu>
7
+ Requires-Python: >=3.8
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: opencv-python>=4.0.0
10
+ Requires-Dist: numpy>=1.20.0
11
+ Requires-Dist: tqdm>=4.0.0
12
+ Requires-Dist: Pillow>=8.0.0
13
+ Requires-Dist: qrcode>=7.0.0
14
+ Provides-Extra: gpu
15
+ Requires-Dist: onnxruntime>=1.17; sys_platform == "darwin" and extra == "gpu"
16
+ Requires-Dist: onnxruntime-gpu[cuda,cudnn]>=1.21; sys_platform != "darwin" and extra == "gpu"
17
+ Provides-Extra: svg
18
+ Requires-Dist: cairosvg>=2.5.0; extra == "svg"
19
+ Provides-Extra: dev
20
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
21
+ Requires-Dist: black>=22.0.0; extra == "dev"
22
+ Requires-Dist: flake8>=4.0.0; extra == "dev"
23
+
24
+ # Dynamo Figures
25
+
26
+ A Python package for creating composite images from videos. This tool extracts frames from a video and merges them using various composition modes to create stunning visual effects.
27
+
28
+ ## Installation
29
+
30
+ ### Install from Git
31
+ ```bash
32
+ # Install directly from GitHub
33
+ pip install git+ssh://git@github.com/dynamicmobility/dynamo_figures.git
34
+ ```
35
+
36
+ ### Install from Local Directory
37
+ ```bash
38
+ # From within the project directory
39
+ git clone git@github.com:dynamicmobility/dynamo_figures.git
40
+ cd dynamo_figures
41
+ pip install -e .
42
+ ```
43
+
44
+ ## Usage
45
+
46
+ ### Command-Line Interface
47
+
48
+ After installation, you can use the `dynamo-composite-image` command:
49
+
50
+ #### 1. VAR Mode (Recommended)
51
+ Uses pixels that are furthest from the mean of the image, creating dynamic composite effects.
52
+
53
+ ```bash
54
+ dynamo-composite-image --video_path ./example/video.mp4 --start_t 0.0 --end_t 99.0 --skip_frame 2 --mode VAR --alpha 0.4 --output ./example/composite.png
55
+ ```
56
+ ![image-20230909002327059](./example/image-20230909002327059.png)
57
+
58
+ #### 2. MIN Mode
59
+ Keeps the darkest pixels from all frames.
60
+
61
+ ```bash
62
+ dynamo-composite-image --video_path ./example/video.mp4 --start_t 0.0 --end_t 99.0 --skip_frame 2 --mode MIN --output ./example/composite.png
63
+ ```
64
+ ![image-20230909002235029](./example/image-20230909002235029.png)
65
+
66
+ #### 3. MAX Mode
67
+ Keeps the lightest pixels from all frames.
68
+
69
+ ```bash
70
+ dynamo-composite-image --video_path ./example/video.mp4 --start_t 0.0 --end_t 99.0 --skip_frame 2 --mode MAX --output ./example/composite.png
71
+ ```
72
+ ![image-20230909002149494](./example/image-20230909002149494.png)
73
+
74
+ ### Python API
75
+
76
+ You can also use the package programmatically in your Python scripts:
77
+
78
+ ```python
79
+ from dynamo_figures import CompositeImage, CompositeMode
80
+ import cv2
81
+
82
+ # Create a composite image with VAR mode
83
+ merger = CompositeImage(
84
+ mode=CompositeMode.MAX_VARIATION,
85
+ video_path="./example/video.mp4",
86
+ start_t=0.0,
87
+ end_t=99.0,
88
+ skip_frame=2,
89
+ alpha=0.4,
90
+ disable_pbar=False # Set to True to disable the progress bar
91
+ )
92
+
93
+ # Generate the composite
94
+ result = merger.merge_images()
95
+
96
+ # Save the result
97
+ cv2.imwrite("output.jpg", result)
98
+ ```
99
+
100
+ ### Alternative Command-Line Methods
101
+
102
+ If you haven't installed the package, you can still run it:
103
+
104
+ ```bash
105
+ # Run as a Python module
106
+ python -m dynamo_figures.composite_image --video_path ./example_video.mp4 --mode VAR
107
+
108
+ # Or run directly
109
+ python src/dynamo_figures/composite_image.py --video_path ./example_video.mp4 --mode VAR
110
+ ```
111
+
112
+ ## Parameters
113
+
114
+ * `--video_path` (required): Path to the input video file
115
+ * `--start_t`: Start time in seconds (default: 0)
116
+ * `--end_t`: End time in seconds (default: 999999)
117
+ * `--skip_frame`: Number of frames to skip when extracting frames. Use `1` to process every frame (default: 1)
118
+ * `--mode`: Composition mode, three options available:
119
+ * `VAR` (Recommended): Uses pixels furthest from the mean, creating dynamic variation effects
120
+ * `MAX`: Keeps the lightest pixels across all frames
121
+ * `MIN`: Keeps the darkest pixels across all frames
122
+ * `--alpha`: Alpha blending factor for intermediate frames, range 0.0-1.0 (default: 0.5)
123
+ * `--disable_pbar`: Disable the progress bar when merging images (flag, no value needed)
124
+ * `--output`: Custom output file path (default: saves as `<video_name>.jpg` in the same directory as the input video)
125
+
126
+ ## Dependencies
127
+
128
+ - Python >= 3.8
129
+ - opencv-python >= 4.0.0
130
+ - numpy >= 1.20.0
131
+ - tqdm >= 4.0.0
132
+
133
+ ## License
134
+
135
+ All Rights Reserved 2023
136
+
137
+ ## Credits
138
+
139
+ Original Author: renyunfan (renyf@connect.hku.hk)
@@ -0,0 +1,116 @@
1
+ # Dynamo Figures
2
+
3
+ A Python package for creating composite images from videos. This tool extracts frames from a video and merges them using various composition modes to create stunning visual effects.
4
+
5
+ ## Installation
6
+
7
+ ### Install from Git
8
+ ```bash
9
+ # Install directly from GitHub
10
+ pip install git+ssh://git@github.com/dynamicmobility/dynamo_figures.git
11
+ ```
12
+
13
+ ### Install from Local Directory
14
+ ```bash
15
+ # From within the project directory
16
+ git clone git@github.com:dynamicmobility/dynamo_figures.git
17
+ cd dynamo_figures
18
+ pip install -e .
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ ### Command-Line Interface
24
+
25
+ After installation, you can use the `dynamo-composite-image` command:
26
+
27
+ #### 1. VAR Mode (Recommended)
28
+ Uses pixels that are furthest from the mean of the image, creating dynamic composite effects.
29
+
30
+ ```bash
31
+ dynamo-composite-image --video_path ./example/video.mp4 --start_t 0.0 --end_t 99.0 --skip_frame 2 --mode VAR --alpha 0.4 --output ./example/composite.png
32
+ ```
33
+ ![image-20230909002327059](./example/image-20230909002327059.png)
34
+
35
+ #### 2. MIN Mode
36
+ Keeps the darkest pixels from all frames.
37
+
38
+ ```bash
39
+ dynamo-composite-image --video_path ./example/video.mp4 --start_t 0.0 --end_t 99.0 --skip_frame 2 --mode MIN --output ./example/composite.png
40
+ ```
41
+ ![image-20230909002235029](./example/image-20230909002235029.png)
42
+
43
+ #### 3. MAX Mode
44
+ Keeps the lightest pixels from all frames.
45
+
46
+ ```bash
47
+ dynamo-composite-image --video_path ./example/video.mp4 --start_t 0.0 --end_t 99.0 --skip_frame 2 --mode MAX --output ./example/composite.png
48
+ ```
49
+ ![image-20230909002149494](./example/image-20230909002149494.png)
50
+
51
+ ### Python API
52
+
53
+ You can also use the package programmatically in your Python scripts:
54
+
55
+ ```python
56
+ from dynamo_figures import CompositeImage, CompositeMode
57
+ import cv2
58
+
59
+ # Create a composite image with VAR mode
60
+ merger = CompositeImage(
61
+ mode=CompositeMode.MAX_VARIATION,
62
+ video_path="./example/video.mp4",
63
+ start_t=0.0,
64
+ end_t=99.0,
65
+ skip_frame=2,
66
+ alpha=0.4,
67
+ disable_pbar=False # Set to True to disable the progress bar
68
+ )
69
+
70
+ # Generate the composite
71
+ result = merger.merge_images()
72
+
73
+ # Save the result
74
+ cv2.imwrite("output.jpg", result)
75
+ ```
76
+
77
+ ### Alternative Command-Line Methods
78
+
79
+ If you haven't installed the package, you can still run it:
80
+
81
+ ```bash
82
+ # Run as a Python module
83
+ python -m dynamo_figures.composite_image --video_path ./example_video.mp4 --mode VAR
84
+
85
+ # Or run directly
86
+ python src/dynamo_figures/composite_image.py --video_path ./example_video.mp4 --mode VAR
87
+ ```
88
+
89
+ ## Parameters
90
+
91
+ * `--video_path` (required): Path to the input video file
92
+ * `--start_t`: Start time in seconds (default: 0)
93
+ * `--end_t`: End time in seconds (default: 999999)
94
+ * `--skip_frame`: Number of frames to skip when extracting frames. Use `1` to process every frame (default: 1)
95
+ * `--mode`: Composition mode, three options available:
96
+ * `VAR` (Recommended): Uses pixels furthest from the mean, creating dynamic variation effects
97
+ * `MAX`: Keeps the lightest pixels across all frames
98
+ * `MIN`: Keeps the darkest pixels across all frames
99
+ * `--alpha`: Alpha blending factor for intermediate frames, range 0.0-1.0 (default: 0.5)
100
+ * `--disable_pbar`: Disable the progress bar when merging images (flag, no value needed)
101
+ * `--output`: Custom output file path (default: saves as `<video_name>.jpg` in the same directory as the input video)
102
+
103
+ ## Dependencies
104
+
105
+ - Python >= 3.8
106
+ - opencv-python >= 4.0.0
107
+ - numpy >= 1.20.0
108
+ - tqdm >= 4.0.0
109
+
110
+ ## License
111
+
112
+ All Rights Reserved 2023
113
+
114
+ ## Credits
115
+
116
+ Original Author: renyunfan (renyf@connect.hku.hk)
@@ -0,0 +1,48 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "dynamo-figures"
7
+ version = "0.3.2"
8
+ authors = [
9
+ { name="Dynamic Mobility Lab at Georgia Tech" },
10
+ { name="Neil Janwani", email="njanwani@gatech.edu" },
11
+ ]
12
+ description = "A Python package for figure generation"
13
+ readme = "README.md"
14
+ requires-python = ">=3.8"
15
+ dependencies = [
16
+ "opencv-python>=4.0.0",
17
+ "numpy>=1.20.0",
18
+ "tqdm>=4.0.0",
19
+ "Pillow>=8.0.0",
20
+ "qrcode>=7.0.0",
21
+ ]
22
+ [project.scripts]
23
+ dynamo-composite-image = "dynamo_figures.composite_image:main"
24
+ dynamo-pic-from-video = "dynamo_figures.pic_from_video:main"
25
+ dynamo-video-to-gif = "dynamo_figures.video_to_gif:main"
26
+ dynamo-qr-code = "dynamo_figures.qr_code:main"
27
+ dynamo-blur-faces = "dynamo_figures.blur_faces.cli:main"
28
+ dynamo-tex2img = "dynamo_figures.tex2img:main"
29
+
30
+ [project.optional-dependencies]
31
+ gpu = [
32
+ "onnxruntime>=1.17; sys_platform == 'darwin'",
33
+ "onnxruntime-gpu[cuda,cudnn]>=1.21; sys_platform != 'darwin'",
34
+ ]
35
+ svg = [
36
+ "cairosvg>=2.5.0",
37
+ ]
38
+ dev = [
39
+ "pytest>=7.0.0",
40
+ "black>=22.0.0",
41
+ "flake8>=4.0.0",
42
+ ]
43
+
44
+ [tool.setuptools.package-data]
45
+ dynamo_figures = ["blur_faces/models/*.onnx"]
46
+
47
+ [tool.setuptools.packages.find]
48
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,13 @@
1
+ """
2
+ dynamo_figures - A Python package for dynamic figure generation
3
+ """
4
+
5
+ __version__ = "0.3.2"
6
+
7
+ from dynamo_figures.composite_image import CompositeImage, CompositeMode
8
+ from dynamo_figures.video_to_gif import VideoToGif
9
+ from dynamo_figures.qr_code import QRCode
10
+ from dynamo_figures.blur_faces import FaceBlur
11
+ from dynamo_figures.tex2img import TexToImage
12
+
13
+ __all__ = ["CompositeImage", "CompositeMode", "VideoToGif", "QRCode", "FaceBlur", "TexToImage", "__version__"]
@@ -0,0 +1,6 @@
1
+ """Entry point for running composite_image as a module."""
2
+
3
+ from dynamo_figures.composite_image import main
4
+
5
+ if __name__ == "__main__":
6
+ main()
@@ -0,0 +1,18 @@
1
+ """
2
+ Package: dynamo_figures.blur_faces
3
+ Description: Anonymize faces in photos and videos, fully locally.
4
+
5
+ Modules:
6
+ core FaceBlur, the high-level image/video API
7
+ detectors YuNet detection on CPU (OpenCV) or GPU (ONNX Runtime)
8
+ tracking Frame-to-frame box smoothing and hold for videos
9
+ obscure Blur / pixelate / fill rendering
10
+ video_io Threaded frame reading and ffmpeg encoding
11
+ cli The dynamo-blur-faces command-line tool
12
+ """
13
+
14
+ from dynamo_figures.blur_faces.core import FaceBlur
15
+ from dynamo_figures.blur_faces.detectors import gpu_provider
16
+ from dynamo_figures.blur_faces.tracking import FaceTracker
17
+
18
+ __all__ = ["FaceBlur", "FaceTracker", "gpu_provider"]
@@ -0,0 +1,6 @@
1
+ """Entry point for running blur_faces as a module: python -m dynamo_figures.blur_faces"""
2
+
3
+ from dynamo_figures.blur_faces.cli import main
4
+
5
+ if __name__ == "__main__":
6
+ main()
@@ -0,0 +1,150 @@
1
+ """
2
+ File: cli.py
3
+ Description: Command-line interface for the dynamo-blur-faces tool.
4
+ Blurs, pixelates, or covers faces in a photo or video, fully locally.
5
+ """
6
+
7
+ import argparse
8
+ import sys
9
+ from pathlib import Path
10
+
11
+ from dynamo_figures.blur_faces.core import FaceBlur
12
+
13
+ IMAGE_EXTENSIONS = {'.jpg', '.jpeg', '.png', '.bmp', '.tif', '.tiff', '.webp'}
14
+ VIDEO_EXTENSIONS = {'.mp4', '.mov', '.avi', '.mkv', '.m4v', '.webm', '.wmv'}
15
+
16
+
17
+ def main():
18
+ """Main function for command-line interface."""
19
+ parser = argparse.ArgumentParser(
20
+ prog='dynamo-blur-faces',
21
+ description='Blur, pixelate, or cover faces in a photo or video. Runs fully locally.',
22
+ epilog='-'
23
+ )
24
+ parser.add_argument('--input', type=str, required=True,
25
+ help='path of input image or video file.')
26
+ parser.add_argument('--output', type=str, default=None,
27
+ help='output file path (default: same directory as input with _blurred suffix)')
28
+ parser.add_argument('--style', default='blur', choices=FaceBlur.STYLES,
29
+ help='how to obscure faces (default: blur)')
30
+ parser.add_argument('--shape', default='ellipse', choices=FaceBlur.SHAPES,
31
+ help='shape of the obscured region (default: ellipse)')
32
+ parser.add_argument('--padding', type=float, default=0.25,
33
+ help='fraction to enlarge each face box on every side (default: 0.25)')
34
+ parser.add_argument('--blur_strength', type=float, default=0.5,
35
+ help='blur kernel size as a fraction of face size, for --style blur (default: 0.5)')
36
+ parser.add_argument('--pixel_blocks', type=int, default=10,
37
+ help='number of mosaic blocks across each face, for --style pixelate (default: 10)')
38
+ parser.add_argument('--fill_color', type=str, default='black',
39
+ help='color name or hex code, for --style fill (default: black)')
40
+ parser.add_argument('--score_threshold', type=float, default=0.6,
41
+ help='minimum detection confidence 0..1; lower catches more faces but more false positives (default: 0.6)')
42
+ parser.add_argument('--nms_threshold', type=float, default=0.3,
43
+ help='overlap threshold for merging duplicate detections (default: 0.3)')
44
+ parser.add_argument('--detect_max_dim', type=int, default=2048,
45
+ help='downscale so the longest side is at most this before detection; '
46
+ 'raise for tiny faces, lower for speed, 0 = full resolution (default: 2048)')
47
+ parser.add_argument('--device', default='auto', choices=FaceBlur.DEVICES,
48
+ help='detection device: gpu needs onnxruntime (CoreML) or onnxruntime-gpu (CUDA); '
49
+ 'auto uses the GPU when available (default: auto)')
50
+ parser.add_argument('--batch_size', type=int, default=8,
51
+ help='video only: frames detected per batch (default: 8)')
52
+ parser.add_argument('--workers', type=int, default=None,
53
+ help='video only: CPU threads for detection/blurring (default: number of cores)')
54
+ parser.add_argument('--hold_frames', type=int, default=5,
55
+ help='video only: keep obscuring a face for this many frames after it is lost (default: 5)')
56
+ parser.add_argument('--smoothing', type=float, default=0.5,
57
+ help='video only: box smoothing between frames, 0..1 (0 = off; higher is steadier '
58
+ 'but lags; the raw detection is always covered) (default: 0.5)')
59
+ parser.add_argument('--start_t', type=float, default=None,
60
+ help='video only: trim the output to start this many seconds into the input '
61
+ '(default: start of video)')
62
+ parser.add_argument('--end_t', type=float, default=None,
63
+ help='video only: trim the output to end this many seconds into the input '
64
+ '(default: end of video)')
65
+ parser.add_argument('--no_audio', action='store_true',
66
+ help='video only: drop the audio track')
67
+ parser.add_argument('--crf', type=int, default=18,
68
+ help='video only: H.264 quality, lower is better (default: 18)')
69
+ parser.add_argument('--draw_boxes', action='store_true',
70
+ help='draw detection boxes and scores instead of obscuring (for tuning)')
71
+ parser.add_argument('--disable_pbar', action='store_true',
72
+ help='disable progress bar when processing videos')
73
+
74
+ args = parser.parse_args()
75
+
76
+ input_path = Path(args.input)
77
+ if not input_path.exists():
78
+ print(f"Error: Input file '{input_path}' not found.")
79
+ sys.exit(1)
80
+
81
+ ext = input_path.suffix.lower()
82
+ if ext in IMAGE_EXTENSIONS:
83
+ is_video = False
84
+ elif ext in VIDEO_EXTENSIONS:
85
+ is_video = True
86
+ else:
87
+ print(f"Error: Unsupported file type '{ext}'.")
88
+ sys.exit(1)
89
+
90
+ if args.output:
91
+ output_path = args.output
92
+ else:
93
+ out_ext = '.mp4' if is_video else ext
94
+ output_path = str(input_path.parent / f'{input_path.stem}_blurred{out_ext}')
95
+
96
+ print(" -- Load Param: input", input_path)
97
+ print(" -- Load Param: output", output_path)
98
+ print(" -- Load Param: style", args.style)
99
+ print(" -- Load Param: shape", args.shape)
100
+ print(" -- Load Param: score_threshold", args.score_threshold)
101
+ print(" -- Load Param: device", args.device)
102
+
103
+ if not 0 <= args.smoothing < 1:
104
+ print("Error: --smoothing must be in [0, 1).")
105
+ sys.exit(1)
106
+
107
+ if not is_video and (args.start_t is not None or args.end_t is not None):
108
+ print("Error: --start_t/--end_t only apply to videos.")
109
+ sys.exit(1)
110
+
111
+ if args.start_t is not None and args.start_t < 0:
112
+ print("Error: --start_t must be >= 0.")
113
+ sys.exit(1)
114
+
115
+ if args.end_t is not None and args.end_t <= (args.start_t or 0.0):
116
+ print("Error: --end_t must be greater than --start_t.")
117
+ sys.exit(1)
118
+
119
+ blurrer = FaceBlur(
120
+ style=args.style,
121
+ shape=args.shape,
122
+ padding=args.padding,
123
+ score_threshold=args.score_threshold,
124
+ nms_threshold=args.nms_threshold,
125
+ detect_max_dim=args.detect_max_dim,
126
+ blur_strength=args.blur_strength,
127
+ pixel_blocks=args.pixel_blocks,
128
+ fill_color=args.fill_color,
129
+ hold_frames=args.hold_frames,
130
+ smoothing=args.smoothing,
131
+ draw_boxes=args.draw_boxes,
132
+ disable_pbar=args.disable_pbar,
133
+ device=args.device,
134
+ batch_size=args.batch_size,
135
+ workers=args.workers,
136
+ )
137
+
138
+ if is_video:
139
+ success = blurrer.process_video(str(input_path), output_path,
140
+ keep_audio=not args.no_audio, crf=args.crf,
141
+ start_t=args.start_t, end_t=args.end_t)
142
+ else:
143
+ success = blurrer.process_image(str(input_path), output_path)
144
+
145
+ if not success:
146
+ sys.exit(1)
147
+
148
+
149
+ if __name__ == "__main__":
150
+ main()