一些理解:
视频文件可以看作是一帧一帧图像文件的叠加,在时间尺度上观察一帧一帧的图像文件就得到了连续的视频效果。这里讨论的视频不包含相应的音频。
对视频文件的读也即是从视频文件中把图像帧一帧一帧的读出来(OpenCV的VideoCapture类的read方法),至于你想干什么就看你 了。
比如你想做个视频播放器,读出来后就一帧一帧的显示出来呗(先不讨论视频声音的问题)。视频播放的速度呢,如果你想播放的慢点,你在显示两帧图像之间加个延时就行了。对于你在使用其他播放器时的加/减速播放的功能,我个人理解也是基于这个逻辑。如果两帧之间不加延时,直接读出来就做显示你会发现视频播放的很快。那可能会有人问了,这个视频文件的原始正常速度是多少呢,我们可以通过VideoCapture类的get方法获取到,也即是fps(Frames per second每秒钟多少帧)。
读出来一帧以后你也可以做点其他的事情,比如把这一帧转化为灰度图,再通过VideoWriter类的write方法写到视频文件里。这样你就实现了一个把彩色视频文件转换为黑白视频的功能,某些视频播放器里的这些功能是不是也用的类似的方法呢。你也可以开发一个更牛逼的功能:把这一帧图像运用一些图像增强算法,然后再写到视频文件里,这样是不是就实现了一个画质增强功能呢。
本文将给出两个例子:
1)实现简单的视频文件读取,然后以YUV颜色编码保存视频文件;
#!/usr/bin/env python3
import cv2
def test():
# Construct an object of VideoCapture class.
videoCapture = cv2.VideoCapture('vid.avi')
# Get some porperty of the video file.
fps = videoCapture.get(cv2.CAP_PROP_FPS)
size = (int(videoCapture.get(cv2.CAP_PROP_FRAME_WIDTH)),
int(videoCapture.get(cv2.CAP_PROP_FRAME_HEIGHT)))
# Construct an object of VideoWriter class. In the class initial parameters,
# the porperty of the output file have been configured.
# The parameter of cv2.VideoWriter_fourcc('I', '4', '2', '0') will encode
# frames as YUV.
videoWriter = cv2.VideoWriter('MyOutputVid.avi',
cv2.VideoWriter_fourcc('I', '4', '2', '0'),
fps,
size)
# Read one frame.
success, frame = videoCapture.read()
# Print the original image property.
print(frame.shape)
print(frame.size)
print(frame.dtype)
# Then, convert the color image to gray image.
img = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# Print the converted image property.
print(img.shape)
print(img.size)
print(img.dtype)
# Display the two different format image.
cv2.imshow('color', frame)
cv2.imshow('gray', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
# Loop until there are no frames.
while success:
# Write current frame to MyOutputVid.avi file.
videoWriter.write(frame)
success, frame = videoCapture.read()
if __name__ == '__main__':
test()
2)做一个简单的视频播放器(没有声音),同时具有将原视频转化为黑白视频的功能:
#!/usr/bin/env python3
import cv2
clicked = False
# Define the mouse callback function.
def onMouse(event, x, y, flags, param):
global clicked
if event == cv2.EVENT_LBUTTONUP:
clicked = True
def test():
# Construct the object of VideoCapture class.
videoCapture = cv2.VideoCapture('vid.avi')
# Get the fps and total frames of the video file.
fps = videoCapture.get(cv2.CAP_PROP_FPS)
totalFrameNum = videoCapture.get(cv2.CAP_PROP_FRAME_COUNT)
cv2.namedWindow('video show')
# Regist the callback to system.
cv2.setMouseCallback('video show', onMouse)
print("Showing video. Click window or press any key to stop")
success, frame = videoCapture.read()
# Display the video.
# The parameter of cv2.waitKey(int(1000/fps)) will config the delay
# period of two frames.
while success and cv2.waitKey(int(1000/fps)) == -1 and not clicked:
# Convert the color frame to gray frame.
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# Display the converted frame.
cv2.imshow('video show', frame)
success, frame = videoCapture.read()
cv2.destroyWindow('video show')
videoCapture.release()
if __name__ == '__main__':
test()
其中cv2.waitKey(int(1000/fps)) == -1表明没有按键被按下,否则waitKey将返回按下按键的ascii码。由于fps表明每秒的帧数,则1000/fps就表示正常播放速度下两帧的时间间隔。在这里waitKey(int(1000/fps))同时具有了延时的功能,即waitKey将等待int(1000/fps)毫秒来等待用户按键的动作。
其实就是看一下这个函数可以实现哪些图像转换功能啦,OpenCV官方文档给出的解释大概有150多种颜色空间的转换,但是我们常用的一般是BGR Gray 与 BGR HSV的转换,一个示例:
#!/usr/bin/env python3
import cv2
def test():
img_BGR = cv2.imread('test.jpg')
img_RGB = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2RGB)
cv2.imshow('RGB', img_RGB)
img_GRAY = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2GRAY)
cv2.imshow('GRAY', img_GRAY)
img_HSV = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2HSV)
cv2.imshow('HSV', img_HSV)
img_YcrCb = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2YCrCb)
cv2.imshow('YcrCb', img_YcrCb)
img_HLS = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2HLS)
cv2.imshow('HLS', img_HLS)
img_XYZ = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2XYZ)
cv2.imshow('XYZ', img_XYZ)
img_LAB = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2LAB)
cv2.imshow('LAB', img_LAB)
img_YUV = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2YUV)
cv2.imshow('YUV', img_YUV)
cv2.waitKey(0)
cv2.destroyAllWindows()
if __name__ == '__main__':
test()