-
一些理解:
視頻文件可以看作是一幀一幀圖像文件的疊加,在時間尺度上觀察一幀一幀的圖像文件就得到了連續的視頻效果。這裏討論的視頻不包含相應的音頻。
對視頻文件的讀也即是從視頻文件中把圖像幀一幀一幀的讀出來(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)毫秒來等待用戶按鍵的動作。
- 本文重要函數解析cv2.cvtColor() :
其實就是看一下這個函數可以實現哪些圖像轉換功能啦,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()