习惯了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实现按指定间隔抽取视频中的图像帧相关推荐

  1. 使用ffmpeg从视频中截取图像帧(最简单实用的视频抽帧,一句命令)

    Table of Contents 1.最佳方式 2.普通的命令:(画质差) 3. 视频旋转: 4. 批量视频抽帧: 参考:ffmpeg视频抽帧 1.最佳方式 第二种方法抽帧图片画质很差,这里提供更好 ...

  2. 教你在多个视频中随机抽帧画面出来,置入到各个视频封面上

    通过抽帧在视频里随机抽取一幅画面图片出来,再次导入到各个视频上作为封面图片,这种的剪辑该如何操作呢?下面我们用一个媒体梦工厂剪辑的工具就可实现,一起看详细教程操作. 准备多个视频保存在同一文件夹中,可 ...

  3. mpeg4视频中,I帧、p帧、B帧的判定

    mpeg4视频中,I帧.p帧.B帧的判定 mpeg4的每一帧开头是固定的:00 00 01 b6,那么我们如何判断当前帧属于什么帧呢?在接下来的2bit,将会告诉我们答案.注意:是2bit,不是byt ...

  4. 批量剪辑,截取视频中某一帧画面保存为图片

    平时刷视频的时候看到好看的画面就想截图保存,那么如何批量提取视频中的某一帧画面呢?不知道怎么操作的朋友走过路过不要错过,小编分享一个方法演示具体的操作步骤,一起来看看. 运行[媒体梦工厂]这款软件中有 ...

  5. 在视频中实现图像特效

    by fanxiushu 2020-06-24 转载或引用请注明原始作者. 说起图像特效,可以打开Photoshop软件,里边有个"滤镜"菜单,再到"滤镜"里边 ...

  6. python OpenCV 按时间间隔截取视频中任意片段帧

    通过视频制作相应的数据集,截取视频中的任意片段帧. 使用python截取视频中的任意片段帧,直接上代码: import cv2 import os# 定义视频文件路径和保存图像文件路径 video_p ...

  7. Python使用OpenCV+pillow提取AVI视频中关键帧图像

    问题描述:使用OpenCV把AVI视频切分成静态图像,提取视频中的关键帧,保存为0.jpg.1.jpg.2.jpg....... 实现步骤: 1)安装扩展库 2)准备一个AVI视频,这里以微课系列(5 ...

  8. 【OpenCV人脸识别2】从视频中检测人脸

    分为两步: 从视频中识别人脸和人的眼睛 从视频中检测人脸.眼睛.鼻子.嘴巴 1.从视频中识别人脸和人的眼睛 关于视频的操作,主要如下: 定义摄像头->打开摄像头->读取视频帧->转而 ...

  9. Matlab从视频中提取图像,可以设定每多少秒提取1帧。

    刚刚数学建模比赛,提取视频中的照片. 解释下: 1. 这个27941是秒数,就是提取视频多少秒.如果整个视频提取的话,可以用VideoAd.Duration即视频总长度替代. video.FrameR ...

最新文章

  1. loadrunner11下载地址
  2. 关于idea打开项目没有目录
  3. Python 实现图片质量比较之PSNR和SSIM
  4. Linux脚本让我选择文件,linux – 用于选择文件和打印文件大小的Awk脚本
  5. VTK:Picking之CellPicking
  6. 【直观理解】一文搞懂RNN(循环神经网络)基础篇
  7. Vue 进阶教程之:详解 v-model
  8. Andoid开发中生成二维码
  9. MediaWiki/安装
  10. [bzoj4813][Cqoi2017]小Q的棋盘
  11. Email - 搭建自定义邮件服务器
  12. 自动驾驶——为什么需要仿真?
  13. ALS算法的基本思想
  14. python 计时器模块_python中计时器
  15. CAR路里大学堂-汽车测试培训(CANOE)
  16. 炎颂科技管理系统软件——助力商协会“互联网+”之路
  17. CMD命令全集(转)
  18. 「Spring Boot」接口幂等性的4种实现方案
  19. Verilog中 reg和wire 用法 以及always和assign的区别
  20. 笔记整理--Linux守护进程

热门文章

  1. Java使用apache.http.client.fluent快速构建HTTP请求
  2. WD西部数据硬盘数据丢失了免费恢复方法
  3. TIA博途WinCC PRO V16 画面分辨率的设置方法
  4. 做一个有温度有条理的表达者
  5. 汽车悬架matlab时域和频域,车辆悬架系统振动控制(精)
  6. html下拉框属性js,Html下拉框Js对象属性方法总结
  7. 高等数学660---从179到185
  8. 易飞ERP软件用户组及权限设定-易飞ERP免费教程 转载
  9. 计算机科学与技术肄业后怎么继续完成学业,学籍学分问题解答
  10. Kali安装常用的软件工具——第二课