读取并播放视频
这篇教学会介绍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") # 如果读取错误,印出讯息breakcv2.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")breakgray = 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')continuecv2.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")breakout.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")breakgray = 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。 |