@@ -221,7 +221,7 @@ def _get_video_frames_count(video_path):
221221 return total_num_of_frames
222222
223223
224- def _get_video_fps_ration (target_fps ,video ,ratio ):
224+ def _get_video_fps_ration (target_fps , video , ratio ):
225225 """
226226 Get video fps / target fps ratio
227227 """
@@ -230,7 +230,7 @@ def _get_video_fps_ration(target_fps,video,ratio):
230230 logger .warning (
231231 "Video frame rate %s smaller than target frame rate %s. Cannot change frame rate." ,
232232 video_fps , target_fps
233- )
233+ )
234234 else :
235235 logger .info (
236236 "Changing video frame rate from %s to target frame rate %s." ,
@@ -239,22 +239,24 @@ def _get_video_fps_ration(target_fps,video,ratio):
239239 ratio = video_fps / target_fps
240240 return ratio
241241
242- def _get_available_image_counts (project ,folder ):
242+
243+ def _get_available_image_counts (project , folder ):
243244 if folder :
244245 folder_id = folder ["id" ]
245246 else :
246247 folder_id = get_project_root_folder_id (project )
247- params = {'team_id' : project ['team_id' ] , 'folder_id' : folder_id }
248- res = _get_upload_auth_token (params = params ,project_id = project ['id' ])
248+ params = {'team_id' : project ['team_id' ], 'folder_id' : folder_id }
249+ res = _get_upload_auth_token (params = params , project_id = project ['id' ])
249250 return res ['availableImageCount' ]
250251
252+
251253def _get_video_rotate_code (video_path ):
252254 rotate_code = None
253255 try :
254256 cv2_rotations = {
255- 90 : cv2 .ROTATE_90_CLOCKWISE ,
256- 180 : cv2 .ROTATE_180 ,
257- 270 : cv2 .ROTATE_90_COUNTERCLOCKWISE ,
257+ 90 : cv2 .ROTATE_90_CLOCKWISE ,
258+ 180 : cv2 .ROTATE_180 ,
259+ 270 : cv2 .ROTATE_90_COUNTERCLOCKWISE ,
258260 }
259261
260262 meta_dict = ffmpeg .probe (str (video_path ))
@@ -276,14 +278,26 @@ def _get_video_rotate_code(video_path):
276278 return rotate_code
277279
278280
279- def _extract_frames_from_video (start_time ,end_time ,ratio ,video ,video_path ,tempdir ,limit ,rotate_code ,total_num_of_frames ):
281+ def _extract_frames_from_video (
282+ start_time , end_time , video_path , tempdir , limit , target_fps
283+ ):
284+ video = cv2 .VideoCapture (str (video_path ), cv2 .CAP_FFMPEG )
285+ if not video .isOpened ():
286+ raise SABaseException (0 , "Couldn't open video file " + str (video_path ))
287+ total_num_of_frames = _get_video_frames_count (video_path )
288+ logger .info ("Video frame count is %s." , total_num_of_frames )
289+ ratio = 1.0
290+ if target_fps :
291+ ratio = _get_video_fps_ration (target_fps , video , ratio )
292+ rotate_code = _get_video_rotate_code (video_path )
280293 video_name = Path (video_path ).stem
281294 frame_no = 0
282295 frame_no_with_change = 1.0
283296 extracted_frame_no = 1
284297 logger .info ("Extracting frames from video to %s." , tempdir .name )
285298 zero_fill_count = len (str (total_num_of_frames ))
286- while extracted_frame_no < (limit + 1 ) :
299+ extracted_frames_paths = []
300+ while len (extracted_frames_paths ) < limit :
287301 success , frame = video .read ()
288302 if not success :
289303 break
@@ -298,16 +312,16 @@ def _extract_frames_from_video(start_time,end_time,ratio,video,video_path,tempdi
298312 continue
299313 if rotate_code :
300314 frame = cv2 .rotate (frame , rotate_code )
301- cv2 .imwrite (
302- str (
303- Path (tempdir .name ) / (
304- video_name + "_" +
305- str (extracted_frame_no ).zfill (zero_fill_count ) + ".jpg"
306- )
307- ), frame
315+ path = str (
316+ Path (tempdir .name ) / (
317+ video_name + "_" +
318+ str (extracted_frame_no ).zfill (zero_fill_count ) + ".jpg"
319+ )
308320 )
321+ cv2 .imwrite (path , frame )
322+ extracted_frames_paths .append (path )
309323 extracted_frame_no += 1
310- return extracted_frame_no - 1
324+ return extracted_frames_paths
311325
312326
313327def upload_video_to_project (
@@ -345,7 +359,7 @@ def upload_video_to_project(
345359 """
346360
347361 project , folder = get_project_and_folder_metadata (project )
348- limit = _get_available_image_counts (project ,folder )
362+ limit = _get_available_image_counts (project , folder )
349363
350364 upload_state = common .upload_state_int_to_str (project .get ("upload_state" ))
351365 if upload_state == "External" :
@@ -354,23 +368,13 @@ def upload_video_to_project(
354368 "The function does not support projects containing images attached with URLs"
355369 )
356370 logger .info ("Uploading from video %s." , str (video_path ))
357- rotate_code = _get_video_rotate_code (video_path )
358- video = cv2 .VideoCapture (str (video_path ), cv2 .CAP_FFMPEG )
359- if not video .isOpened ():
360- raise SABaseException (0 , "Couldn't open video file " + str (video_path ))
361-
362- total_num_of_frames = _get_video_frames_count (video_path )
363- logger .info ("Video frame count is %s." , total_num_of_frames )
364- ratio = 1.0
365- if target_fps :
366- ratio = _get_video_fps_ration (target_fps ,video ,ratio )
367371 tempdir = tempfile .TemporaryDirectory ()
368- extracted_frame_no = _extract_frames_from_video (start_time , end_time , ratio ,
369- video , video_path ,tempdir ,
370- limit , rotate_code , total_num_of_frames )
372+ extracted_frames = _extract_frames_from_video (
373+ start_time , end_time , video_path , tempdir , limit , target_fps
374+ )
371375 logger .info (
372376 "Extracted %s frames from video. Now uploading to platform." ,
373- extracted_frame_no
377+ len ( extracted_frames )
374378 )
375379 filenames = upload_images_from_folder_to_project (
376380 (project , folder ),
@@ -853,9 +857,7 @@ def upload_images_to_project(
853857 :rtype: tuple (3 members) of list of strs
854858 """
855859 project , folder = get_project_and_folder_metadata (project )
856- folder_name = project ["name" ] + (
857- f'/{ folder ["name" ]} ' if folder else ""
858- )
860+ folder_name = project ["name" ] + (f'/{ folder ["name" ]} ' if folder else "" )
859861 upload_state = common .upload_state_int_to_str (project .get ("upload_state" ))
860862 if upload_state == "External" :
861863 raise SABaseException (
@@ -895,24 +897,23 @@ def upload_images_to_project(
895897 if len_img_paths == 0 :
896898 return ([], [], duplicate_images )
897899
898-
899900 if folder :
900901 folder_id = folder ["id" ]
901902 else :
902903 folder_id = get_project_root_folder_id (project )
903904
904- params = {'team_id' : team_id , 'folder_id' : folder_id }
905+ params = {'team_id' : team_id , 'folder_id' : folder_id }
905906 uploaded = [[] for _ in range (_NUM_THREADS )]
906907 tried_upload = [[] for _ in range (_NUM_THREADS )]
907908 couldnt_upload = [[] for _ in range (_NUM_THREADS )]
908909 finish_event = threading .Event ()
909910
910- res = _get_upload_auth_token (params = params ,project_id = project_id )
911+ res = _get_upload_auth_token (params = params , project_id = project_id )
911912
912913 prefix = res ['filePath' ]
913914 limit = res ['availableImageCount' ]
914915 images_to_upload = img_paths [:limit ]
915- images_to_skip = img_paths [limit :]
916+ images_to_skip = [ str ( path ) for path in img_paths [limit :] ]
916917 chunksize = int (math .ceil (len (images_to_upload ) / _NUM_THREADS ))
917918
918919 tqdm_thread = threading .Thread (
@@ -927,8 +928,8 @@ def upload_images_to_project(
927928 t = threading .Thread (
928929 target = __upload_images_to_aws_thread ,
929930 args = (
930- res , images_to_upload , project , annotation_status , prefix , thread_id ,
931- chunksize , couldnt_upload , uploaded , tried_upload ,
931+ res , images_to_upload , project , annotation_status , prefix ,
932+ thread_id , chunksize , couldnt_upload , uploaded , tried_upload ,
932933 image_quality_in_editor , from_s3_bucket , folder_id
933934 ),
934935 daemon = True
@@ -987,9 +988,7 @@ def attach_image_urls_to_project(
987988 """
988989
989990 project , folder = get_project_and_folder_metadata (project )
990- folder_name = project ["name" ] + (
991- f'/{ folder ["name" ]} ' if folder else ""
992- )
991+ folder_name = project ["name" ] + (f'/{ folder ["name" ]} ' if folder else "" )
993992 upload_state = common .upload_state_int_to_str (project .get ("upload_state" ))
994993 if upload_state == "Basic" :
995994 raise SABaseException (
@@ -1027,8 +1026,7 @@ def attach_image_urls_to_project(
10271026 image_data = pd .DataFrame (image_data , columns = ["name" , "url" ])
10281027 img_names_urls = image_data .values .tolist ()
10291028 logger .info (
1030- "Uploading %s images to project %s." , len (img_names_urls ),
1031- folder_name
1029+ "Uploading %s images to project %s." , len (img_names_urls ), folder_name
10321030 )
10331031 if len (img_names_urls ) == 0 :
10341032 return ([], [], duplicate_images )
@@ -1038,14 +1036,14 @@ def attach_image_urls_to_project(
10381036 else :
10391037 folder_id = get_project_root_folder_id (project )
10401038
1041- params = {'team_id' : team_id , 'folder_id' : folder_id }
1039+ params = {'team_id' : team_id , 'folder_id' : folder_id }
10421040 uploaded = [[] for _ in range (_NUM_THREADS )]
10431041 tried_upload = [[] for _ in range (_NUM_THREADS )]
10441042 couldnt_upload = [[] for _ in range (_NUM_THREADS )]
10451043 finish_event = threading .Event ()
10461044
1047- res = _get_upload_auth_token (params = params ,project_id = project_id )
1048-
1045+ res = _get_upload_auth_token (params = params , project_id = project_id )
1046+
10491047 prefix = res ['filePath' ]
10501048 limit = res ['availableImageCount' ]
10511049 images_to_upload = img_names_urls [:limit ]
@@ -1084,7 +1082,7 @@ def attach_image_urls_to_project(
10841082 for f in upload_thread :
10851083 list_of_uploaded .append (str (f ))
10861084
1087- list_of_not_uploaded += [i [0 ] for i in images_to_skip ]
1085+ list_of_not_uploaded += [i [0 ] for i in images_to_skip ]
10881086 return (list_of_uploaded , list_of_not_uploaded , duplicate_images )
10891087
10901088
0 commit comments