OpenCV实现按指定间隔抽取视频中的图像帧
习惯了C++语言的OpenCV突然用Python语言OpenCV还是感觉有点不适应,但是慢慢在写的过程中,觉得Python语言的风格也挺美的(但自己的写的还是很丑…),晚上回宿舍的剩余时间,记录一下最近用PythonOpenCV实现的视频抽帧小工具。
实现代码
2022/9/26更新:将while循环中连续帧读取再根据条件保存关键帧的代码改为通过OpenCVVideoCapture::set()
函数传入cv2.CAP_PROP_POS_FRAMES
参数和帧间隔实现每次循环读取直接跳到关键帧并保存(其实就是快进功能)
参数解读:
cv2.CAP_PROP_POS_FRAMES
: 接下来要解码/捕获的帧(基于0的索引)
代码就是逻辑关系,简单记录一下:
import cv2
import os
import numpy as np# video所在的根目录
video_base_path = "F:/my_Video/RowVideo"
# processVideo所在根目录
save_base_path = "F:/my_Video/ProcessVideo"
# 保存抽取的图像帧时所在的根目录
JPEGImage_base_path = "./JPEGImage"# ******************指定提取图像帧的模式********************* #
# model = 0 以帧间隔提取, model = 1以秒间隔提取
extract_frame_model = 0def form_single_channel_video(video_name: str, save_name: str, channel: int):"""提取RGB中某通道形成一个单通道图像:param video_name: 输入根目录文件夹下video_name,eg. test.mp4:param save_name: 输入保存视频的name,eg. protest.mp4:param channel: 需要的提取的channel -->(0, 1, 2):return: None"""video_path = os.path.join(video_base_path, video_name)save_path = os.path.join(save_base_path, save_name)inputVideo = cv2.VideoCapture(video_path)if not inputVideo.isOpened():raise IOError("current video path is not exist!")ex = int(inputVideo.get(cv2.CAP_PROP_FOURCC))Size = (int(inputVideo.get(cv2.CAP_PROP_FRAME_WIDTH)), int(inputVideo.get(cv2.CAP_PROP_FRAME_HEIGHT)))fps = int(inputVideo.get(cv2.CAP_PROP_FPS))total_frame = inputVideo.get(cv2.CAP_PROP_FRAME_COUNT)# 写入视频的文件路径 opencv的Size参数是(width,height)outputVideo = cv2.VideoWriter(save_path, ex, fps, Size, True)if not outputVideo.isOpened():raise IOError("no way to open the save path, please restart")print("input frame resolution: width=%d height=%d, fps=%d, the total frame=%d"% (Size[0], Size[1], fps, total_frame))while inputVideo.isOpened():ret, frame = inputVideo.read()if not ret:break(B, G, R) = cv2.split(frame)zeros = np.zeros(np.shape(frame)[:2], dtype="uint8")output = np.zeros(np.shape(frame), dtype="uint8")if channel == 0:output = cv2.merge([B, zeros, zeros])elif channel == 1:output = cv2.merge([zeros, G, zeros])else:output = cv2.merge([zeros, zeros, R])# 将帧写入视频outputVideo.write(output)cv2.imshow("frame", frame)cv2.imshow("output", output)key = cv2.waitKey(1)if key == ord('q'):breakprint("clearing up!")cv2.destroyAllWindows()inputVideo.release()outputVideo.release()def plus_shot_video_frame(video_name: str, image_save_path: str = None, frequency: int = 1, second: int = 1):"""根据mode实现的不同形式的抽帧方式,当mode==0,按指定的帧间隔抽帧,mode==1,按指定的秒间隔进行抽帧:param video_name: 输入根目录文件夹下的video name,eg. test.mp4:param image_save_path: 当为None时默认在video所在文件中创建一个同名一个与video同名的文件中用于保存图像帧,否则输入绝对路径:param frequency: 当mode为0时,该参数启用,表示设置的帧间隔:param second: 当mode为1时,该参数启用,表示设置的秒间隔:return: None"""actual_video_name = video_name.split('.')[0] # 提取真正的文件夹名称if image_save_path is None:image_save_path = os.path.join(video_base_path, actual_video_name)if not os.path.exists(image_save_path):os.makedirs(image_save_path)video_path = os.path.join(video_base_path, video_name)inputVideo = cv2.VideoCapture(video_path)if not inputVideo.isOpened():raise IOError("current video path is not exist!")Size = (int(inputVideo.get(cv2.CAP_PROP_FRAME_WIDTH)), int(inputVideo.get(cv2.CAP_PROP_FRAME_HEIGHT)))fps = int(inputVideo.get(cv2.CAP_PROP_FPS))total_frame = inputVideo.get(cv2.CAP_PROP_FRAME_COUNT)print("input frame resolution: width=%d height=%d, fps=%d, the total frame=%d"% (Size[0], Size[1], fps, total_frame))num_frame = 0 # 帧计数if extract_frame_model == 0:frame_gap = frequencyelse:frame_gap = int(second * fps)start_time = time.time() # 时间测算# 循环读取每一帧,根据model来确定抽帧模式while True:ret_success, frame = inputVideo.read()if not ret_success:print("extract frame from video fail, current frame=%d" % num_frame)break# frame = cv2.resize(frame, dsize=None, fx=0.5, fy=0.5, interpolation=cv2.INTER_LINEAR)image_name = actual_video_name + str(round(num_frame / frame_gap)) + '.jpg'cv2.imwrite(os.path.join(image_save_path, image_name), frame)print("saved " + str(round(num_frame / frame_gap)) + '.jpg')num_frame += frame_gap # 更新帧计数inputVideo.set(cv2.CAP_PROP_POS_FRAMES, num_frame) # 隔帧读取end_time = time.time()print("time consuming: {:.2f}second".format(end_time - start_time))print("cleaning up!")inputVideo.release()if __name__ == "__main__":video_name = 'shotTestVideo.MP4'shot_video_frame(video_name, frequency=20)
实现结果
终端打印
图片文件夹
总结
发现对于视频流的解码过程几乎不了解,对于倍数播放,当视频分辨率过大(4K)时,几乎没有效果,要想达到potplayer的效果还有很长的一段路要走。
OpenCV实现按指定间隔抽取视频中的图像帧相关推荐
- 使用ffmpeg从视频中截取图像帧(最简单实用的视频抽帧,一句命令)
Table of Contents 1.最佳方式 2.普通的命令:(画质差) 3. 视频旋转: 4. 批量视频抽帧: 参考:ffmpeg视频抽帧 1.最佳方式 第二种方法抽帧图片画质很差,这里提供更好 ...
- 教你在多个视频中随机抽帧画面出来,置入到各个视频封面上
通过抽帧在视频里随机抽取一幅画面图片出来,再次导入到各个视频上作为封面图片,这种的剪辑该如何操作呢?下面我们用一个媒体梦工厂剪辑的工具就可实现,一起看详细教程操作. 准备多个视频保存在同一文件夹中,可 ...
- mpeg4视频中,I帧、p帧、B帧的判定
mpeg4视频中,I帧.p帧.B帧的判定 mpeg4的每一帧开头是固定的:00 00 01 b6,那么我们如何判断当前帧属于什么帧呢?在接下来的2bit,将会告诉我们答案.注意:是2bit,不是byt ...
- 批量剪辑,截取视频中某一帧画面保存为图片
平时刷视频的时候看到好看的画面就想截图保存,那么如何批量提取视频中的某一帧画面呢?不知道怎么操作的朋友走过路过不要错过,小编分享一个方法演示具体的操作步骤,一起来看看. 运行[媒体梦工厂]这款软件中有 ...
- 在视频中实现图像特效
by fanxiushu 2020-06-24 转载或引用请注明原始作者. 说起图像特效,可以打开Photoshop软件,里边有个"滤镜"菜单,再到"滤镜"里边 ...
- python OpenCV 按时间间隔截取视频中任意片段帧
通过视频制作相应的数据集,截取视频中的任意片段帧. 使用python截取视频中的任意片段帧,直接上代码: import cv2 import os# 定义视频文件路径和保存图像文件路径 video_p ...
- Python使用OpenCV+pillow提取AVI视频中关键帧图像
问题描述:使用OpenCV把AVI视频切分成静态图像,提取视频中的关键帧,保存为0.jpg.1.jpg.2.jpg....... 实现步骤: 1)安装扩展库 2)准备一个AVI视频,这里以微课系列(5 ...
- 【OpenCV人脸识别2】从视频中检测人脸
分为两步: 从视频中识别人脸和人的眼睛 从视频中检测人脸.眼睛.鼻子.嘴巴 1.从视频中识别人脸和人的眼睛 关于视频的操作,主要如下: 定义摄像头->打开摄像头->读取视频帧->转而 ...
- Matlab从视频中提取图像,可以设定每多少秒提取1帧。
刚刚数学建模比赛,提取视频中的照片. 解释下: 1. 这个27941是秒数,就是提取视频多少秒.如果整个视频提取的话,可以用VideoAd.Duration即视频总长度替代. video.FrameR ...
最新文章
- loadrunner11下载地址
- 关于idea打开项目没有目录
- Python 实现图片质量比较之PSNR和SSIM
- Linux脚本让我选择文件,linux – 用于选择文件和打印文件大小的Awk脚本
- VTK:Picking之CellPicking
- 【直观理解】一文搞懂RNN(循环神经网络)基础篇
- Vue 进阶教程之:详解 v-model
- Andoid开发中生成二维码
- MediaWiki/安装
- [bzoj4813][Cqoi2017]小Q的棋盘
- Email - 搭建自定义邮件服务器
- 自动驾驶——为什么需要仿真?
- ALS算法的基本思想
- python 计时器模块_python中计时器
- CAR路里大学堂-汽车测试培训(CANOE)
- 炎颂科技管理系统软件——助力商协会“互联网+”之路
- CMD命令全集(转)
- 「Spring Boot」接口幂等性的4种实现方案
- Verilog中 reg和wire 用法 以及always和assign的区别
- 笔记整理--Linux守护进程
热门文章
- Java使用apache.http.client.fluent快速构建HTTP请求
- WD西部数据硬盘数据丢失了免费恢复方法
- TIA博途WinCC PRO V16 画面分辨率的设置方法
- 做一个有温度有条理的表达者
- 汽车悬架matlab时域和频域,车辆悬架系统振动控制(精)
- html下拉框属性js,Html下拉框Js对象属性方法总结
- 高等数学660---从179到185
- 易飞ERP软件用户组及权限设定-易飞ERP免费教程 转载
- 计算机科学与技术肄业后怎么继续完成学业,学籍学分问题解答
- Kali安装常用的软件工具——第二课