1.实现代码
最开始的版本是使用opencv实现的,但是在实施的过程中,发现opencv在读取视频帧的时候,有的时候ret, frame = capture.read()
中的返回值ret
有时会为False
,会存为错误的1帧,所以改用ffmpeg实现。
使用多线程的ffmpeg实现代码如下:
# 将UCF101数据集中的视频提取为帧
from __future__ import print_function, division
import os
import sys
import subprocess
from multiprocessing import Pool
from tqdm import tqdm
n_thread = 30
# file_name: v_ApplyEyeMakeup_g01_c01.avi
# class_path: xxx/Videos/ApplyEyeMakeup
# dst_class_path: xxx/jpgs/ApplyEyeMakeup
def vid2jpg(file_name, class_path, dst_dir_path):
if '.avi' not in file_name:
return
name, ext = os.path.splitext(file_name)
dst_directory_path = os.path.join(dst_dir_path, name) # dst_directory_path: xxx/jpgs/v_ApplyEyeMakeup_g01_c01
video_file_path = os.path.join(class_path, file_name) # video_file_path: xxx/Videos/ApplyEyeMakeup/v_ApplyEyeMakeup_g01_c01.avi
try:
if os.path.exists(dst_directory_path):
if not os.path.exists(os.path.join(dst_directory_path, 'img_00001.jpg')):
subprocess.call('rm -r \"{}\"'.format(dst_directory_path), shell=True)
print('remove {}'.format(dst_directory_path))
os.mkdir(dst_directory_path)
else:
print('*** convert has been done: {}'.format(dst_directory_path))
return
else:
os.mkdir(dst_directory_path)
except:
print(dst_directory_path)
return
cmd = 'ffmpeg -i \"{}\" -threads 1 -vf scale=-1:331 -q:v 0 \"{}/img_%05d.jpg\"'.format(video_file_path, dst_directory_path)
# print(cmd)
subprocess.call(cmd, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
def class_process(dir_path, dst_dir_path, class_name): # dir_path: xxx/Videos dst_dir_path: xxx/jpgs ApplyEyeMakeup
print('*' * 20, class_name, '*'*20)
class_path = os.path.join(dir_path, class_name) # class_path: xxx/Videos/ApplyEyeMakeup
if not os.path.isdir(class_path):
print('*** is not a dir {}'.format(class_path))
return
# dst_class_path = os.path.join(dst_dir_path, class_name) # dst_class_path: xxx/jpgs/ApplyEyeMakeup
# if not os.path.exists(dst_class_path):
# os.mkdir(dst_class_path)
vid_list = os.listdir(class_path)
vid_list.sort()
p = Pool(n_thread)
from functools import partial
worker = partial(vid2jpg, class_path=class_path, dst_dir_path=dst_dir_path)
for _ in tqdm(p.imap_unordered(worker, vid_list), total=len(vid_list)):
pass
# p.map(worker, vid_list)
p.close()
p.join()
print('\n')
if __name__ == "__main__":
dir_path = sys.argv[1] # /home/xxx/data/projects/datasets/UCF101/Videos
dst_dir_path = sys.argv[2] # /home/xxx/data/projects/datasets/UCF101/jpgs
class_list = os.listdir(dir_path)
class_list.sort()
for class_name in class_list: # class_name: ApplyEyeMakeup
class_process(dir_path, dst_dir_path, class_name)