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.
@@ -1,3 +1,4 @@
1
+ C:/troubleshooting/sleap_two_animals/project_folder/project_config.ini
1
2
  E:/troubleshooting/mitra_emergence/project_folder/project_config.ini
2
3
  C:/troubleshooting/meberled/project_folder/project_config.ini
3
4
  C:/troubleshooting/mitra/project_folder/project_config.ini
@@ -603,8 +603,6 @@ class FeatureExtractionMixin(object):
603
603
  else:
604
604
  pass
605
605
 
606
-
607
-
608
606
  for cord in [nose_cords, ear_left_cords, ear_right_cords]:
609
607
  if len(cord) != len(self.animal_bp_dict.keys()) * 2:
610
608
  direction_viable = False
simba/sandbox/av1.py ADDED
@@ -0,0 +1,5 @@
1
+ from simba.video_processors.video_processing import convert_to_webm
2
+
3
+
4
+
5
+ convert_to_webm(path=r"D:\troubleshooting\batch_fps\2025-09-08_13-06-38-AloneH-1.mp4", codec='vp9')
@@ -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 mpeg4 -crf {crf} -vtag DIVX "{out_path}" -loglevel error -stats -hide_banner -y'
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 libxvid -q:v {qv} "{out_path}" -loglevel error -stats -hide_banner -y'
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 mjpeg -q:v {qv} "{out_path}" -loglevel error -stats -hide_banner -y'
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
- if codec == 'vp8':
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.5
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=iUE8T6XQxOEGrK-r53XVeuz3xdjHgxeQPBogS4yZIyk,193
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=rUwHEG3wKpyreme8nXAeBEhktHG_Q75v3OJI2aFOOOA,59587
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=u9AZMY6HcrcputziJ_b16L29HyT3m0arTW02eR1doFg,252005
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=ynHC-9-Pt020GMZa5xPDhfpouHS5i6D26mT-5F9NAY0,327790
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.5.dist-info/LICENSE,sha256=Sjn362upcvYFypam-b-ziOXU1Wl5GGuTt5ICrGimzyA,1720
1547
- simba_uw_tf_dev-4.7.5.dist-info/METADATA,sha256=JduCaUVbf9SLKDXxS9bVrRblmH2-IMuVU1PQ_LwGhOk,11432
1548
- simba_uw_tf_dev-4.7.5.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
1549
- simba_uw_tf_dev-4.7.5.dist-info/entry_points.txt,sha256=Nfh_EbfDGdKftLjCnGWtQrBHENiDYMdgupwLyLpU5dc,44
1550
- simba_uw_tf_dev-4.7.5.dist-info/top_level.txt,sha256=ogtimvlqDxDTOBAPfT2WaQ2pGAAbKRXG8z8eUTzf6TU,14
1551
- simba_uw_tf_dev-4.7.5.dist-info/RECORD,,
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,,