使用OpenCV实现逐帧获取视频图片
作者:学习BigData
这篇文章主要为大家详细介绍了如何使用OpenCV实现逐帧获取视频中的图片用来标注,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
背景
由于我要做一个深度学习方向的计算机视觉项目,需要一些数据集来进行训练,我便想尝试捕获视频中的图片用来标注。
注意事项
如果视频中的场景单一,那么使用该视频获取的数据集训练出的模型面对其他场景的泛化能力就会受到限制。为了提高数据集的多样性,可以采用多种不同场景的视频,并且在获取数据时采用大间隔捕获的方式。采用大间隔捕获数据的方法可以捕获到的图片同质化降低,从而进一步增加数据集的多样性。
import os import sys from concurrent.futures import ThreadPoolExecutor import cv2 def output_img(video_path,img_dir): # 由视频逐帧输出图片 # video_path: 视频文件路径 # img_dir: 图片保存目录路径,路径不支持中文 os.makedirs(img_dir,exist_ok=True) # img_dir:表示要创建的目录路径。 # exist_ok=True:表示如果目录已经存在时不抛出异常。如果将 exist_ok 设置为 True,那么如果目录已经存在,os.makedirs() 函数也不会报错;如果设置为 False,则会抛出一个 FileExistsError 异常。 cv = cv2.VideoCapture(video_path) frame_count = 0 # 计数器 n = 0 # 命名计数器 while True: ret,frame = cv.read() if not ret: break frame_count += 1 if frame_count % 30 ==0: # 每隔三十帧获取一次图片 n += 1 img_name = "0000000{0}.jpg".format(n) img_file_path = os.path.join(img_dir,img_name) if not os.path.exists(img_file_path): sys.stdout.write("创建文件:"+ img_file_path + "\n") # 标准输出流,将指定文本输出到控制台或其他输出设备中 cv2.imwrite(img_file_path,frame,[cv2.IMWRITE_JPEG_QUALITY,100]) # 将图像帧保存为jepg格式的图像,质量最高为100 else: sys.stderr.write("跳过:" + img_file_path + "\n") ret,frame = cv.read() def run(video_dir,img_dir): pool = ThreadPoolExecutor() # 创建一个线程池对象,实例化ThreadPoolExecutor类,将任务提交给线程池,线程池会自动调度线程来执行这些任务 for file in os.listdir(video_dir): if file[-4:] == ".mp4": video_file_path = os.path.join(video_dir,file) img_dir_name = os.path.join(img_dir,file[:-4]) os.makedirs(img_dir_name,exist_ok=True) pool.submit(output_img,*(video_file_path,img_dir_name)) #* 和 ** 是用于解包参数的操作符。在这种情况下,*(video_file_path, img_dir_name) # 的作用是将元组 (video_file_path, img_dir_name) 中的元素解包并作为单独的参数传递给函数。 if __name__ == '__main__': run(r"E:\video",r"E:\image")
知识补充
除了上文的方法,小编还为大家整理了opencv按帧提取视频中的图片的相关方法,希望对大家有所帮助
方法一
import cv2 import logging # log information settings logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s: %(message)s') def save_image(num, image): image_path = 'D:\CODE\keras-face-recognition\jietu/{}.jpg'.format(str(num)) cv2.imwrite(image_path, image) vc = cv2.VideoCapture('1.avi') if vc.isOpened(): ret, frame = vc.read() else: ret = False count = 0 # 照片排序 frame_interval = 10 # 隔10帧取图片 frame_interval_count = 0 while ret: ret, frame = vc.read() if frame_interval_count % frame_interval == 0: save_image(count, frame) logging.info("num:" + str(count) + ", frame: " + str(frame_interval_count)) count += 1 frame_interval_count += 1 cv2.waitKey(1) vc.release()
方法二
import cv2 import os #要提取视频的文件名,隐藏后缀 sourceFileName='a2' #在这里把后缀接上 video_path = os.path.join("", "", sourceFileName+'.mp4') times=0 #提取视频的频率,每25帧提取一个 frameFrequency=25 #输出图片到当前目录vedio文件夹下 outPutDirName='vedio/'+sourceFileName+'/' if not os.path.exists(outPutDirName): #如果文件目录不存在则创建目录 os.makedirs(outPutDirName) camera = cv2.VideoCapture(video_path) while True: times+=1 res, image = camera.read() if not res: print('not res , not image') break if times%frameFrequency==0: cv2.imwrite(outPutDirName + str(times)+'.jpg', image) print(outPutDirName + str(times)+'.jpg') print('图片提取结束') camera.release()
方法三
import cv2 import os video_path = 'D:/BaiduNetdiskDownload/DISFA/Videos_LeftCamera/LeftVideoSN032_comp.avi' # 视频文件地址,是视频文件 timeF = 1 # 隔timeF帧截一次图,1表示全截 images_path = video_path.split('.', 1)[0] #.号隔开,1代表分割一次 if not os.path.exists(images_path): # 文件夹不存在则新建 os.mkdir(images_path) vc = cv2.VideoCapture(video_path) # 读入视频文件 c = 0 rat = 1 if vc.isOpened(): # 判断是否正常打开 print('视频读取成功,正在逐帧截取...') while rat: # 循环读取视频帧 rat, frame = vc.read() # frame为一帧图像,当frame为空时,ret返回false,否则为true if(c%timeF == 0 and rat == True): # 每隔timeF帧截一次图像 cv2.imwrite(images_path + '/' + str(c) + '.jpg',frame) c = c + 1 vc.release() print('截取完成,图像保存在:%s' %images_path) else: print('视频读取失败,请检查文件地址')
到此这篇关于使用OpenCV实现逐帧获取视频图片的文章就介绍到这了,更多相关OpenCV获取视频图片内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!