simba-uw-tf-dev 4.5.8__py3-none-any.whl → 4.6.2__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/SimBA.py CHANGED
@@ -966,8 +966,8 @@ class App(object):
966
966
  video_process_menu.add_cascade(label="Drop body-parts from tracking data", compound="left", image=self.menu_icons["trash"]["img"], command=DropTrackingDataPopUp, font=Formats.FONT_REGULAR.value)
967
967
  extract_frames_menu = Menu(video_process_menu, font=Formats.FONT_REGULAR.value)
968
968
  extract_frames_menu.add_command(label="Extract defined frames", command=ExtractSpecificFramesPopUp, font=Formats.FONT_REGULAR.value, image=self.menu_icons["frames"]["img"], compound="left")
969
- extract_frames_menu.add_command(label="Extract frames from single video", command=SingleVideo2FramesPopUp, font=Formats.FONT_REGULAR.value, image=self.menu_icons["video"]["img"], compound="left")
970
- extract_frames_menu.add_command(label="Extract frames from multiple video", command=MultipleVideos2FramesPopUp, font=Formats.FONT_REGULAR.value, image=self.menu_icons["stack"]["img"], compound="left")
969
+ extract_frames_menu.add_command(label="Extract frames from single video", command=SingleVideo2FramesPopUp, font=Formats.FONT_REGULAR.value, image=self.menu_icons["frames_2"]["img"], compound="left")
970
+ extract_frames_menu.add_command(label="Extract frames from multiple videos", command=MultipleVideos2FramesPopUp, font=Formats.FONT_REGULAR.value, image=self.menu_icons["stack"]["img"], compound="left")
971
971
  extract_frames_menu.add_command(label="Extract frames from seq files", command=ExtractSEQFramesPopUp, font=Formats.FONT_REGULAR.value, image=self.menu_icons["fire"]["img"], compound="left")
972
972
  video_process_menu.add_cascade(label="Extract frames...", compound="left", image=self.menu_icons["frames"]["img"], menu=extract_frames_menu, font=Formats.FONT_REGULAR.value)
973
973
 
Binary file
@@ -29,5 +29,14 @@
29
29
  "LOCATION_FRAME_COUNT": "The location in the video where the \n frame count is positioned.",
30
30
  "ROTATE_FILL_COLOR": "When video is rotated, there may be empty space not \n covered by the video. What color should this space have?",
31
31
  "VIDEO_DIR": "Directory containing videos.",
32
- "SAVE_DIR": "Directory where to save results."
32
+ "SAVE_DIR": "Directory where to save results.",
33
+ "CONCAT_HEIGHT": "If join involves aligning videos horizontally, this values \nwill be used to ensure videos have the same height. ",
34
+ "CONCAT_WIDTH": "If join involves aligning videos vertically, this values \nwill be used to ensure videos have the same width. ",
35
+ "CONCAT_RES_HEADER": "When stacking videos horizontally and/or vertically, \n the videos need to be same height and/or width. Here, \n select what resolution to use.",
36
+ "EGOCENTRIC_DATA_DIR": "Folder containing pose-estimation CSV data.\n Can be sub-directory in 'project_folder/csv' folder.\n Should contain same file names as the VIDEO files",
37
+ "EGOCENTRIC_VIDEO_DIR": "Folder containing videos.\n Should contain same file names as the DATA files.",
38
+ "EGOCENTRIC_ANCHOR": "This body-part will be placed in the center of the video",
39
+ "EGOCENTRIC_DIRECTION_ANCHOR": "This body-part will be placed at N degrees relative to the anchor",
40
+ "EGOCENTRIC_DIRECTION": "The anchor body-part will always be placed at these degrees relative to the center anchor",
41
+ "CORE_COUNT": "Higher core counts speeds up processing but may require more RAM memory"
33
42
  }
@@ -1,196 +1,137 @@
1
- __author__ = "Simon Nilsson; sronilsson@gmail.com"
2
-
3
- import os
4
- import shutil
5
- from datetime import datetime
6
- from typing import List, Optional, Union
7
-
8
- try:
9
- from typing import Literal
10
- except ImportError:
11
- from typing_extensions import Literal
12
-
13
- from simba.mixins.config_reader import ConfigReader
14
- from simba.utils.checks import (check_ffmpeg_available,
15
- check_file_exist_and_readable, check_int,
16
- check_nvidea_gpu_available, check_str,
17
- check_valid_lst)
18
- from simba.utils.enums import Paths, TagNames
19
- from simba.utils.errors import FFMPEGCodecGPUError
20
- from simba.utils.printing import SimbaTimer, log_event, stdout_success
21
- from simba.utils.read_write import copy_files_to_directory, get_fn_ext
22
- from simba.video_processors.video_processing import (
23
- horizontal_video_concatenator, mixed_mosaic_concatenator,
24
- mosaic_concatenator, vertical_video_concatenator)
25
-
26
- HORIZONTAL = "horizontal"
27
- VERTICAL = "vertical"
28
- MOSAIC = "mosaic"
29
- MIXED_MOSAIC = "mixed_mosaic"
30
- ACCEPTED_TYPES = [HORIZONTAL, VERTICAL, MOSAIC, MIXED_MOSAIC]
31
-
32
-
33
- class FrameMergererFFmpeg(ConfigReader):
34
- """
35
- Merge separate visualizations of classifications, descriptive statistics etc., into single video mosaic.
36
-
37
- .. note::
38
- `GitHub tutorial <https://github.com/sgoldenlab/simba/blob/master/docs/tutorial.md#step-12-merge-frames>`_.
39
-
40
- .. image:: _static/img/mosaic_videos.gif
41
- :width: 600
42
- :align: center
43
-
44
- :parameter str config_path: Optional path to SimBA project config file in Configparser format.
45
- :parameter Literal["horizontal", "vertical", "mosaic", "mixed_mosaic"] concat_type: Type of concatenation. OPTIONS: 'horizontal', 'vertical', 'mosaic', 'mixed_mosaic'.
46
- :parameter List[Union[str, os.PathLike]] video_paths: List with videos to concatenate.
47
- :parameter Optional[int] video_height: Optional height of the canatenated videos. Required if concat concat_type is not mixed_mosaic.
48
- :parameter int video_width: Optional wisth of the canatenated videos. Required if concat concat_type is not mixed_mosaic.
49
- :parameter Optional[bool] gpu: If True, use NVIDEA FFMpeg GPU codecs. Default False.
50
-
51
- :example:
52
- >>> video_paths = ['/Users/simon/Desktop/envs/simba/troubleshooting/mouse_open_field/project_folder/videos/SI_DAY3_308_CD1_PRESENT_downsampled.mp4', '/Users/simon/Desktop/envs/simba/troubleshooting/mouse_open_field/project_folder/videos/SI_DAY3_308_CD1_PRESENT_downsampled.mp4']
53
- >>> merger = FrameMergererFFmpeg(config_path='/Users/simon/Desktop/envs/simba/troubleshooting/two_black_animals_14bp/project_folder/project_config.ini', video_paths=videos, video_height=600, video_width=600, concat_type='mosaic')
54
- >>> merger.run()
55
- """
56
-
57
- def __init__(
58
- self,
59
- concat_type: Literal["horizontal", "vertical", "mosaic", "mixed_mosaic"],
60
- video_paths: List[Union[str, os.PathLike]],
61
- video_height: Optional[int] = None,
62
- video_width: Optional[int] = None,
63
- config_path: Optional[str] = None,
64
- gpu: Optional[bool] = False,
65
- ):
66
-
67
- if gpu and not check_nvidea_gpu_available():
68
- raise FFMPEGCodecGPUError(
69
- msg="NVIDEA GPU not available (as evaluated by nvidea-smi returning None",
70
- source=self.__class__.__name__,
71
- )
72
- check_ffmpeg_available()
73
- check_str(
74
- name=f"{FrameMergererFFmpeg.__name__} concat_type",
75
- value=concat_type,
76
- options=ACCEPTED_TYPES,
77
- )
78
- check_valid_lst(
79
- data=video_paths,
80
- source=f"{self.__class__.__name__} video_paths",
81
- valid_dtypes=(str,),
82
- min_len=2,
83
- )
84
- for i in video_paths:
85
- check_file_exist_and_readable(file_path=i)
86
- if concat_type != MIXED_MOSAIC:
87
- check_int(
88
- name=f"{FrameMergererFFmpeg.__name__} video_height",
89
- value=video_height,
90
- min_value=0,
91
- )
92
- check_int(
93
- name=f"{FrameMergererFFmpeg.__name__} video_width",
94
- value=video_height,
95
- min_value=0,
96
- )
97
- if config_path is not None:
98
- ConfigReader.__init__(self, config_path=config_path)
99
- log_event(
100
- logger_name=str(__class__.__name__),
101
- log_type=TagNames.CLASS_INIT.value,
102
- msg=self.create_log_msg_from_init_args(locals=locals()),
103
- )
104
- self.output_dir = os.path.join(
105
- self.project_path, Paths.CONCAT_VIDEOS_DIR.value
106
- )
107
- self.output_path = os.path.join(
108
- self.project_path,
109
- Paths.CONCAT_VIDEOS_DIR.value,
110
- f"merged_video_{self.datetime}.mp4",
111
- )
112
- else:
113
- self.timer = SimbaTimer(start=True)
114
- self.datetime = datetime.now().strftime("%Y%m%d%H%M%S")
115
- self.output_dir, _, _ = get_fn_ext(filepath=video_paths[0])
116
- self.output_path = os.path.join(
117
- self.output_dir, f"merged_video_{self.datetime}.mp4"
118
- )
119
-
120
- self.video_height, self.video_width, self.gpu = video_height, video_width, gpu
121
- self.video_paths, self.concat_type = video_paths, concat_type
122
- if not os.path.exists(self.output_dir):
123
- os.makedirs(self.output_dir)
124
-
125
- def run(self):
126
- if self.concat_type == HORIZONTAL:
127
- _ = horizontal_video_concatenator(
128
- video_paths=self.video_paths,
129
- save_path=self.output_path,
130
- height_px=self.video_height,
131
- gpu=self.gpu,
132
- verbose=True,
133
- )
134
- elif self.concat_type == VERTICAL:
135
- _ = vertical_video_concatenator(
136
- video_paths=self.video_paths,
137
- save_path=self.output_path,
138
- width_px=self.video_width,
139
- gpu=self.gpu,
140
- verbose=True,
141
- )
142
- elif self.concat_type == MOSAIC:
143
- _ = mosaic_concatenator(
144
- video_paths=self.video_paths,
145
- save_path=self.output_path,
146
- width_px=self.video_width,
147
- height_px=self.video_height,
148
- gpu=self.gpu,
149
- verbose=True,
150
- )
151
- else:
152
- _ = mixed_mosaic_concatenator(
153
- video_paths=self.video_paths,
154
- save_path=self.output_path,
155
- gpu=self.gpu,
156
- verbose=True,
157
- )
158
- self.timer.stop_timer()
159
- stdout_success(
160
- msg=f"Merged video saved at {self.output_path}",
161
- source=self.__class__.__name__,
162
- elapsed_time=self.timer.elapsed_time_str,
163
- )
164
-
165
-
166
- # videos = ['/Users/simon/Desktop/envs/simba/troubleshooting/mouse_open_field/project_folder/videos/SI_DAY3_308_CD1_PRESENT_downsampled.mp4', '/Users/simon/Desktop/envs/simba/troubleshooting/mouse_open_field/project_folder/videos/SI_DAY3_308_CD1_PRESENT_downsampled.mp4']
167
- #
168
- # merger = FrameMergererFFmpeg(config_path='/Users/simon/Desktop/envs/simba/troubleshooting/two_black_animals_14bp/project_folder/project_config.ini',
169
- # video_paths=videos,
170
- # video_height=600,
171
- # video_width=600,
172
- # concat_type='vertical') #horizontal, vertical, mosaic, mixed_mosaic
173
- # merger.run()
174
-
175
-
176
- #
177
- # FrameMergererFFmpeg(config_path=None,
178
- # frame_types={'Video 1': '/Users/simon/Desktop/envs/troubleshooting/two_black_animals_14bp/project_folder/videos/Together_1.avi',
179
- # 'Video 2': '/Users/simon/Desktop/envs/troubleshooting/two_black_animals_14bp/project_folder/videos/Together_1.avi'},
180
- # video_height=640,
181
- # video_width=480,
182
- # concat_type='vertical') #horizontal, vertical, mosaic, mixed_mosaic
183
- #
184
- #
185
-
186
-
187
- # FrameMergererFFmpeg(config_path=None,
188
- # frame_types={'Video 1': r'C:\Users\Nape_Computer_2\Desktop\test_videos\Box1_PM2_day_5_20211104T171021.mp4',
189
- # 'Video 2': r'C:\Users\Nape_Computer_2\Desktop\test_videos\Box1_PM2_day_5_20211104T171021.mp4',
190
- # 'Video 3': r'C:\Users\Nape_Computer_2\Desktop\test_videos\Box1_PM2_day_5_20211104T171021.mp4',
191
- # 'Video 4': r'C:\Users\Nape_Computer_2\Desktop\test_videos\Box1_PM2_day_5_20211104T171021.mp4'},
192
- # video_height=640,
193
- # video_width=480,
194
- # concat_type='mixed_mosaic',
195
- # gpu=False) #horizontal, vertical, mosaic, mixed_mosaic
196
- #
1
+ __author__ = "Simon Nilsson; sronilsson@gmail.com"
2
+
3
+ import os
4
+ import shutil
5
+ from datetime import datetime
6
+ from typing import List, Optional, Union
7
+
8
+ try:
9
+ from typing import Literal
10
+ except ImportError:
11
+ from typing_extensions import Literal
12
+
13
+ from simba.mixins.config_reader import ConfigReader
14
+ from simba.utils.checks import (check_ffmpeg_available,
15
+ check_file_exist_and_readable, check_int,
16
+ check_nvidea_gpu_available, check_str,
17
+ check_valid_boolean, check_valid_lst)
18
+ from simba.utils.enums import Paths, TagNames
19
+ from simba.utils.errors import FFMPEGCodecGPUError
20
+ from simba.utils.printing import SimbaTimer, log_event, stdout_success
21
+ from simba.utils.read_write import copy_files_to_directory, get_fn_ext
22
+ from simba.video_processors.video_processing import (
23
+ horizontal_video_concatenator, mixed_mosaic_concatenator,
24
+ mosaic_concatenator, vertical_video_concatenator)
25
+
26
+ HORIZONTAL = "horizontal"
27
+ VERTICAL = "vertical"
28
+ MOSAIC = "mosaic"
29
+ MIXED_MOSAIC = "mixed_mosaic"
30
+ ACCEPTED_TYPES = [HORIZONTAL, VERTICAL, MOSAIC, MIXED_MOSAIC]
31
+
32
+
33
+ class FrameMergererFFmpeg(ConfigReader):
34
+ """
35
+ Merge separate visualizations of classifications, descriptive statistics etc., into single video mosaic.
36
+
37
+ .. note::
38
+ `GitHub tutorial <https://github.com/sgoldenlab/simba/blob/master/docs/tutorial.md#step-12-merge-frames>`_.
39
+
40
+ .. image:: _static/img/mosaic_videos.gif
41
+ :width: 600
42
+ :align: center
43
+
44
+ :parameter str config_path: Optional path to SimBA project config file in Configparser format.
45
+ :parameter Literal["horizontal", "vertical", "mosaic", "mixed_mosaic"] concat_type: Type of concatenation. OPTIONS: 'horizontal', 'vertical', 'mosaic', 'mixed_mosaic'.
46
+ :parameter List[Union[str, os.PathLike]] video_paths: List with videos to concatenate.
47
+ :param int quality: Video quality (CRF value). Lower values = higher quality. Range 0-52. Default 23.
48
+ :parameter Optional[int] video_height: Optional height of the canatenated videos. Required if concat concat_type is not mixed_mosaic.
49
+ :parameter int video_width: Optional wisth of the canatenated videos. Required if concat concat_type is not mixed_mosaic.
50
+ :parameter Optional[bool] gpu: If True, use NVIDEA FFMpeg GPU codecs. Default False.
51
+
52
+ :example:
53
+ >>> video_paths = ['/Users/simon/Desktop/envs/simba/troubleshooting/mouse_open_field/project_folder/videos/SI_DAY3_308_CD1_PRESENT_downsampled.mp4', '/Users/simon/Desktop/envs/simba/troubleshooting/mouse_open_field/project_folder/videos/SI_DAY3_308_CD1_PRESENT_downsampled.mp4']
54
+ >>> merger = FrameMergererFFmpeg(config_path='/Users/simon/Desktop/envs/simba/troubleshooting/two_black_animals_14bp/project_folder/project_config.ini', video_paths=videos, video_height=600, video_width=600, concat_type='mosaic')
55
+ >>> merger.run()
56
+ """
57
+
58
+ def __init__( self,
59
+ concat_type: Literal["horizontal", "vertical", "mosaic", "mixed_mosaic"],
60
+ video_paths: List[Union[str, os.PathLike]],
61
+ video_height: Optional[int] = None,
62
+ video_width: Optional[int] = None,
63
+ config_path: Optional[str] = None,
64
+ quality: int = 23,
65
+ gpu: bool = False):
66
+
67
+ if gpu and not check_nvidea_gpu_available():
68
+ raise FFMPEGCodecGPUError(msg="NVIDEA GPU not available (as evaluated by nvidea-smi returning None", source=self.__class__.__name__)
69
+ check_ffmpeg_available()
70
+ check_str(name=f"{FrameMergererFFmpeg.__name__} concat_type", value=concat_type, options=ACCEPTED_TYPES)
71
+ check_valid_lst(data=video_paths, source=f"{self.__class__.__name__} video_paths", valid_dtypes=(str,), min_len=2)
72
+ check_valid_boolean(value=gpu, source=f'{self.__class__.__name__} gpu', raise_error=True)
73
+ self.quality = 23 if not check_int(name='quality', value=quality, min_value=0, max_value=52, raise_error=False)[0] else int(quality)
74
+ for i in video_paths:
75
+ check_file_exist_and_readable(file_path=i)
76
+ if concat_type != MIXED_MOSAIC:
77
+ check_int(name=f"{FrameMergererFFmpeg.__name__} video_height", value=video_height, min_value=0)
78
+ check_int(name=f"{FrameMergererFFmpeg.__name__} video_width", value=video_height, min_value=0)
79
+ if config_path is not None:
80
+ ConfigReader.__init__(self, config_path=config_path)
81
+ log_event(logger_name=str(__class__.__name__), log_type=TagNames.CLASS_INIT.value, msg=self.create_log_msg_from_init_args(locals=locals()))
82
+ self.output_dir = os.path.join(self.project_path, Paths.CONCAT_VIDEOS_DIR.value)
83
+ self.output_path = os.path.join(self.project_path, Paths.CONCAT_VIDEOS_DIR.value, f"merged_video_{self.datetime}.mp4")
84
+ else:
85
+ self.timer = SimbaTimer(start=True)
86
+ self.datetime = datetime.now().strftime("%Y%m%d%H%M%S")
87
+ self.output_dir, _, _ = get_fn_ext(filepath=video_paths[0])
88
+ self.output_path = os.path.join(self.output_dir, f"merged_video_{self.datetime}.mp4")
89
+
90
+ self.video_height, self.video_width, self.gpu = video_height, video_width, gpu
91
+ self.video_paths, self.concat_type = video_paths, concat_type
92
+ if not os.path.exists(self.output_dir): os.makedirs(self.output_dir)
93
+
94
+ def run(self):
95
+ if self.concat_type == HORIZONTAL:
96
+ _ = horizontal_video_concatenator(video_paths=self.video_paths, save_path=self.output_path, height_px=self.video_height, gpu=self.gpu, quality=self.quality, verbose=True)
97
+ elif self.concat_type == VERTICAL:
98
+ _ = vertical_video_concatenator(video_paths=self.video_paths, save_path=self.output_path, width_px=self.video_width, gpu=self.gpu, quality=self.quality, verbose=True)
99
+ elif self.concat_type == MOSAIC:
100
+ _ = mosaic_concatenator(video_paths=self.video_paths, save_path=self.output_path, width_px=self.video_width, height_px=self.video_height, gpu=self.gpu, quality=self.quality, verbose=True)
101
+ else:
102
+ _ = mixed_mosaic_concatenator(video_paths=self.video_paths, save_path=self.output_path, gpu=self.gpu, verbose=True)
103
+ self.timer.stop_timer()
104
+ stdout_success(msg=f"Merged video saved at {self.output_path}", source=self.__class__.__name__, elapsed_time=self.timer.elapsed_time_str)
105
+
106
+
107
+ # videos = ['/Users/simon/Desktop/envs/simba/troubleshooting/mouse_open_field/project_folder/videos/SI_DAY3_308_CD1_PRESENT_downsampled.mp4', '/Users/simon/Desktop/envs/simba/troubleshooting/mouse_open_field/project_folder/videos/SI_DAY3_308_CD1_PRESENT_downsampled.mp4']
108
+ #
109
+ # merger = FrameMergererFFmpeg(config_path='/Users/simon/Desktop/envs/simba/troubleshooting/two_black_animals_14bp/project_folder/project_config.ini',
110
+ # video_paths=videos,
111
+ # video_height=600,
112
+ # video_width=600,
113
+ # concat_type='vertical') #horizontal, vertical, mosaic, mixed_mosaic
114
+ # merger.run()
115
+
116
+
117
+ #
118
+ # FrameMergererFFmpeg(config_path=None,
119
+ # frame_types={'Video 1': '/Users/simon/Desktop/envs/troubleshooting/two_black_animals_14bp/project_folder/videos/Together_1.avi',
120
+ # 'Video 2': '/Users/simon/Desktop/envs/troubleshooting/two_black_animals_14bp/project_folder/videos/Together_1.avi'},
121
+ # video_height=640,
122
+ # video_width=480,
123
+ # concat_type='vertical') #horizontal, vertical, mosaic, mixed_mosaic
124
+ #
125
+ #
126
+
127
+
128
+ # FrameMergererFFmpeg(config_path=None,
129
+ # frame_types={'Video 1': r'C:\Users\Nape_Computer_2\Desktop\test_videos\Box1_PM2_day_5_20211104T171021.mp4',
130
+ # 'Video 2': r'C:\Users\Nape_Computer_2\Desktop\test_videos\Box1_PM2_day_5_20211104T171021.mp4',
131
+ # 'Video 3': r'C:\Users\Nape_Computer_2\Desktop\test_videos\Box1_PM2_day_5_20211104T171021.mp4',
132
+ # 'Video 4': r'C:\Users\Nape_Computer_2\Desktop\test_videos\Box1_PM2_day_5_20211104T171021.mp4'},
133
+ # video_height=640,
134
+ # video_width=480,
135
+ # concat_type='mixed_mosaic',
136
+ # gpu=False) #horizontal, vertical, mosaic, mixed_mosaic
137
+ #