Python + 读取 / 写入视频

读取并播放视频

这篇教学会介绍OpenCV 里的VideoCapture() 方法,透过这个方法,读取电脑中的视频,或开启电脑的摄影镜头读取视频画面。

因为程式中的OpenCV 会需要使用镜头或GPU,所以请使用本机环境( 参考:使用Python 虚拟环境) 或使用Anaconda Jupyter 进行实作( 参考:使用Anaconda ) ,并安装OpenCV 函式库( 参考:OpenCV函式库)。

VideoCapture() 开启视频

使用VideoCapture() 方法时,如果参数指定「视频路径」,可以开启电脑中的视频,如果参数指定「0、1、2…」数字,则会开启电脑的摄影镜头读取影像画面,数字代表镜头的编号,通常都从0 开始,如果有外接镜头可能会是1、2 之类的编号。

cap = cv2.VideoCapture(0)         # 读取摄影镜头
cap = cv2.VideoCapture('视频路径') # 读取电脑中的视频

如果有遇到错误讯息( 特别是Windows ),可以尝试加入第二个cv2.CAP_DSHOW 参数( 表示DirectShow,也就是目前系统)。

cv2.CAP_DSHOW 是DirectShow,内容是一个「数值」,使用后等同输入700,第二个参数详细可以参考:Flags for video I/O

cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)

使用VideoCapture() 之后,通常会再透过cap.isOpened() 来判断视频是否正常开启,如果正常开启会回传True,否则是False,下方的程式码执行后,会读取电脑摄影镜头,如果没有读取到镜头资讯,就会印出Cannot open camera 的文字。

import cv2
cap = cv2.VideoCapture(0)
if not cap.isOpened():
    print("Cannot open camera")
    exit()

顺利开起视频后,就能使用cap.read() 的方法,读取视频的每一帧( 例如60fps 表示一秒钟有六十帧),读取后会回传两个值,第一个值ret 为True 或False,表示顺利读取或读取错误,第二个值表示读取到视频某一帧的画面,如果读取成功,就能透过imshow() 的方法,将该帧的画面显示出来,下方的程式码除了显示图片,更搭配waitKey(1) 方法,就能不断更新显示的图片,看起来就像播放视频一般。

使用waitKey(1) 表示每一毫秒更新一次画面,参数数值设定越大,图片更新时间就会越长,视频看起来就会出现延迟的状况,参考:waitKey() 等待多久关闭

import cv2
cap = cv2.VideoCapture(0)
if not cap.isOpened():
    print("Cannot open camera")
    exit()
while True:
    ret, frame = cap.read()             # 读取视频的每一帧
    if not ret:
        print("Cannot receive frame")   # 如果读取错误,印出讯息
        break
    cv2.imshow('oxxostudio', frame)     # 如果读取成功,显示该帧的画面
    if cv2.waitKey(1) == ord('q'):      # 每一毫秒更新一次,直到按下 q 结束
        break
cap.release()                           # 所有作业都完成后,释放资源
cv2.destroyAllWindows()                 # 结束所有视窗

搭配cvtColor() 改变视频色彩

cvtColor() 方法可以改变图片的色彩,如果将视频每一帧的图片套用cvtColor(),最后就会呈现的改变颜色的视频,下面的程式码执行后,就会读取电脑摄影机,并将彩色视频转换成黑白色彩的视频。

import cv2
cap = cv2.VideoCapture(0)
if not cap.isOpened():
    print("Cannot open camera")
    exit()
while True:
    ret, frame = cap.read()
    if not ret:
        print("Cannot receive frame")
        break
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)  # 转换成灰阶
    # gray = cv2.cvtColor(frame, 6)  # 也可以用数字对照 6 表示转换成灰阶
    cv2.imshow('oxxostudio', gray)
    if cv2.waitKey(1) == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()

读取串流图片MJPEG ( Motion JPEG ) 使用cap.read() 不仅能读取电脑摄影机画面,也可以读取MJPEG ( Motion JPEG ) 的图片串流格式,Motion JPEG ( Motion Joint Photographic Experts Group、M-JPEG ) 是一种影像压缩格式,每一个视讯框图像分别使用JPEG 编码,常用在网路摄影机、物联网摄影机之类的装置。 下方的范例读取交通部的「CCTV 开放资料集」所提供的「国道监视器影像」,读取后就能开启OpenCV 视窗并即时监看特定影像。

import cv2
cap = cv2.VideoCapture('https://cctvn.freeway.gov.tw/abs2mjpg/bmjpg?camera=15771')

if not cap.isOpened():
    print("Cannot open camera")
    exit()
while True:
    ret, frame = cap.read()             # 读取视频的每一帧
    if not ret:
        print("Cannot receive frame")   # 如果读取错误,印出讯息
        # 出现错误就再读取一次,避免程式到此处就停止
        cap = cv2.VideoCapture('https://cctvn.freeway.gov.tw/abs2mjpg/bmjpg?camera=15771')
        continue
    cv2.imshow('oxxostudio', frame)     # 如果读取成功,显示该帧的画面
    if cv2.waitKey(1) == ord('q'):      # 每一毫秒更新一次,直到按下 q 结束
        break
cap.release()                           # 所有作业都完成后,释放资源
cv2.destroyAllWindows()                 # 结束所有视窗

写入并储存视频

这篇教学会介绍OpenCV 里的VideoWriter() 方法,透过这个方法,可以将读取到的视频( 电脑中的视频或摄影镜头拍摄的视频),进行转档或转换色彩,储存成新的视频档。

因为程式中的OpenCV 会需要使用镜头或GPU,所以请使用本机环境( 参考:使用Python 虚拟环境) 或使用Anaconda Jupyter 进行实作( 参考:使用Anaconda ) ,并安装OpenCV 函式库( 参考:OpenCV函式库)。

使用VideoWriter() 储存视频

使用VideoWriter() 方法,可以建立一个空的「视频档」,将撷取到的影像图片组成新的串流格式,写入空的视频档案里,完成后就会储存成新为新的视频。

  • 使用cv2.VideoCapture() 读取电脑摄影机镜头影像。
  • 读取影像后使用cap.get() 方法取得视频长宽尺寸。
  • 使用cv2.VideoWriter_fourcc() 方法设定储存的视频格式。
  • 使用cv2.VideoWriter() 产生空的视频档案( 设定格式、帧率fps、长宽)。
  • 在while 回圈里使用out.write() 方法,将取得的图片写入每一帧。
  • 结束后使用out.release() 释放资源。
  • import cv2
    cap = cv2.VideoCapture(0)                         # 读取电脑摄影机镜头影像。
    width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))    # 取得影像宽度
    height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))  # 取得影像高度
    fourcc = cv2.VideoWriter_fourcc(*'MJPG')          # 设定视频的格式为 MJPG
    out = cv2.VideoWriter('output.mp4', fourcc, 20.0, (width,  height))  # 产生空的视频
    if not cap.isOpened():
        print("Cannot open camera")
        exit()
    while True:
        ret, frame = cap.read()
        if not ret:
            print("Cannot receive frame")
            break
        out.write(frame)       # 将取得的每一帧图像写入空的视频
        cv2.imshow('oxxostudio', frame)
        if cv2.waitKey(1) == ord('q'):
            break             # 按下 q 键停止
    cap.release()
    out.release()      # 释放资源
    cv2.destroyAllWindows()

    解决无法储存视频的问题

    实作过程中,可能会遇到「无法储存视频」的状况,通常的解决方法有下面三种:

  • 修改fourcc 的视频格式,如果是mov 或mp4 的影片档,使用「*'mp4v'」、「*'MJPG'」或「'M','J','P','G'」 ( 星号改半形)。
  • 将输入视频的长宽和输入的长宽度调整为「相同的长宽」。
  • 修改视频的档名,加上01、02、03…等数字。
  • 搭配cvtColor() 储存为黑白的视频

    使用cvtColor() 方法可以改变图片的色彩,如果将视频每一帧的图片套用cvtColor(),最后就会呈现的改变颜色的视频,下面的程式码执行后,就会读取电脑摄影机,并将彩色视频转换成黑白色彩的影片,最后储存为黑白的视频。

    import cv2
    cap = cv2.VideoCapture(0)
    width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
    fourcc = cv2.VideoWriter_fourcc(*'MJPG')
    out = cv2.VideoWriter('output.mov', fourcc, 20.0, (width,  height))
    # 如果转换成黑白视频后如果无法开启,请加上 isColor=False 参数设定
    # out = cv2.VideoWriter('output.mov', fourcc, 20.0, (width,  height), isColor=False)
    if not cap.isOpened():
        print("Cannot open camera")
        exit()
    while True:
        ret, frame = cap.read()
        if not ret:
            print("Cannot receive frame")
            break
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)  # 转换成灰阶
        out.write(gray)
        cv2.imshow('oxxostudio', gray)
        if cv2.waitKey(1) == ord('q'):
            break
    cap.release()
    out.release()
    cv2.destroyAllWindows()

    get 方法可取得的视频属性

    上述的范例程式码中,使用了cap.get() 方法取得视频属性,下方列出该方法可取得的属性,以及对应的数字编号:

    数字 属性 说明
    0 CAP_PROP_POS_MSEC 视频目前播放的毫秒数。
    1 CAP_PROP_POS_FRAMES 从0 开始的被截取或解码的帧的索引值。
    2 CAP_PROP_POS_AVI_RATIO 视频播放的相对位置,0 表示开始,1 表示结束。
    3 CAP_PROP_FRAME_WIDTH 视频宽度。
    4 CAP_PROP_FRAME_HEIGHT 视频高度。
    5 CAP_PROP_FPS 视频帧率fps。
    6 CAP_PROP_FOURCC 编解码的的四个字元。
    7 CAP_PROP_FRAME_COUNT 视频总共有几帧。
    8 CAP_PROP_FORMAT 视频格式。
    9 CAP_PROP_MODE 模式 目前的截取模式。
    10 CAP_PROP_BRIGHTNESS 亮度 摄影机亮度。
    11 CAP_PROP_CONTRAST 摄影机对比度。
    12 CAP_PROP_SATURATION 摄影机饱和度。
    十三 CV.CAP_PROP_HUE 摄影机HUE 色调数值。
    14 CAP_PROP_GAIN 摄影机图像增益数值。
    15 CAP_PROP_EXPOSURE 摄影机曝光度。
    16 CAP_PROP_CONVERT_RGB 复制代码 视频是否有转换为RGB。

    作者:普通网友

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python + 读取 / 写入视频

    发表回复