simba-uw-tf-dev 4.7.5__py3-none-any.whl → 4.7.6__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.
- simba/assets/.recent_projects.txt +1 -0
- simba/mixins/feature_extraction_mixin.py +0 -2
- simba/sandbox/av1.py +5 -0
- simba/sandbox/denoise_hqdn3d.py +266 -0
- simba/sandbox/extract_random_frames.py +126 -0
- simba/ui/pop_ups/video_processing_pop_up.py +1 -1
- simba/video_processors/video_processing.py +20 -13
- {simba_uw_tf_dev-4.7.5.dist-info → simba_uw_tf_dev-4.7.6.dist-info}/METADATA +1 -1
- {simba_uw_tf_dev-4.7.5.dist-info → simba_uw_tf_dev-4.7.6.dist-info}/RECORD +13 -10
- {simba_uw_tf_dev-4.7.5.dist-info → simba_uw_tf_dev-4.7.6.dist-info}/LICENSE +0 -0
- {simba_uw_tf_dev-4.7.5.dist-info → simba_uw_tf_dev-4.7.6.dist-info}/WHEEL +0 -0
- {simba_uw_tf_dev-4.7.5.dist-info → simba_uw_tf_dev-4.7.6.dist-info}/entry_points.txt +0 -0
- {simba_uw_tf_dev-4.7.5.dist-info → simba_uw_tf_dev-4.7.6.dist-info}/top_level.txt +0 -0
simba/sandbox/av1.py
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Function to apply hqdn3d (high-quality denoise 3D) filter to a video file using ffmpeg.
|
|
3
|
+
|
|
4
|
+
The hqdn3d filter is a spatial-temporal denoise filter that reduces noise while preserving
|
|
5
|
+
video quality and details.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
import subprocess
|
|
10
|
+
from typing import Union, Optional
|
|
11
|
+
|
|
12
|
+
from simba.utils.checks import (
|
|
13
|
+
check_ffmpeg_available,
|
|
14
|
+
check_file_exist_and_readable,
|
|
15
|
+
check_if_dir_exists,
|
|
16
|
+
check_nvidea_gpu_available
|
|
17
|
+
)
|
|
18
|
+
from simba.utils.errors import FFMPEGCodecGPUError
|
|
19
|
+
from simba.utils.printing import SimbaTimer, stdout_success
|
|
20
|
+
from simba.utils.read_write import get_fn_ext
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def denoise_bm3d(file_path: Union[str, os.PathLike],
|
|
24
|
+
save_path: Optional[Union[str, os.PathLike]] = None,
|
|
25
|
+
gpu: Optional[bool] = False,
|
|
26
|
+
quality: int = 60,
|
|
27
|
+
sigma: Optional[float] = None,
|
|
28
|
+
block: Optional[int] = None,
|
|
29
|
+
bstep: Optional[int] = None,
|
|
30
|
+
group: Optional[int] = None) -> None:
|
|
31
|
+
"""
|
|
32
|
+
Apply bm3d (Block-Matching 3D) denoise filter to a video file.
|
|
33
|
+
|
|
34
|
+
BM3D is a more advanced denoising algorithm than hqdn3d, often better at removing texture
|
|
35
|
+
and background noise while preserving details. It's slower but produces better results.
|
|
36
|
+
|
|
37
|
+
**For removing background texture (e.g., sawdust pellets):**
|
|
38
|
+
- **sigma** is MOST IMPORTANT - controls noise level/denoising strength (higher = more denoising)
|
|
39
|
+
- **block** - block size (default: 4, larger = more smoothing but slower)
|
|
40
|
+
- **bstep** - block step (default: 4, smaller = better quality but slower)
|
|
41
|
+
- **group** - group size (default: 1, larger = better denoising but slower)
|
|
42
|
+
|
|
43
|
+
:param Union[str, os.PathLike] file_path: Path to input video file.
|
|
44
|
+
:param Optional[Union[str, os.PathLike]] save_path: Optional save location for the denoised video. If None, then the new video is saved in the same directory as the input video with the ``_bm3d_denoised`` suffix.
|
|
45
|
+
:param Optional[bool] gpu: If True, use NVIDEA GPU codecs. Default False.
|
|
46
|
+
:param int quality: Video quality percentage (1-100). Higher values = higher quality. Default 60.
|
|
47
|
+
:param Optional[float] sigma: Noise level/denoising strength (default: 1.0). **MOST IMPORTANT** - higher values = more denoising. For background texture removal, try 5-20.
|
|
48
|
+
:param Optional[int] block: Block size (default: 4). Larger values = more smoothing but slower processing.
|
|
49
|
+
:param Optional[int] bstep: Block step (default: 4). Smaller values = better quality but slower.
|
|
50
|
+
:param Optional[int] group: Group size (default: 1). Larger values = better denoising but slower.
|
|
51
|
+
:returns: None. If save_path is not passed, the result is stored in the same directory as the input file with the ``_bm3d_denoised.mp4`` suffix.
|
|
52
|
+
|
|
53
|
+
.. note::
|
|
54
|
+
Codec is automatically selected: libx264 for CPU encoding (ignored if gpu=True).
|
|
55
|
+
BM3D is slower than hqdn3d but often produces better results for texture removal.
|
|
56
|
+
For background texture removal, start with sigma=10-15 and adjust from there.
|
|
57
|
+
|
|
58
|
+
:example:
|
|
59
|
+
>>> denoise_bm3d(file_path='project_folder/videos/Video_1.avi', sigma=10)
|
|
60
|
+
>>> denoise_bm3d(file_path='/Users/simon/Desktop/test/noisy_video.mp4', sigma=15, block=8, quality=80)
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
check_ffmpeg_available(raise_error=True)
|
|
64
|
+
if gpu and not check_nvidea_gpu_available():
|
|
65
|
+
raise FFMPEGCodecGPUError(
|
|
66
|
+
msg="No GPU found (as evaluated by nvidea-smi returning None)",
|
|
67
|
+
source=denoise_bm3d.__name__
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
timer = SimbaTimer(start=True)
|
|
71
|
+
check_file_exist_and_readable(file_path=file_path)
|
|
72
|
+
|
|
73
|
+
dir, file_name, ext = get_fn_ext(filepath=file_path)
|
|
74
|
+
|
|
75
|
+
if save_path is None:
|
|
76
|
+
save_name = os.path.join(dir, f"{file_name}_bm3d_denoised.mp4")
|
|
77
|
+
else:
|
|
78
|
+
check_if_dir_exists(
|
|
79
|
+
in_dir=os.path.dirname(save_path),
|
|
80
|
+
source=f'{denoise_bm3d.__name__} save_path',
|
|
81
|
+
create_if_not_exist=True
|
|
82
|
+
)
|
|
83
|
+
save_name = save_path
|
|
84
|
+
|
|
85
|
+
# Set default bm3d parameters if not provided
|
|
86
|
+
sigma_val = sigma if sigma is not None else 1.0
|
|
87
|
+
block_val = block if block is not None else 4
|
|
88
|
+
bstep_val = bstep if bstep is not None else 4
|
|
89
|
+
group_val = group if group is not None else 1
|
|
90
|
+
|
|
91
|
+
# Check if bm3d filter is available first (may not be compiled into all ffmpeg builds)
|
|
92
|
+
check_cmd = 'ffmpeg -filters 2>&1 | findstr /i "bm3d"'
|
|
93
|
+
result = subprocess.run(check_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
|
|
94
|
+
if not result.stdout.strip():
|
|
95
|
+
raise FFMPEGCodecGPUError(
|
|
96
|
+
msg="BM3D filter not available in your ffmpeg build. BM3D may not be compiled into your ffmpeg installation. Try using hqdn3d or nlmeans instead.",
|
|
97
|
+
source=denoise_bm3d.__name__
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
# Build bm3d filter string with named parameters
|
|
101
|
+
# Format: bm3d=sigma=value:block=value:bstep=value:group=value
|
|
102
|
+
filter_str = f'bm3d=sigma={sigma_val}:block={block_val}:bstep={bstep_val}:group={group_val}'
|
|
103
|
+
|
|
104
|
+
# Build ffmpeg command with bm3d filter
|
|
105
|
+
if gpu:
|
|
106
|
+
# GPU encoding with bm3d filter
|
|
107
|
+
from simba.utils.lookups import quality_pct_to_crf
|
|
108
|
+
quality_crf = quality_pct_to_crf(pct=int(quality))
|
|
109
|
+
cmd = f'ffmpeg -hwaccel auto -c:v h264_cuvid -i "{file_path}" -vf {filter_str} -rc vbr -cq {quality_crf} -c:v h264_nvenc -c:a copy "{save_name}" -loglevel error -stats -hide_banner -y'
|
|
110
|
+
else:
|
|
111
|
+
# CPU encoding with bm3d filter
|
|
112
|
+
from simba.utils.lookups import quality_pct_to_crf
|
|
113
|
+
quality_crf = quality_pct_to_crf(pct=int(quality))
|
|
114
|
+
cmd = f'ffmpeg -i "{file_path}" -vf {filter_str} -c:v libx264 -crf {quality_crf} -c:a copy "{save_name}" -loglevel error -stats -hide_banner -y'
|
|
115
|
+
|
|
116
|
+
print(f"Applying bm3d denoise filter (sigma={sigma_val}, block={block_val}, bstep={bstep_val}, group={group_val}) to {file_name}...")
|
|
117
|
+
print(f"Command: {cmd}")
|
|
118
|
+
|
|
119
|
+
process = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
|
|
120
|
+
if process.returncode != 0:
|
|
121
|
+
error_msg = process.stderr if process.stderr else (process.stdout if process.stdout else "Unknown error")
|
|
122
|
+
print(f"Error output: {error_msg}")
|
|
123
|
+
raise FFMPEGCodecGPUError(
|
|
124
|
+
msg=f"FFmpeg bm3d filter failed: {error_msg}",
|
|
125
|
+
source=denoise_bm3d.__name__
|
|
126
|
+
)
|
|
127
|
+
timer.stop_timer()
|
|
128
|
+
stdout_success(
|
|
129
|
+
msg=f"SIMBA COMPLETE: Video denoised with BM3D! {save_name} generated!",
|
|
130
|
+
elapsed_time=timer.elapsed_time_str,
|
|
131
|
+
source=denoise_bm3d.__name__
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def denoise_hqdn3d(file_path: Union[str, os.PathLike],
|
|
136
|
+
save_path: Optional[Union[str, os.PathLike]] = None,
|
|
137
|
+
gpu: Optional[bool] = False,
|
|
138
|
+
quality: int = 60,
|
|
139
|
+
luma_spatial: Optional[float] = None,
|
|
140
|
+
luma_temporal: Optional[float] = None,
|
|
141
|
+
chroma_spatial: Optional[float] = None,
|
|
142
|
+
chroma_temporal: Optional[float] = None) -> None:
|
|
143
|
+
"""
|
|
144
|
+
Apply hqdn3d (high-quality denoise 3D) filter to a video file.
|
|
145
|
+
|
|
146
|
+
The hqdn3d filter has 4 parameters that control denoising strength:
|
|
147
|
+
- Higher values = more denoising but may blur details
|
|
148
|
+
- Lower values = less denoising but preserves more detail
|
|
149
|
+
|
|
150
|
+
**For removing background texture (e.g., sawdust pellets):**
|
|
151
|
+
- **luma_spatial** and **chroma_spatial** are MOST IMPORTANT - these control spatial smoothing within each frame
|
|
152
|
+
- **luma_temporal** and **chroma_temporal** are less critical - these smooth across frames (helpful for motion noise, not static background)
|
|
153
|
+
- For background texture removal, focus on high spatial values (50-200+) and moderate temporal values (10-20)
|
|
154
|
+
|
|
155
|
+
.. note::
|
|
156
|
+
hqdn3d may not be ideal for removing static background texture. Consider background subtraction or blur filters instead.
|
|
157
|
+
For background texture removal, try: luma_spatial=100-200, chroma_spatial=100-200, luma_temporal=10-20, chroma_temporal=10-20
|
|
158
|
+
|
|
159
|
+
:param Union[str, os.PathLike] file_path: Path to input video file.
|
|
160
|
+
:param Optional[Union[str, os.PathLike]] save_path: Optional save location for the denoised video. If None, then the new video is saved in the same directory as the input video with the ``_denoised`` suffix.
|
|
161
|
+
:param Optional[bool] gpu: If True, use NVIDEA GPU codecs. Default False.
|
|
162
|
+
:param int quality: Video quality percentage (1-100). Higher values = higher quality. Default 60.
|
|
163
|
+
:param Optional[float] luma_spatial: Spatial luma strength (default: 4.0). Controls detail preservation in luma channel. **MOST IMPORTANT for background texture removal.**
|
|
164
|
+
:param Optional[float] luma_temporal: Temporal luma strength (default: 3.0). Controls motion blur artifacts in luma channel. Less critical for static background.
|
|
165
|
+
:param Optional[float] chroma_spatial: Spatial chroma strength (default: 3.0). Controls detail preservation in chroma channel. **MOST IMPORTANT for background texture removal.**
|
|
166
|
+
:param Optional[float] chroma_temporal: Temporal chroma strength (default: 6.0). Controls motion blur artifacts in chroma channel. Less critical for static background.
|
|
167
|
+
:returns: None. If save_path is not passed, the result is stored in the same directory as the input file with the ``_denoised.mp4`` suffix.
|
|
168
|
+
|
|
169
|
+
.. note::
|
|
170
|
+
Codec is automatically selected: libx264 for CPU encoding (ignored if gpu=True).
|
|
171
|
+
Default parameters are conservative. For stronger denoising, try: luma_spatial=8, luma_temporal=6, chroma_spatial=6, chroma_temporal=9
|
|
172
|
+
For very noisy videos, you may need values of 10-15 or higher.
|
|
173
|
+
|
|
174
|
+
:example:
|
|
175
|
+
>>> denoise_hqdn3d(file_path='project_folder/videos/Video_1.avi')
|
|
176
|
+
>>> denoise_hqdn3d(file_path='/Users/simon/Desktop/test/noisy_video.mp4', luma_spatial=8, luma_temporal=6, quality=80)
|
|
177
|
+
>>> # For removing background texture (sawdust pellets):
|
|
178
|
+
>>> denoise_hqdn3d(file_path='video.mp4', luma_spatial=150, chroma_spatial=150, luma_temporal=15, chroma_temporal=15)
|
|
179
|
+
"""
|
|
180
|
+
|
|
181
|
+
check_ffmpeg_available(raise_error=True)
|
|
182
|
+
if gpu and not check_nvidea_gpu_available():
|
|
183
|
+
raise FFMPEGCodecGPUError(
|
|
184
|
+
msg="No GPU found (as evaluated by nvidea-smi returning None)",
|
|
185
|
+
source=denoise_hqdn3d.__name__
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
timer = SimbaTimer(start=True)
|
|
189
|
+
check_file_exist_and_readable(file_path=file_path)
|
|
190
|
+
|
|
191
|
+
dir, file_name, ext = get_fn_ext(filepath=file_path)
|
|
192
|
+
|
|
193
|
+
if save_path is None:
|
|
194
|
+
save_name = os.path.join(dir, f"{file_name}_denoised.mp4")
|
|
195
|
+
else:
|
|
196
|
+
check_if_dir_exists(
|
|
197
|
+
in_dir=os.path.dirname(save_path),
|
|
198
|
+
source=f'{denoise_hqdn3d.__name__} save_path',
|
|
199
|
+
create_if_not_exist=True
|
|
200
|
+
)
|
|
201
|
+
save_name = save_path
|
|
202
|
+
|
|
203
|
+
# Set default hqdn3d parameters if not provided
|
|
204
|
+
luma_sp = luma_spatial if luma_spatial is not None else 4.0
|
|
205
|
+
luma_tmp = luma_temporal if luma_temporal is not None else 3.0
|
|
206
|
+
chroma_sp = chroma_spatial if chroma_spatial is not None else 3.0
|
|
207
|
+
chroma_tmp = chroma_temporal if chroma_temporal is not None else 6.0
|
|
208
|
+
|
|
209
|
+
# Build hqdn3d filter string with parameters
|
|
210
|
+
# Format: hqdn3d=luma_spatial:chroma_spatial:luma_temporal:chroma_temporal
|
|
211
|
+
filter_str = f'hqdn3d={luma_sp}:{chroma_sp}:{luma_tmp}:{chroma_tmp}'
|
|
212
|
+
|
|
213
|
+
# Build ffmpeg command with hqdn3d filter
|
|
214
|
+
if gpu:
|
|
215
|
+
# GPU encoding with hqdn3d filter
|
|
216
|
+
from simba.utils.lookups import quality_pct_to_crf
|
|
217
|
+
quality_crf = quality_pct_to_crf(pct=int(quality))
|
|
218
|
+
cmd = f'ffmpeg -hwaccel auto -c:v h264_cuvid -i "{file_path}" -vf {filter_str} -rc vbr -cq {quality_crf} -c:v h264_nvenc -c:a copy "{save_name}" -loglevel error -stats -hide_banner -y'
|
|
219
|
+
else:
|
|
220
|
+
# CPU encoding with hqdn3d filter
|
|
221
|
+
from simba.utils.lookups import quality_pct_to_crf
|
|
222
|
+
quality_crf = quality_pct_to_crf(pct=int(quality))
|
|
223
|
+
cmd = f'ffmpeg -i "{file_path}" -vf {filter_str} -c:v libx264 -crf {quality_crf} -c:a copy "{save_name}" -loglevel error -stats -hide_banner -y'
|
|
224
|
+
|
|
225
|
+
print(f"Applying hqdn3d denoise filter (luma_spatial={luma_sp}, chroma_spatial={chroma_sp}, luma_temporal={luma_tmp}, chroma_temporal={chroma_tmp}) to {file_name}...")
|
|
226
|
+
|
|
227
|
+
subprocess.call(cmd, shell=True, stdout=subprocess.PIPE)
|
|
228
|
+
timer.stop_timer()
|
|
229
|
+
stdout_success(
|
|
230
|
+
msg=f"SIMBA COMPLETE: Video denoised! {save_name} generated!",
|
|
231
|
+
elapsed_time=timer.elapsed_time_str,
|
|
232
|
+
source=denoise_hqdn3d.__name__
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
#
|
|
236
|
+
# For removing background texture (sawdust pellets):
|
|
237
|
+
# Focus on HIGH spatial values (most important) and moderate temporal values
|
|
238
|
+
# Spatial parameters blur within each frame - critical for static background texture
|
|
239
|
+
# Temporal parameters smooth across frames - less critical for static background
|
|
240
|
+
# denoise_hqdn3d(
|
|
241
|
+
# file_path=r"E:\open_video\open_field_4\2.mp4",
|
|
242
|
+
# luma_spatial=200, # VERY HIGH - most important for background texture removal
|
|
243
|
+
# luma_temporal=40, # Moderate - 200 is overkill for static background
|
|
244
|
+
# chroma_spatial=200, # VERY HIGH - most important for background texture removal
|
|
245
|
+
# chroma_temporal=40 # Moderate - 200 is overkill for static background
|
|
246
|
+
# )
|
|
247
|
+
|
|
248
|
+
# BM3D - Better for texture removal, slower but often produces better results
|
|
249
|
+
# sigma is the most important parameter - controls denoising strength
|
|
250
|
+
# denoise_bm3d(
|
|
251
|
+
# file_path=r"E:\open_video\open_field_4\2.mp4",
|
|
252
|
+
# sigma=15, # High denoising strength for background texture removal
|
|
253
|
+
# block=8, # Larger blocks = more smoothing
|
|
254
|
+
# bstep=2, # Smaller step = better quality
|
|
255
|
+
# group=1 # Default group size
|
|
256
|
+
# )
|
|
257
|
+
#
|
|
258
|
+
# # BM3D - Better for texture removal, slower but often produces better results
|
|
259
|
+
# # sigma is the most important parameter - controls denoising strength
|
|
260
|
+
# denoise_bm3d(
|
|
261
|
+
# file_path=r"E:\open_video\open_field_4\2.mp4",
|
|
262
|
+
# sigma=15, # High denoising strength for background texture removal
|
|
263
|
+
# block=8, # Larger blocks = more smoothing
|
|
264
|
+
# bstep=2, # Smaller step = better quality
|
|
265
|
+
# group=1 # Default group size
|
|
266
|
+
# )
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Function to extract random N frames from all videos in a directory.
|
|
3
|
+
|
|
4
|
+
Each frame is saved as videoname_framenumber.png in the same directory as the video.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
import random
|
|
9
|
+
from typing import Union, Optional
|
|
10
|
+
import numpy as np
|
|
11
|
+
import cv2
|
|
12
|
+
|
|
13
|
+
from simba.utils.checks import (
|
|
14
|
+
check_if_dir_exists,
|
|
15
|
+
check_int,
|
|
16
|
+
check_file_exist_and_readable
|
|
17
|
+
)
|
|
18
|
+
from simba.utils.read_write import (
|
|
19
|
+
get_video_meta_data,
|
|
20
|
+
find_all_videos_in_directory,
|
|
21
|
+
read_frm_of_video,
|
|
22
|
+
get_fn_ext
|
|
23
|
+
)
|
|
24
|
+
from simba.utils.printing import SimbaTimer, stdout_success
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def extract_random_frames_from_directory(
|
|
28
|
+
directory: Union[str, os.PathLike],
|
|
29
|
+
n_frames: int = 10,
|
|
30
|
+
save_dir: Optional[Union[str, os.PathLike]] = None,
|
|
31
|
+
verbose: Optional[bool] = True
|
|
32
|
+
) -> None:
|
|
33
|
+
"""
|
|
34
|
+
Extract random N frames from all videos in a directory.
|
|
35
|
+
|
|
36
|
+
For each video, randomly samples N frames and saves them as individual PNG files.
|
|
37
|
+
Frames are saved with the naming convention: videoname_framenumber.png
|
|
38
|
+
|
|
39
|
+
:param Union[str, os.PathLike] directory: Path to directory containing video files.
|
|
40
|
+
:param int n_frames: Number of random frames to extract from each video. Default: 10.
|
|
41
|
+
:param Optional[Union[str, os.PathLike]] save_dir: Optional directory where extracted frames will be saved.
|
|
42
|
+
If None, frames are saved in the same directory as each video file. Default: None.
|
|
43
|
+
:param Optional[bool] verbose: If True, prints progress messages during extraction. Default: True.
|
|
44
|
+
:return: None. Frames are saved to disk.
|
|
45
|
+
|
|
46
|
+
:example:
|
|
47
|
+
>>> extract_random_frames_from_directory(directory='project_folder/videos', n_frames=20)
|
|
48
|
+
>>> extract_random_frames_from_directory(directory='/Users/simon/Desktop/videos', n_frames=5, save_dir='/Users/simon/Desktop/frames')
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
timer = SimbaTimer(start=True)
|
|
52
|
+
check_if_dir_exists(in_dir=directory, source=extract_random_frames_from_directory.__name__)
|
|
53
|
+
check_int(name="n_frames", value=n_frames, min_value=1)
|
|
54
|
+
|
|
55
|
+
# Find all videos in directory
|
|
56
|
+
video_paths = find_all_videos_in_directory(
|
|
57
|
+
directory=directory,
|
|
58
|
+
as_dict=False,
|
|
59
|
+
raise_error=True
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
if not video_paths or video_paths == ["No videos found"]:
|
|
63
|
+
raise ValueError(f"No videos found in directory: {directory}")
|
|
64
|
+
|
|
65
|
+
total_frames_extracted = 0
|
|
66
|
+
|
|
67
|
+
for video_cnt, video_name in enumerate(video_paths):
|
|
68
|
+
video_path = os.path.join(directory, video_name)
|
|
69
|
+
check_file_exist_and_readable(file_path=video_path)
|
|
70
|
+
|
|
71
|
+
# Get video metadata
|
|
72
|
+
video_meta_data = get_video_meta_data(video_path=video_path)
|
|
73
|
+
total_frames = video_meta_data["frame_count"]
|
|
74
|
+
_, video_name_only, _ = get_fn_ext(filepath=video_path) # Returns (directory, filename, extension)
|
|
75
|
+
|
|
76
|
+
# Determine save directory
|
|
77
|
+
if save_dir is None:
|
|
78
|
+
video_save_dir = directory # Save to the same directory as the videos
|
|
79
|
+
else:
|
|
80
|
+
video_save_dir = save_dir
|
|
81
|
+
|
|
82
|
+
# Create save directory if it doesn't exist
|
|
83
|
+
if not os.path.exists(video_save_dir):
|
|
84
|
+
os.makedirs(video_save_dir)
|
|
85
|
+
|
|
86
|
+
# Randomly sample N frames (or all frames if video has fewer than N frames)
|
|
87
|
+
n_samples = min(n_frames, total_frames)
|
|
88
|
+
if total_frames < n_frames:
|
|
89
|
+
if verbose:
|
|
90
|
+
print(f"Video {video_name_only} has only {total_frames} frames. Extracting all {total_frames} frames.")
|
|
91
|
+
selected_frames = list(range(total_frames))
|
|
92
|
+
else:
|
|
93
|
+
selected_frames = sorted(random.sample(range(total_frames), n_samples))
|
|
94
|
+
|
|
95
|
+
# Extract and save frames
|
|
96
|
+
cap = cv2.VideoCapture(video_path)
|
|
97
|
+
for frame_idx, frame_number in enumerate(selected_frames):
|
|
98
|
+
# Seek to the correct frame
|
|
99
|
+
cap.set(cv2.CAP_PROP_POS_FRAMES, frame_number)
|
|
100
|
+
ret, frame = cap.read()
|
|
101
|
+
|
|
102
|
+
if not ret:
|
|
103
|
+
if verbose:
|
|
104
|
+
print(f"Warning: Could not read frame {frame_number} from {video_name_only}. Skipping...")
|
|
105
|
+
continue
|
|
106
|
+
|
|
107
|
+
# Save frame with naming convention: videoname_framenumber.png
|
|
108
|
+
# video_name_only is the video filename without extension
|
|
109
|
+
save_path = os.path.join(video_save_dir, f"{video_name_only}_{frame_number}.png")
|
|
110
|
+
cv2.imwrite(save_path, frame, [cv2.IMWRITE_PNG_COMPRESSION, 3])
|
|
111
|
+
total_frames_extracted += 1
|
|
112
|
+
|
|
113
|
+
if verbose:
|
|
114
|
+
print(f"Video {video_cnt + 1}/{len(video_paths)}: Frame {frame_number} saved from {video_name_only} ({frame_idx + 1}/{len(selected_frames)})")
|
|
115
|
+
|
|
116
|
+
cap.release()
|
|
117
|
+
|
|
118
|
+
timer.stop_timer()
|
|
119
|
+
stdout_success(
|
|
120
|
+
msg=f"SIMBA COMPLETE: Extracted {total_frames_extracted} random frames from {len(video_paths)} video(s)!",
|
|
121
|
+
elapsed_time=timer.elapsed_time_str,
|
|
122
|
+
source=extract_random_frames_from_directory.__name__
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
extract_random_frames_from_directory(directory=r"D:\maplight_tg2576_yolo\videos", n_frames=35, save_dir=r'D:\maplight_tg2576_yolo\frames')
|
|
@@ -2495,7 +2495,7 @@ class Convert2WEBMPopUp(PopUpMixin):
|
|
|
2495
2495
|
def __init__(self):
|
|
2496
2496
|
super().__init__(title="CONVERT VIDEOS TO WEBM", icon='webm')
|
|
2497
2497
|
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
|
|
2498
|
-
self.WEBM_CODEC_LK = {'VP8': 'vp8', 'VP9': 'vp9'}
|
|
2498
|
+
self.WEBM_CODEC_LK = {'VP8': 'vp8', 'VP9': 'vp9', 'AV1': 'av1'}
|
|
2499
2499
|
|
|
2500
2500
|
self.quality_dropdown = SimBADropDown(parent=settings_frm, label="OUTPUT VIDEO QUALITY:", dropdown_options=list(range(10, 110, 10)), label_width=25, value=60, img='pct', dropdown_width=30)
|
|
2501
2501
|
self.codec_dropdown = SimBADropDown(parent=settings_frm, label="COMPRESSION CODEC:", dropdown_options=list(self.WEBM_CODEC_LK.keys()), label_width=25, value='VP9', img='file_type', dropdown_width=30)
|
|
@@ -56,7 +56,7 @@ from simba.utils.lookups import (get_current_time, get_ffmpeg_codec,
|
|
|
56
56
|
get_ffmpeg_crossfade_methods, get_fonts,
|
|
57
57
|
get_named_colors, percent_to_crf_lookup,
|
|
58
58
|
percent_to_qv_lk, quality_pct_to_crf,
|
|
59
|
-
video_quality_to_preset_lookup)
|
|
59
|
+
video_quality_to_preset_lookup, get_ffmpeg_encoders)
|
|
60
60
|
from simba.utils.printing import SimbaTimer, stdout_information, stdout_success
|
|
61
61
|
from simba.utils.read_write import (
|
|
62
62
|
check_if_hhmmss_timestamp_is_valid_part_of_video,
|
|
@@ -440,10 +440,11 @@ def clahe_enhance_video(file_path: Union[str, os.PathLike],
|
|
|
440
440
|
dir, file_name, file_ext = get_fn_ext(filepath=file_path)
|
|
441
441
|
if out_path is None:
|
|
442
442
|
save_path = os.path.join(dir, f"CLAHE_{file_name}.avi")
|
|
443
|
+
fourcc = cv2.VideoWriter_fourcc(*Formats.AVI_CODEC.value)
|
|
443
444
|
else:
|
|
444
445
|
check_if_dir_exists(in_dir=os.path.dirname(out_path), source=f'{clahe_enhance_video.__name__} out_path')
|
|
446
|
+
fourcc = cv2.VideoWriter_fourcc(*Formats.MP4_CODEC.value)
|
|
445
447
|
save_path = out_path
|
|
446
|
-
fourcc = cv2.VideoWriter_fourcc(*Formats.AVI_CODEC.value)
|
|
447
448
|
if verbose: print(f"Applying CLAHE on video {file_name}, this might take awhile...")
|
|
448
449
|
cap = cv2.VideoCapture(file_path)
|
|
449
450
|
writer = cv2.VideoWriter( save_path, fourcc, video_meta_data["fps"], (video_meta_data["width"], video_meta_data["height"]), 0)
|
|
@@ -3265,6 +3266,9 @@ def convert_to_avi(path: Union[str, os.PathLike],
|
|
|
3265
3266
|
timer = SimbaTimer(start=True)
|
|
3266
3267
|
check_ffmpeg_available(raise_error=True)
|
|
3267
3268
|
check_str(name=f'{convert_to_avi.__name__} codec', value=codec, options=('xvid', 'divx', 'mjpeg'))
|
|
3269
|
+
CODEC_LK = {'mpeg4': 'mpeg4', 'divx': 'libxvid', 'mjpeg': 'mjpeg'}
|
|
3270
|
+
codec = CODEC_LK[codec]
|
|
3271
|
+
check_valid_codec(codec=codec, raise_error=True, source=f'{convert_to_avi.__name__} codec')
|
|
3268
3272
|
check_instance(source=f'{convert_to_avi.__name__} path', instance=path, accepted_types=(str,))
|
|
3269
3273
|
check_int(name=f'{convert_to_avi.__name__} quality', value=quality)
|
|
3270
3274
|
datetime_ = datetime.now().strftime("%Y%m%d%H%M%S")
|
|
@@ -3292,18 +3296,18 @@ def convert_to_avi(path: Union[str, os.PathLike],
|
|
|
3292
3296
|
_ = get_video_meta_data(video_path=file_path)
|
|
3293
3297
|
out_path = os.path.join(save_dir, f'{video_name}.avi')
|
|
3294
3298
|
if codec == 'divx':
|
|
3295
|
-
cmd = f'ffmpeg -i "{file_path}" -c:v
|
|
3299
|
+
cmd = f'ffmpeg -i "{file_path}" -c:v {codec} -crf {crf} -vtag DIVX "{out_path}" -loglevel error -stats -hide_banner -y'
|
|
3296
3300
|
elif codec == 'xvid':
|
|
3297
|
-
cmd = f'ffmpeg -i "{file_path}" -c:v
|
|
3301
|
+
cmd = f'ffmpeg -i "{file_path}" -c:v {codec} -q:v {qv} "{out_path}" -loglevel error -stats -hide_banner -y'
|
|
3298
3302
|
else:
|
|
3299
|
-
cmd = f'ffmpeg -i "{file_path}" -c:v
|
|
3303
|
+
cmd = f'ffmpeg -i "{file_path}" -c:v {codec} -q:v {qv} "{out_path}" -loglevel error -stats -hide_banner -y'
|
|
3300
3304
|
subprocess.call(cmd, shell=True, stdout=subprocess.PIPE)
|
|
3301
3305
|
timer.stop_timer()
|
|
3302
3306
|
stdout_success(msg=f"{len(file_paths)} video(s) converted to AVI and saved in {save_dir} directory.", elapsed_time=timer.elapsed_time_str, source=convert_to_avi.__name__,)
|
|
3303
3307
|
|
|
3304
3308
|
|
|
3305
3309
|
def convert_to_webm(path: Union[str, os.PathLike],
|
|
3306
|
-
codec: Literal['vp8', 'vp9'] = 'vp9',
|
|
3310
|
+
codec: Literal['vp8', 'vp9', 'av1'] = 'vp9',
|
|
3307
3311
|
save_dir: Optional[Union[str, os.PathLike]] = None,
|
|
3308
3312
|
quality: Optional[int] = 60) -> None:
|
|
3309
3313
|
|
|
@@ -3326,7 +3330,10 @@ def convert_to_webm(path: Union[str, os.PathLike],
|
|
|
3326
3330
|
|
|
3327
3331
|
timer = SimbaTimer(start=True)
|
|
3328
3332
|
check_ffmpeg_available(raise_error=True)
|
|
3329
|
-
check_str(name=f'{convert_to_webm.__name__} codec', value=codec, options=('vp8', 'vp9'))
|
|
3333
|
+
check_str(name=f'{convert_to_webm.__name__} codec', value=codec, options=('vp8', 'vp9', 'av1'))
|
|
3334
|
+
CODEC_LK = {'vp8': 'libvpx', 'vp9': 'libvpx-vp9', 'av1': 'libaom-av1'}
|
|
3335
|
+
codec = CODEC_LK[codec]
|
|
3336
|
+
check_valid_codec(codec=codec, raise_error=True, source=f'{convert_to_webm.__name__} codec')
|
|
3330
3337
|
check_instance(source=f'{convert_to_webm.__name__} path', instance=path, accepted_types=(str,))
|
|
3331
3338
|
check_int(name=f'{convert_to_webm.__name__} quality', value=quality)
|
|
3332
3339
|
datetime_ = datetime.now().strftime("%Y%m%d%H%M%S")
|
|
@@ -3346,17 +3353,13 @@ def convert_to_webm(path: Union[str, os.PathLike],
|
|
|
3346
3353
|
os.makedirs(save_dir)
|
|
3347
3354
|
else:
|
|
3348
3355
|
raise InvalidInputError(msg=f'Paths is not a valid file or directory path.', source=convert_to_webm.__name__)
|
|
3356
|
+
|
|
3349
3357
|
for file_cnt, file_path in enumerate(file_paths):
|
|
3350
3358
|
_, video_name, _ = get_fn_ext(filepath=file_path)
|
|
3351
3359
|
print(f'Converting video {video_name} to WEBM (Video {file_cnt+1}/{len(file_paths)})...')
|
|
3352
3360
|
_ = get_video_meta_data(video_path=file_path)
|
|
3353
3361
|
out_path = os.path.join(save_dir, f'{video_name}.webm')
|
|
3354
|
-
|
|
3355
|
-
cmd = f'ffmpeg -i "{file_path}" -c:v libvpx -crf {crf} "{out_path}" -loglevel error -stats -hide_banner -y'
|
|
3356
|
-
elif codec == 'vp9':
|
|
3357
|
-
cmd = f'ffmpeg -i "{file_path}" -c:v libvpx-vp9 -crf {crf} "{out_path}" -loglevel error -stats -hide_banner -y'
|
|
3358
|
-
else:
|
|
3359
|
-
cmd = f'ffmpeg -i "{file_path}" -c:v libaom-av1 -crf {crf} "{out_path}" -loglevel error -stats -hide_banner -y'
|
|
3362
|
+
cmd = f'ffmpeg -i "{file_path}" -c:v {codec} -crf {crf} "{out_path}" -loglevel error -stats -hide_banner -y'
|
|
3360
3363
|
subprocess.call(cmd, shell=True, stdout=subprocess.PIPE)
|
|
3361
3364
|
timer.stop_timer()
|
|
3362
3365
|
stdout_success(msg=f"{len(file_paths)} video(s) converted to WEBM and saved in {save_dir} directory.", elapsed_time=timer.elapsed_time_str, source=convert_to_webm.__name__,)
|
|
@@ -3381,6 +3384,10 @@ def convert_to_mov(path: Union[str, os.PathLike],
|
|
|
3381
3384
|
timer = SimbaTimer(start=True)
|
|
3382
3385
|
check_ffmpeg_available(raise_error=True)
|
|
3383
3386
|
check_str(name=f'{convert_to_mov.__name__} codec', value=codec, options=('prores', 'animation', 'cineform', 'dnxhd'))
|
|
3387
|
+
|
|
3388
|
+
|
|
3389
|
+
|
|
3390
|
+
|
|
3384
3391
|
check_instance(source=f'{convert_to_mov.__name__} path', instance=path, accepted_types=(str,))
|
|
3385
3392
|
check_int(name=f'{convert_to_mov.__name__} quality', value=quality)
|
|
3386
3393
|
datetime_ = datetime.now().strftime("%Y%m%d%H%M%S")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: simba-uw-tf-dev
|
|
3
|
-
Version: 4.7.
|
|
3
|
+
Version: 4.7.6
|
|
4
4
|
Summary: Toolkit for computer classification and analysis of behaviors in experimental animals
|
|
5
5
|
Home-page: https://github.com/sgoldenlab/simba
|
|
6
6
|
Author: Simon Nilsson, Jia Jie Choong, Sophia Hwang
|
|
@@ -13,7 +13,7 @@ simba/__init__.py,sha256=Zbw277SaA4dLpF3IDQnIjzOb-GWKgF-V6caod95b4YA,539
|
|
|
13
13
|
simba/requirements.txt,sha256=Ou1KKYqIsOaqQ10UeqxTPorpHWBH5rTMGzpFif1VRWc,2072
|
|
14
14
|
simba/assets/.DS_Store,sha256=ElS4pjNueynnfN3F6ibhpIe9tS-jrVEx88jASA9_DYo,14340
|
|
15
15
|
simba/assets/.env,sha256=bI_XK4TDnRDnV1M5SyZrEfeayi9ZK7rX2lrYQcJnH0s,538
|
|
16
|
-
simba/assets/.recent_projects.txt,sha256=
|
|
16
|
+
simba/assets/.recent_projects.txt,sha256=18t7rzwuoVChVyfpME5c11LShZT9Frb8rEj6Puvfba8,265
|
|
17
17
|
simba/assets/TheGoldenLab.PNG,sha256=Dwg7zXASz_XDhJ_gDgKyBmAINxLL-Zkg-3xzy94YEsc,31812
|
|
18
18
|
simba/assets/UbuntuMono-Regular.ttf,sha256=N0xTF4v7xLE_m2rVu8gaQ5OqZSZf_H0zqnvYnxKjDfg,189004
|
|
19
19
|
simba/assets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -621,7 +621,7 @@ simba/mixins/abstract_classes.py,sha256=umpVIU7EG_jZ1DU8x5zkTb8A-KH46jlCISowfrT4
|
|
|
621
621
|
simba/mixins/annotator_mixin.py,sha256=TQWqBZ5UVR5blI5CUyr3nuxsB3HyrxYimPg3rXcOHfU,40917
|
|
622
622
|
simba/mixins/circular_statistics.py,sha256=yzYRKsuY3xK_LgDC7rpu4OQnbSQpjXO0EiLv4kH6cp8,77336
|
|
623
623
|
simba/mixins/config_reader.py,sha256=9su8ZGnGWghk5bAl12iaTQdqIOVfcW2ZQcxeEXmXtcI,52362
|
|
624
|
-
simba/mixins/feature_extraction_mixin.py,sha256=
|
|
624
|
+
simba/mixins/feature_extraction_mixin.py,sha256=kOlU4FsqKxvDQ_UA9RrcvidTKv2sCitx_noZtHc6eyY,59585
|
|
625
625
|
simba/mixins/feature_extraction_supplement_mixin.py,sha256=6dPi1WFi26y-rmccsMgDe5sULm4fTQaBcSiH91DEkN0,44770
|
|
626
626
|
simba/mixins/geometry_mixin.py,sha256=QL16YFqSR0Wtio0v2PE2l41KTP_DKmW_tiGY6ns-Ojg,248630
|
|
627
627
|
simba/mixins/image_mixin.py,sha256=C3FcZGp_kLMYMvbFxOedYPebIYm6KJIRPAB7rcu6J80,125807
|
|
@@ -806,6 +806,7 @@ simba/sandbox/append_targets'.py,sha256=f8lB0FFdJy97uZuEyfWsJYOf2Uw05skSGjH3uiLF
|
|
|
806
806
|
simba/sandbox/apply_offsets.py,sha256=XKqGD3ihq0clkZUFF3JBuZP-KlcRFAPphHV-7VCGnQU,3601
|
|
807
807
|
simba/sandbox/async_frame_writer.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
808
808
|
simba/sandbox/async_frm_reader.py,sha256=aPs3RTHfnDuNHeGnKH6yeQmQAO4QestVQbeyMGhrzwU,4694
|
|
809
|
+
simba/sandbox/av1.py,sha256=t5_RS-kJ0wNSkiVIZO9acSeJ5JLApqkqx1feYmFX9Ww,174
|
|
809
810
|
simba/sandbox/average_frm_popup.py,sha256=E1nn5D_P8A8imnES6uskaXw5EMMieYEUL6-RjEl3atQ,9216
|
|
810
811
|
simba/sandbox/baker_huber_gamma_index.py,sha256=Mki6-POmlN09NKAhHdKDIenNRwsbFhRLYXz8aZVn23A,2129
|
|
811
812
|
simba/sandbox/bar_chart.py,sha256=kZCVZPq3Wrmt195NWkpNwdi1beaOxJ945xl1O4gS9Zg,2614
|
|
@@ -906,6 +907,7 @@ simba/sandbox/debug_csv_columns.py,sha256=uJwHZ1UQE6vFzTyFMbwf8qrWcL3KM7EafDmvIY
|
|
|
906
907
|
simba/sandbox/debug_network.py,sha256=niyPStKhIpyom6AVREjYC_7aixnVdErlnz7yMaQxTOk,7125
|
|
907
908
|
simba/sandbox/define_rois.py,sha256=UHxsbfe2b1GjbuNU6jfqXnFy3X_-B0I0CgZVqIw5TlA,1671
|
|
908
909
|
simba/sandbox/denoise_gpu.py,sha256=vDiRuXMv-dyFMgomZMEiKJNPDmT9sinpXILcBOfAn9k,1832
|
|
910
|
+
simba/sandbox/denoise_hqdn3d.py,sha256=dbpFKQSSS84PEkmpoBtX-8Yw6Ogl3iyK4T_Qq_Wx1Zo,14498
|
|
909
911
|
simba/sandbox/denoiser.py,sha256=BXB_YAnUXCDe3csnT3cT5YLes9oRS0immjA5P4YP2hs,10324
|
|
910
912
|
simba/sandbox/detect_scene_changes.py,sha256=P7tmHoFH55ryTXwgY2cVxXQiVNCRaf_4hVi1Nd-ZOCA,561
|
|
911
913
|
simba/sandbox/dir_to_mosaic.py,sha256=rNnxJlEyJMG8jXmWx-NgEcS9hHQ3sqOlLQ-hYTEg7P4,1576
|
|
@@ -950,6 +952,7 @@ simba/sandbox/extract_and_convert_videos.py,sha256=nE3ncyoRb8Ac_vdbxSK1D2-Lqr71M
|
|
|
950
952
|
simba/sandbox/extract_annotation_frames_pop_up.py,sha256=EYHEL5SlpvLpeFPnGmeib5LL97mkkdlb3fhaDcYehAk,5783
|
|
951
953
|
simba/sandbox/extract_aucio_track.py,sha256=tTp0PlTXt76-fDf-E695NZ1cxlS36Wb783dE0ZoF7k0,3092
|
|
952
954
|
simba/sandbox/extract_frames.py,sha256=J4POX21DXP92lYhvZUiYcZAGmT-kp6Y3ICkMb-pjkxA,838
|
|
955
|
+
simba/sandbox/extract_random_frames.py,sha256=pBtJ1WEDNdI9er8LrclxHSCqM7xoZ7ocww48VfnTQm0,5225
|
|
953
956
|
simba/sandbox/ez_path_plot.py,sha256=euSazuxyIRWaHrlhiOMjDugqMba8SvsRWUuOl78M6MI,6409
|
|
954
957
|
simba/sandbox/feature_subset_new.py,sha256=OF-wTPvktqJbyBPctIqMWS1qgyMlMsStX_Ddrn31CCw,23088
|
|
955
958
|
simba/sandbox/fecal_boli.py,sha256=pdInnlZ94sNgVQAmsQRbT0Sw1qz9JPWaowEkscTErkc,1636
|
|
@@ -1471,7 +1474,7 @@ simba/ui/pop_ups/subset_feature_extractor_pop_up.py,sha256=M24iJSqh-DpYdpw1pSaIm
|
|
|
1471
1474
|
simba/ui/pop_ups/targeted_annotation_clips_pop_up.py,sha256=PFh5ua2f_OMQ1Pth9Ha8Fo5lTPZNQV3bMnRGEoAPhTQ,6997
|
|
1472
1475
|
simba/ui/pop_ups/third_party_annotator_appender_pop_up.py,sha256=Xnha2UwM-08djObCkL_EXK2L4pernyipzbyNKQvX5aQ,7694
|
|
1473
1476
|
simba/ui/pop_ups/validation_plot_pop_up.py,sha256=yIo_el2dR_84ZAh_-2fYFg-BJDG0Eip_P_o9vzTQRkk,12174
|
|
1474
|
-
simba/ui/pop_ups/video_processing_pop_up.py,sha256=
|
|
1477
|
+
simba/ui/pop_ups/video_processing_pop_up.py,sha256=_7nVjWkXoLuvxIjEEAJjzWe7Lf1H_HAWbNp31ZB6AvA,252019
|
|
1475
1478
|
simba/ui/pop_ups/visualize_pose_in_dir_pop_up.py,sha256=PpFs0zaqF4dnHJ_yH-PqYgsjAyxYPVP427Soj-kYtM0,8838
|
|
1476
1479
|
simba/ui/pop_ups/yolo_inference_popup.py,sha256=C4_WDvEHLp9JMUTjLZuRpKHxMCGpa_pxXELuj-zerCs,14679
|
|
1477
1480
|
simba/ui/pop_ups/yolo_plot_results.py,sha256=yi9D3WquDu4L8PWJLZsODulojgakfy7Dzh_CpYK6Vgk,10096
|
|
@@ -1541,11 +1544,11 @@ simba/video_processors/multi_cropper.py,sha256=1BI0Ami4kB9rdMUHR0EistmIKqc-E5FK5
|
|
|
1541
1544
|
simba/video_processors/roi_selector.py,sha256=5N3s0Bi1Ub6c9gjE_-mV7AWr8Fqg7HQKdBKBF6whurg,8522
|
|
1542
1545
|
simba/video_processors/roi_selector_circle.py,sha256=SD_lv6V3MGiIQd0VtUFSKe83ySW_qvE1t8xsgAlr2hI,6436
|
|
1543
1546
|
simba/video_processors/roi_selector_polygon.py,sha256=DMtilt__gGwNu6VV73CWbnPqrPBXkan1_akUqGEzfGw,6742
|
|
1544
|
-
simba/video_processors/video_processing.py,sha256=
|
|
1547
|
+
simba/video_processors/video_processing.py,sha256=SOocFxbo5O5TXpH1ClO19-Rhn7CKHQ82wLasfmTUT8M,327985
|
|
1545
1548
|
simba/video_processors/videos_to_frames.py,sha256=8hltNZpwUfb3GFi-63D0PsySmD5l59pbzQGJx8SscgU,7818
|
|
1546
|
-
simba_uw_tf_dev-4.7.
|
|
1547
|
-
simba_uw_tf_dev-4.7.
|
|
1548
|
-
simba_uw_tf_dev-4.7.
|
|
1549
|
-
simba_uw_tf_dev-4.7.
|
|
1550
|
-
simba_uw_tf_dev-4.7.
|
|
1551
|
-
simba_uw_tf_dev-4.7.
|
|
1549
|
+
simba_uw_tf_dev-4.7.6.dist-info/LICENSE,sha256=Sjn362upcvYFypam-b-ziOXU1Wl5GGuTt5ICrGimzyA,1720
|
|
1550
|
+
simba_uw_tf_dev-4.7.6.dist-info/METADATA,sha256=hp7yO2XbbWvm182wc7TgReqkM40vYpLB591vqNKNlc4,11432
|
|
1551
|
+
simba_uw_tf_dev-4.7.6.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
|
|
1552
|
+
simba_uw_tf_dev-4.7.6.dist-info/entry_points.txt,sha256=Nfh_EbfDGdKftLjCnGWtQrBHENiDYMdgupwLyLpU5dc,44
|
|
1553
|
+
simba_uw_tf_dev-4.7.6.dist-info/top_level.txt,sha256=ogtimvlqDxDTOBAPfT2WaQ2pGAAbKRXG8z8eUTzf6TU,14
|
|
1554
|
+
simba_uw_tf_dev-4.7.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|