Python+ opencv:将长视频均匀的切成相同时长的小视频

一、概述

由于本人的项目需要对一小段一小段的视频进行研究提取特征,所以目前首要任务是将我录制的长视频剪辑成一小段一小段的视频。

代码参考链接:

  • python利用opencv将一段大视频等份的切成多个小视频段

二、代码实现与详解

import cv2
cap = cv2.VideoCapture("F:/datasets_1/video_1.mp4")  #获取视频(用绝对路径)
#cv2.videocapture读取视频必须要绝对路径正确,要用/,不用\
cap.isOpened()  #判断视频是否能顺利打开读取,True为能打开,False为不能打开

#获取视频信息
width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT) #获得视频帧宽和帧高
print(width, height)

if cap.isOpened(): #当成功打开视频时cap.isOpened()返回True, 否则返回False
    rate = cap.get(5)  #cap.get()括号中的参数为5代表获取帧速率
    FrameNumber = int(cap.get(7)) #获取视频文件的总帧数
    duration = FrameNumber/rate #视频总帧数除以帧速率等于视频时间,除以60之后的单位就是分钟
    fps = int(rate)# 每一段小视频帧数(我这个视频1秒钟的视频17帧),也用于后面的写入视频的帧速率
    print(rate)
    print(FrameNumber)
    print(duration)
    print(fps)

success, frame = cap.read()
#cap.read() 返回一个布尔值给sucess(True/False)。如果帧读取的是正确的,
#就是True。所以最后你可以通过检查他的返回值来查看视频文件是否已经到
#了结尾。返回视频帧给frame
print(success)
print(frame) #打印出来的是帧图像的矩阵(为三维矩阵)

i = 0
while (True):
    success, frame = cap.read()
    # cap.read()表示按帧读取视频,success,frame获得cap.read()的两个返回值
    # 其中success是布尔值,取帧是正确的则返回TRUE,如果文件读到结尾它的返回值就是False
    # frame就是每一帧图像,是一个三维矩阵
    if success:
        i += 1
        if (i % (5*fps) == 1):  #每5秒保存一段小视频,每一秒的视频有17帧,这里一共保存了5秒(如果你想保存其他时长的视频,你只需要更改5这个数字)
            # cap.read()按帧读取视频,每读取一帧,i就+1,
            # 当读取到的帧数能整除每段小视频的帧数了,那就把视频保存下来
            videoWriter = cv2.VideoWriter(str(i) + '.mp4', cv2.VideoWriter_fourcc('D', 'I', 'V', 'X'), fps, (int(width), int(height)))
            #videoWriter = cv2.VideoWriter(str(i) + '.mp4', -1, fps, (int(width), int(height)))
            # 分别是:保存文件名、编码器、帧率、视频宽高
            # 视频全部保存在了本代码所在的文件夹中,若你保存的小视频长度都为1秒,因为保存的是帧速率大小的帧图像,也就是每秒17帧的速率,就刚好保存了每秒17帧的小视频
            videoWriter.write(frame)  # 写入帧图像
        else: 
            videoWriter.write(frame)
    else:
        print('end')
        break

cap.release()  #释放摄像头

三、期间可能遇到的问题、解决办法、部分代码详解

1. cap = cv2.VideoCapture(0)打开视频

VideoCapture()中参数是0,表示打开笔记本的内置摄像头,参数是视频文件路径则打开视频,如cap = cv2.VideoCapture("F:/datasets_1/video_1.mp4")

**注意:**cv2.videocapture()读取视频必须要绝对路径正确,要用/,不用\。如果这里路径写法不正确就打不开你的视频。

2. cap.isOpened()
判断视频是否能顺利打开读取,True为能打开,False为不能打开

3. cap.read()
返回一个布尔值(True/False)。如果帧读取的是正确的,
就是True。所以最后你可以通过检查他的返回值来查看视频文件是否已经到
了结尾

4. success, frame = cap.read()

cap.read()表示按帧读取视频,success, frame是获cap.read()方法的两个返回值。其中success是布尔值,如果读取帧是正确的则返回True,如果文件读取到结尾,它的返回值就为Falseframe就是每一帧的图像,是个三维矩阵。

5. OpenCV VideoCapture.get()参数详解
函数cap.get(propId) 来获得视频的一些参数信息。这里
propId 可以是0 到18 之间的任何整数。每一个数代表视频的一个属性,见下表:

参考链接:

https://www.jianshu.com/p/676bef32e655

param define
cv2.VideoCapture.get(0) 视频文件的当前位置(播放)以毫秒为单位
cv2.VideoCapture.get(1) 基于以0开始的被捕获或解码的帧索引
cv2.VideoCapture.get(2) 视频文件的相对位置(播放):0=电影开始,1=影片的结尾。
cv2.VideoCapture.get(3) 在视频流的帧的宽度
cv2.VideoCapture.get(4) 在视频流的帧的高度
cv2.VideoCapture.get(5) 帧速率
cv2.VideoCapture.get(6) 编解码的4字-字符代码
cv2.VideoCapture.get(7) 视频文件中的帧数
cv2.VideoCapture.get(8) 返回对象的格式
cv2.VideoCapture.get(9) 返回后端特定的值,该值指示当前捕获模式
cv2.VideoCapture.get(10) 图像的亮度(仅适用于照相机)
cv2.VideoCapture.get(11) 图像的对比度(仅适用于照相机)
cv2.VideoCapture.get(12) 图像的饱和度(仅适用于照相机)
cv2.VideoCapture.get(13) 色调图像(仅适用于照相机)
cv2.VideoCapture.get(14) 图像增益(仅适用于照相机)(Gain在摄影中表示白平衡提升)
cv2.VideoCapture.get(15) 曝光(仅适用于照相机)
cv2.VideoCapture.get(16) 指示是否应将图像转换为RGB布尔标志
cv2.VideoCapture.get(17) × 暂时不支持
cv2.VideoCapture.get(18) 立体摄像机的矫正标注(目前只有DC1394 v.2.x后端支持这个功能)

具体属性名及英文说明:

属性名 说明
CV_CAP_PROP_POS_MSEC Current position of the video file in milliseconds or video capture timestamp.
CV_CAP_PROP_POS_FRAMES 0-based index of the frame to be decoded/captured next.
CV_CAP_PROP_POS_AVI_RATIO Relative position of the video file: 0 - start of the film, 1 - end of the film.
CV_CAP_PROP_FRAME_WIDTH Width of the frames in the video stream.
CV_CAP_PROP_FRAME_HEIGHT Height of the frames in the video stream.
CV_CAP_PROP_FPS Frame rate.
CV_CAP_PROP_FOURCC 4-character code of codec.
CV_CAP_PROP_FRAME_COUNT Number of frames in the video file.
CV_CAP_PROP_FORMAT Format of the Mat objects returned by retrieve() .
CV_CAP_PROP_MODE Backend-specific value indicating the current capture mode.
CV_CAP_PROP_BRIGHTNESS Brightness of the image (only for cameras).
CV_CAP_PROP_CONTRAST Contrast of the image (only for cameras).
CV_CAP_PROP_SATURATION Saturation of the image (only for cameras).
CV_CAP_PROP_HUE Hue of the image (only for cameras).
CV_CAP_PROP_GAIN Gain of the image (only for cameras).
CV_CAP_PROP_EXPOSURE Exposure (only for cameras).
CV_CAP_PROP_CONVERT_RGB Boolean flags indicating whether images should be converted to RGB.
CV_CAP_PROP_WHITE_BALANCE Currently not supported
CV_CAP_PROP_RECTIFICATION Rectification flag for stereo cameras (note: only supported by DC1394 v 2.x backend currently)

Note: 如果查询的视频属性是VideoCapture类不支持的,将会返回0

6. 保存视频
在我们捕获视频,并对每一帧都进行加工之后我们想要保存这个视频。对于图片来时很简单只需要使用 cv2.imwrite()。但对于视频来说就要多做点工作。以上面的代码为例cv2.VideoWriter(str(i) + '.mp4', cv2.VideoWriter_fourcc('D', 'I', 'V', 'X'), fps, (int(width), int(height)))

cv.videoWriter()写入视频:

  • 第一个参数是保存的视频的名字str(i)+'.mp4'
  • 第二个参数是指定FourCC编码
    FourCC全称Four-Character Codes,代表四字符代码 (four character code), 它是一个32位的标示符,是一种独立标示视频数据流格式的四字符代码。因此cv2.VideoWriter_fourcc()函数的作用是输入四个字符代码即可得到对应的视频编码器。

CV_FOURCC获取编码格式编码:
CV_FOURCC(‘P’, ‘I’, ‘M’, ‘1’) = MPEG-1 codec
CV_FOURCC(‘M’, ‘J’, ‘P’, ‘G’) = motion-jpeg codec
CV_FOURCC(‘M’, ‘P’, ‘4’, ‘2’) = MPEG-4.2 codec
CV_FOURCC(‘D’, ‘I’, ‘V’, ‘3’) = MPEG-4.3 codec
CV_FOURCC(‘D’, ‘I’, ‘V’, ‘X’) = MPEG-4 codec (mp4可以用这个)
CV_FOURCC(‘U’, ‘2’, ‘6’, ‘3’) = H263 codec CV_FOURCC(‘I’, ‘2’, ‘6’, ‘3’) = H263Icodec
CV_FOURCC(‘F’, ‘L’, ‘V’, ‘1’) = FLV1 codec

  • 第三个参数fps是帧率
  • 第四个参数是帧宽帧高

扩展理解:

  • *视频文件格式:*即视频文件的后缀,如mp4,avi等等,主要为帮助系统的程序知道应该使用何种程序打开该文件;这就是说如果你把一个视频格式的文件后缀从avi改成mp4,并不意味该文件就变成了mp4格式。
  • *视频封装格式:*则是一种视频封装容器。什么意思呢?在视频文件中同时含有视频部分、音频部分等等;那么视频封装容器则一种可以把多种视频数据放在一起的一个大盒子。这个盒子就是我们常说的视频格式,例如AVI(后缀.avi)格式、MPEG(后缀.mpg .mpeg .mpe .dat .vob .asf .3gp .mp4)格式、REAL Video(后缀.rmvb)格式、Flash Video(后缀.flv)格式等等。
  • *视频编码器:*是指能够对数字视频进行压缩存储和解压缩的程序或设备。目前场景的编码器有H.26X系列(目前最流行的是H.264和H.265)和MPEG系列(目前最流行的是MPEG-4第十部分,即H.264)。上文代码中提到的XVID(旧称为DIVX)是一个开放源代码的MPEG-4视频编解码器.

参考链接:

  • Opencv-VideoWriter

7. 遇到无法保存视频的问题
*可能的问题:*选择编码器错误

  • *解决办法一:*若是你不知道选择什么编码,或者是运行环境没有相对应的视频编码器,故无法生成视频,或者是第二个参数设置不合适,你可以将cv2.VideoWriter()函数中的第二个参数设为-1**,程序运行时则会交互的弹出一个对话框,让你从已有的编码中选择一个。
    例:v = cv2.VideoWriter('output_video.mp4', -1, fps, size)

  • *解决办法二:*直接查看你电脑中现有的编码器有哪些。
    如果你不能正常保存视频,也有可能是你的系统没有对应的编码库。指的是MJPEG 编码格式,那么需要你的系统里支持MJPEG编码(光支持解码是不够的)。我的系统里面安装了ffmpeg, 在我编译opencv库时已经配置了这一选项。因此ffmpeg支持的编解码库,我的opencv 也是支持的。现在我们来查看我的电脑里面的ffmpeg支持的编解码形式。
    在你的终端中输入命令:
    ffmpeg -codecs 查询ffmpeg支持的编解码形式
    或者输入:
    ffmpeg -codecs | grep 264 查询是否支持264编码
    如下图所示,我的电脑中有decoder也有encoder,且支持MPEG,所以我直接使用CV_FOURCC('D', 'I', 'V', 'X')即可。
    Python+ opencv:将长视频均匀的切成相同时长的小视频_第1张图片

参考链接:

  • OpenCV视频写入详解_Python,视频保存0kb问题
  • opencv VideoWriter保存视频失败原因

8. 调用release()释放摄像头

为了将长视频剪成批量的小视频,我还花了挺长时间来找合适的方式的,还好最后去尝试了这种方法。其实我早几天前已经看到相似的代码了,但是我没有去尝试,主要是自己对OpenCV处理视频图像的代码太不熟悉了,自己看不懂代码,所以导致自己错过了正确的解决方法。所以以后要解决问题的时候,先要把代码看懂,才能真正的解决一个问题。

你可能感兴趣的:(opencv,视频处理,pytorch,神经网络,机器学习)