视频处理在OpenCV中处于极为重要的地位,目标实时跟踪等各种实时图像处理算法都是以视频为基础。
1.从相机捕获视频
首先我们来了解一下使用电脑自带的相机来进行捕获视频。通常,我们必须使用摄像机捕获实时流。OpenCV提供了一个非常简单的界面来执行此操作。让我们从相机捕获视频(我使用笔记本电脑上的内置网络摄像头),我们需要了解几个函数:
cap = cv2.VideoCapture(0)
VideoCapture()中参数是0,表示打开笔记本的内置摄像头,参数是视频文件路径则打开视频,如cap = cv2.VideoCapture("../test.avi"),当然了,如果你外接的有其他的摄像头,那就可以选用其他的参数例如1从而调用它。
ret,frame = cap.read()
cap.read()按帧读取视频,ret,frame是获cap.read()方法的两个返回值。其中ret是布尔值,如果读取帧是正确的则返回True,如果文件读取到结尾,它的返回值就为False。frame就是每一帧的图像,是个三维矩阵,我们都知道视频是由一帧一帧的图像连续组成的,OpenCV在对图像处理时就是对每一帧的图像进行快速处理。
cv2.waitkey()
waitKey()方法本身表示等待键盘输入,参数是1,表示延时1ms切换到下一帧图像,对于视频而言;参数为0,如cv2.waitKey(0)只显示当前帧图像,相当于视频暂停,;参数过大如cv2.waitKey(1000),会因为延时过久而卡顿感觉到卡顿。
c得到的是键盘输入的ASCII码,esc键对应的ASCII码是27,即当按esc键是if条件句成立。
release()
调用release()释放摄像头,调用destroyAllWindows()关闭所有图像窗口。
现在我们首先进行代码实验,之后会进行一些说明:
import numpy as np
import cv2 as cv
cap = cv.VideoCapture(0)
if not cap.isOpened():
print("Cannot open camera")
exit()
while True:
# Capture frame-by-frame
ret, frame = cap.read()
# if frame is read correctly ret is True
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
break
# Our operations on the frame come here
# gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
# Display the resulting frame
cv.imshow('frame', gray)
if cv.waitKey(1) == ord('q'):
break
# When everything done, release the capture
cap.release()
cv.destroyAllWindows()
isOpened可以确定摄像头是否被打开,如果打开则继续,如果未成功打开则自动退出。前面的时候我们已经讲过,frame所指代的,就是摄像头视频的每一帧图像,所以在显示时,我们也是显示每一帧。如果对每一帧图像都进行灰度化处理,那么所显示的视频就是灰度化视频,当然,关于灰度化现在还没有讲到,但是可以先做个小实验,我们来看代码:
import numpy as np
import cv2 as cv
cap = cv.VideoCapture(0)
if not cap.isOpened():
print("Cannot open camera")
exit()
while True:
# Capture frame-by-frame
ret, frame = cap.read()
# if frame is read correctly ret is True
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
break
# Our operations on the frame come here
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
# Display the resulting frame
cv.imshow('frame', gray)
if cv.waitKey(1) == ord('q'):
break
# When everything done, release the capture
cap.release()
cv.destroyAllWindows()
大家自己实验,体验一下效果。或许有的人已经发现了,我们的视频跟实际中好像是相反的,属于镜像效果,我们可以取消这种效果,在这里需要介绍一个函数,后面在图像增强部分也会介绍到:
cv2.flip ()
函数原型:flip(src, flipCode[, dst])
src代表输入的图像,我么你来看一下flipCode的参数表:
现在我们加入这行代码:
import numpy as np
import cv2 as cv
cap = cv.VideoCapture(0)
if not cap.isOpened():
print("Cannot open camera")
exit()
while True:
# Capture frame-by-frame
ret, frame = cap.read()
frame = cv.flip(frame, 1)
# if frame is read correctly ret is True
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
break
# Our operations on the frame come here
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
# Display the resulting frame
cv.imshow('frame', gray)
if cv.waitKey(1) == ord('q'):
break
# When everything done, release the capture
cap.release()
cv.destroyAllWindows()
2.从文件播放视频
从文件播放视频与从摄像机捕获视频相同,只是将摄像机索引更改为视频文件名。另外,在显示框架时,请使用适当的时间cv.waitKey()。如果太少,则视频将非常快,而如果太高,则视频将变得很慢(嗯,这就是显示慢动作的方式)。正常情况下25毫秒就可以了。
给出实例代码:
import cv2 as cv
cap = cv.VideoCapture('test.avi')
while cap.isOpened():
ret, frame = cap.read()
# if frame is read correctly ret is True
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
break
cv.imshow('frame', frame)
if cv.waitKey(25) == ord('q'):
break
cap.release()
cv.destroyAllWindows()
3.保存视频
当我们想要保存图像的时候,,这非常简单:只需使用cv2.imwrite()。而当我们想要保存视频的时候,需要做更多的工作。
这次我们创建一个VideoWriter对象。我们应该指定输出文件名(例如:output.avi)。然后,我们应指定FourCC代码(下一段中的详细信息)。然后应传递每秒的帧数(fps)和帧大小。最后一个是isColor标志。如果为True,则编码器需要彩色框,否则将与灰度框一起使用。
FourCC是一个4字节的代码,用于指定视频编码器以及****。可用代码列表可在fourcc.org中找到,它取决于平台。
- 在Fedora中:DIVX,XVID,MJPG,X264,WMV1,WMV2。(最好使用XVID。MJPG可以生成大尺寸的视频。X264提供非常小的尺寸的视频)
- 在Windows中:DIVX(尚待测试和添加)
- 在OSX中:MJPG(.mp4),DIVX(.avi),X264(.mkv)。
FourCC代码作为MJPG的`cv.VideoWriter_fourcc('M','J','P','G')or cv.VideoWriter_fourcc(*'MJPG')`传递。
e supported options may include the following:
0: This option is an uncompressed raw video file. The file extension should be .avi.
cv2.VideoWriter_fourcc('I','4','2','0'): This option is an uncompressed YUV encoding, 4:2:0 chroma subsampled. This encoding is widely compatible but produces large files. The file extension should be .avi.
cv2.VideoWriter_fourcc('P','I','M','1'): This option is MPEG-1. The file extension should be .avi.
cv2.VideoWriter_fourcc('X','V','I','D'): This option is a relatively old MPEG-4 encoding. It is a good option if you want to limit the size of the resulting video. The file extension should be .avi.
cv2.VideoWriter_fourcc('M','P','4','V'): This option is another relatively old MPEG-4 encoding. It is a good option if you want to limit the size of the resulting video. The file extension should be .mp4.
cv2.VideoWriter_fourcc('X','2','6','4'): This option is a relatively new MPEG-4 encoding. It may be the best option if you want to limit the size of the resulting video. The file extension should be .mp4.
cv2.VideoWriter_fourcc('T','H','E','O'): This option is Ogg Vorbis. The file extension should be .ogv.
cv2.VideoWriter_fourcc('F','L','V','1'): This option is a Flash video. The file extension should be .flv.
以下代码从摄像机捕获,在垂直方向上翻转每一帧,然后保存视频:
import numpy as np
import cv2 as cv
cap = cv.VideoCapture(0)
# Define the codec and create VideoWriter object
fourcc = cv.VideoWriter_fourcc(*'XVID')
out = cv.VideoWriter('output.avi', fourcc, 20.0, (640, 480))
while cap.isOpened():
ret, frame = cap.read()
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
break
frame = cv.flip(frame, 1)
# write the flipped frame
out.write(frame)
cv.imshow('frame', frame)
if cv.waitKey(1) == ord('q'):
break
# Release everything if job is finished
cap.release()
out.release()
cv.destroyAllWindows()
大家可以自己尝试演示效果。
视频处理的部分基本上就结束了,以上介绍到的将是以后学习中非常重要的基础。而事实上,OpenCV中对于视频的处理也有更多的操作,现在介绍最后一个函数:
VideoCapture.get()
由于前面我们已经指定cap = cv.VideoCapture(0),所以调用此函数只需用cap.get(),get中将传入参数,给出参数表:
共有18个参数,而至于相关的代码,请大家自己实验,可以使用print函数输出视频的详细信息。
天道酬勤 循序渐进 技压群雄