今天繼續測試 OpenCV 功能, 本系列之前的文章參考 :
OpenCV 官方教學文件 (Python) 參考 :
一. 從檔案讀取視訊 :
本篇要來測試 OpenCV 的視訊讀寫功能, 這要用到其 VideoCapture 類別, 它可以從檔案 (例如 mp4 檔) 或攝影機讀取視訊, 呼叫其建構式 VideoCapture() 會傳回一個 VideoCapture 物件, 其參數介面如下 :
vcap=VideoCapture(file [, flag]) # 從檔案 file (含路徑) 讀取視訊
此處用來測試的影片是從 YT 下載, 網友改編自周星馳電影 "唐伯虎點秋香", 用來提醒明天要補班的片段 :
可以用線上 YT 轉 MP4 工具下載 :
將下載的 mp4 檔案放在工作目錄下, 然後將檔名傳給 cv2.VideoCapture() 即可, 它會傳回一個包含兩元素的 tuple
>>> import cv2
>>> vcap=cv2.VideoCapture('唐伯虎點秋香-記得明天要上班.mp4')
>>> type(vcap)
<class 'cv2.VideoCapture'>
用 dir() 檢視 VideoCapture 物件的內容 :
>>> dir(vcap)
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'get', 'getBackendName', 'getExceptionMode', 'grab', 'isOpened', 'open', 'read', 'release', 'retrieve', 'set', 'setExceptionMode', 'waitAny']
VideoCapture 物件提供一些方法可用來讀取視訊框, 常用者如下表 :
VideoCapture 物件方法 | 說明 |
isOpened() | 檢查影片檔是否正常開啟, 傳回 True/False |
read() | 向下讀取一幀 (frame) 訊框, 傳回 (ret, frame), ret=True 表示讀取成功 |
release() | 釋放儲存視訊框的記憶體 |
顯示所讀取之視訊要用一個 while 無窮迴圈呼叫 VideoCapture 物件的 read() 方法依序讀取物件中的視訊框, 然後用 cv2.imshow() 顯示此訊框 (圖片), 並利用傳入 cv2.waitKey() 之延遲毫秒參數控制影片播放速度, 直到讀不到訊框 (ret=False) 跳出無窮迴圈為止.
例如 :
# opencv_read_mp4_1.py
import cv2
vcap=cv2.VideoCapture('唐伯虎點秋香-記得明天要上班.mp4') # 讀取 mp4 檔案
if not vcap.isOpened(): # 檢查檔案是否開啟成功
print('無法開啟影片檔')
exit() # 跳出程式
while True:
ret, frame=vcap.read() # 讀取下一個訊框
if not ret: # 檢查訊框是否已讀完
print('未收到訊框')
break # 跳出迴圈
cv2.imshow('videocapture', frame) # 顯示此訊框
if cv2.waitKey(50) == ord('q'): # 延遲 50ms 期間若按下 'q' 跳出迴圈
break
vcap.release()
cv2.destroyAllWindows()
截圖如下如下 :
此例中 cv2.waitKey() 參數值調小會讓動作變快, 調大則會變慢. 適當的值可參考影片檔的總幀數 與影片時間長度來決定, 只要將時長除以總幀數即可得到每幀要停留多久時間. 如果影片檔較小, 可以用下列網站來取得總幀數與時長 :
將影片檔上傳, 播完後即可得到總 frame 數與時長 :
可見此影片總框數為 776 框, 影片總長為 12.933 秒, 故每幀時間為 12.933/776=16.7 ms, 但 cv2.waitKey() 只能傳入整數, 故取 17 ms, 但播放起來還是覺得有點快動作, 改成 50 就比較自然了.
二. 從攝影機讀取視訊 :
如果是筆電或有外接攝影機的電腦, 只要將攝影機編號 (第一台編號 0, 第二台編號 1, ...) 傳給 VideoCapture() 建構式即可即時從攝影機擷取視訊, 將其分解為一幀幀的圖片 :
vcap=VideoCapture(camera [, flag]) # 從攝影機 camera (0, 1, 2 ...) 讀取視訊
用法與上面讀取影片檔類似, 只是將第一參數從檔案名稱字串改成攝影機編號而已, 例如 :
import cv2
vcap=cv2.VideoCapture(0) # 讀取編號 0 攝影機
if not vcap.isOpened():
print('無法開啟攝影機')
exit()
while True:
ret, frame=vcap.read()
if not ret:
print('未收到訊框')
break
cv2.imshow('videocapture', frame)
if cv2.waitKey(1) == ord('q'): # 延遲時間用 1 影像較即時
break
vcap.release()
cv2.destroyAllWindows()
注意, 此例 cv2.waitKey() 參數改為 1ms 才能喪影像反應更即時. 截圖如下 :
沒有留言 :
張貼留言