Skip to content

Commit d933d1b

Browse files
committed
Fix fps
1 parent 537e365 commit d933d1b

File tree

1 file changed

+37
-28
lines changed

1 file changed

+37
-28
lines changed

superannotate/db/projects.py

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ def _get_target_frames_count(video_path, target_fps):
215215
"""
216216
Get video frames count
217217
"""
218+
# deprecated : because cv2.CAP_PROP_FPS in not reliable
218219
video = cv2.VideoCapture(str(video_path), cv2.CAP_FFMPEG)
219220
total_num_of_frames = 0
220221
flag = True
@@ -225,7 +226,7 @@ def _get_target_frames_count(video_path, target_fps):
225226
else:
226227
break
227228

228-
return math.ceil((total_num_of_frames*target_fps) / video.get(cv2.CAP_PROP_FPS))
229+
return math.ceil((total_num_of_frames * target_fps) / video.get(cv2.CAP_PROP_FPS))
229230

230231

231232
def _get_video_frames_count(video_path):
@@ -244,22 +245,22 @@ def _get_video_frames_count(video_path):
244245
return total_num_of_frames
245246

246247

247-
def _get_video_fps_ration(target_fps, video, ratio):
248+
def _get_video_fps_ration(target_fps, video, ratio, log):
248249
"""
249250
Get video fps / target fps ratio
250251
"""
251252
video_fps = float(video.get(cv2.CAP_PROP_FPS))
252-
if target_fps >= video_fps:
253+
if target_fps >= video_fps and log:
253254
logger.warning(
254255
"Video frame rate %s smaller than target frame rate %s. Cannot change frame rate.",
255256
video_fps, target_fps
256257
)
257258
else:
258-
259-
logger.info(
260-
"Changing video frame rate from %s to target frame rate %s.",
261-
video_fps, target_fps
262-
)
259+
if log:
260+
logger.info(
261+
"Changing video frame rate from %s to target frame rate %s.",
262+
video_fps, target_fps
263+
)
263264
ratio = video_fps / target_fps
264265
return ratio
265266

@@ -274,7 +275,7 @@ def _get_available_image_counts(project, folder):
274275
return res['availableImageCount']
275276

276277

277-
def _get_video_rotate_code(video_path):
278+
def _get_video_rotate_code(video_path, log=True):
278279
rotate_code = None
279280
try:
280281
cv2_rotations = {
@@ -286,42 +287,43 @@ def _get_video_rotate_code(video_path):
286287
meta_dict = ffmpeg.probe(str(video_path))
287288
rot = int(meta_dict['streams'][0]['tags']['rotate'])
288289
rotate_code = cv2_rotations[rot]
289-
if rot != 0:
290+
if rot != 0 and log:
290291
logger.info(
291292
"Frame rotation of %s found. Output images will be rotated accordingly.",
292293
rot
293294
)
294295
except Exception as e:
295296
warning_str = ""
296-
if "ffprobe" in str(e):
297+
if "ffprobe" in str(e) and log:
297298
warning_str = "This could be because ffmpeg package is not installed. To install it, run: sudo apt install ffmpeg"
298299

299-
logger.warning(
300-
"Couldn't read video metadata to determine rotation. %s",
301-
warning_str
302-
)
300+
if log:
301+
logger.warning(
302+
"Couldn't read video metadata to determine rotation. %s",
303+
warning_str
304+
)
303305
return rotate_code
304306

305307

306308
def _extract_frames_from_video(
307-
start_time, end_time, video_path, tempdir, limit, target_fps, chunk_size
309+
start_time, end_time, video_path, tempdir, limit, target_fps, chunk_size, save
308310
):
309311
video = cv2.VideoCapture(str(video_path), cv2.CAP_FFMPEG)
310312
if not video.isOpened():
311313
raise SABaseException(0, "Couldn't open video file " + str(video_path))
312314
total_num_of_frames = _get_video_frames_count(video_path)
313-
314-
logger.info("Video frame count is %s.", total_num_of_frames)
315+
if save:
316+
logger.info("Video frame count is %s.", total_num_of_frames)
315317
ratio = 1.0
316318
if target_fps:
317-
ratio = _get_video_fps_ration(target_fps, video, ratio)
318-
rotate_code = _get_video_rotate_code(video_path)
319+
ratio = _get_video_fps_ration(target_fps, video, ratio, log=save)
320+
rotate_code = _get_video_rotate_code(video_path, log=save)
319321
video_name = Path(video_path).stem
320322
frame_no = 0
321323
frame_no_with_change = 1.0
322324
extracted_frame_no = 1
323-
324-
logger.info("Extracting frames from video to %s.", tempdir.name)
325+
if save:
326+
logger.info("Extracting frames from video to %s.", tempdir.name)
325327
zero_fill_count = len(str(total_num_of_frames))
326328
extracted_frames_paths = []
327329
all_paths = []
@@ -346,8 +348,8 @@ def _extract_frames_from_video(
346348
str(extracted_frame_no).zfill(zero_fill_count) + ".jpg"
347349
)
348350
)
349-
350-
cv2.imwrite(path, frame)
351+
if save:
352+
cv2.imwrite(path, frame)
351353
extracted_frames_paths.append(path)
352354
extracted_frame_no += 1
353355
if len(extracted_frames_paths) % chunk_size == 0:
@@ -362,6 +364,7 @@ def _extract_frames_from_video(
362364
yield q
363365
return extracted_frames_paths
364366

367+
365368
@Trackable
366369
def upload_video_to_project(
367370
project,
@@ -420,10 +423,16 @@ def upload_video_to_project(
420423
tempdir = tempfile.TemporaryDirectory()
421424
upload_file_names = []
422425
chunk_size = 100
423-
all_frames_count = _get_target_frames_count(video_path, target_fps)
426+
all_frames_count = 0
427+
428+
for frames_path in _extract_frames_from_video(
429+
start_time, end_time, video_path, tempdir, limit, target_fps, chunk_size, False
430+
):
431+
all_frames_count += len(frames_path)
432+
424433
pbar = None
425434
for _ in _extract_frames_from_video(
426-
start_time, end_time, video_path, tempdir, limit, target_fps, chunk_size
435+
start_time, end_time, video_path, tempdir, limit, target_fps, chunk_size, save=True
427436
):
428437
if not pbar:
429438
pbar = tqdm(total=all_frames_count)
@@ -471,7 +480,7 @@ def upload_videos_from_folder_to_project(
471480
:type project: str
472481
:param folder_path: from which folder to upload the videos
473482
:type folder_path: Pathlike (str or Path)
474-
:param extensions: tuple or list of filename extensions to include from folder
483+
:param extensions: tuple or list of filename extensions to include from folder
475484
:type extensions: tuple or list of strs
476485
:param exclude_file_patterns: filename patterns to exclude from uploading
477486
:type exclude_file_patterns: listlike of strs
@@ -751,7 +760,7 @@ def attach_image_urls_to_project(
751760
project, attachments, annotation_status="NotStarted"
752761
):
753762
"""Link images on external storage to SuperAnnotate.
754-
763+
755764
:param project: project name or project folder path
756765
:type project: str or dict
757766
:param attachments: path to csv file on attachments metadata

0 commit comments

Comments
 (0)