????????在我們進行計算機視覺任務時,經常會對視頻中的圖像進行操作,這里我來給大家分享一下,cv2對視頻文件的操作方法。這里我們主要介紹cv2.VideoCapture函數的基本使用方法。
cv2.VideoCapture函數
當我們在使用cv2.VideoCapture函數時,我們通常使用輪詢的方式,即:
while True:if condition1:do somethingif condition2:break...
更一般化的是?
import cv2
#這里是獲取實時視頻源,如果是讀取已有視頻文件cap=cv2.VideoCapture(filename='')
cap=cv2.VideoCapture(index=0)
if cap.isOpened():while True:ret,frame=cap.read()#...#... 針對視頻中的每一幀圖像的其他操作#....if not ret:breakcv2.imshow('test',frame)key=cv2.waitKey(1)if key==27:#置頂一個按鍵來結束循環,這里使用esc健的ASCII碼breakcap.release()cv2.destroyAllWindows()
else:print('攝像頭未打開')
初始化
? ? ? ? 視頻文件
????????如果你需要處理的是已有的視頻文件,而不是打開攝像頭捕獲的實時視頻流,那么只需要傳入filename即可。apiPerference是可選參數主要用來指定視頻捕獲的后端,即使用哪種頂層API來讀取視頻流或攝像頭,默認值是cv2.CAP_ANY由opencv自動選擇
import cv2
'''
filename:視頻文件路徑 .mp4
apiPerference:指定視頻捕獲的后端(即使用哪種底層API來讀取視頻流或攝像頭)apiPerference參數常用flag:
cv2.CAP_ANY: 自動選擇默認后端(OpenCV自行決定)跨平臺
cv2.CAP_ANDROID: 使用Android的Camera2 API
cv2.CAP_DSHOW: 使用DirectShow(Windows專用)
cv2.CAP_MSMF: 使用Microsoft Media Foundation(Windows 10+)
cv2.CAP_V4L2: 使用Video4Linux2(Linux專用)Linux
cv2.CAP_FFMPEG: 使用FFmpeg解碼視頻文件跨平臺(需安裝 FFmpeg)
cv2.CAP_GSTREAMER: 使用 GStreamer(Linux常用)
cv2.CAP_OPENNI: 用于深度攝像頭(如Kinect)特定設備
'''
cap=cv2.VideoCapture(r'test.mp4')
實時視頻流?
????????如果你處理的是實時視頻流,那么需要設置index參數,不使用外接設備時index一般都設置為apiPerference是可選參數主要用來指定視頻捕獲的后端,即使用哪種頂層API來讀取視頻流或攝像頭,默認值是cv2.CAP_ANY由opencv自動選擇
import cv2
'''
index:0或1,0是電腦內置攝像頭,1是外接攝像頭,沒有外接攝像頭仍然設置Index=1的話不會報錯,只是代碼不運行
apiPerference:指定視頻捕獲的后端(即使用哪種底層API來讀取視頻流或攝像頭)apiPerference參數常用flag:
cv2.CAP_ANY: 自動選擇默認后端(OpenCV自行決定)跨平臺
cv2.CAP_ANDROID: 使用Android的Camera2 API
cv2.CAP_DSHOW: 使用DirectShow(Windows專用)
cv2.CAP_MSMF: 使用Microsoft Media Foundation(Windows 10+)
cv2.CAP_V4L2: 使用Video4Linux2(Linux專用)Linux
cv2.CAP_FFMPEG: 使用FFmpeg解碼視頻文件跨平臺(需安裝 FFmpeg)
cv2.CAP_GSTREAMER: 使用 GStreamer(Linux常用)
cv2.CAP_OPENNI: 用于深度攝像頭(如Kinect)特定設備
'''
cap=cv2.VideoCapture(index=1,apiPreference=cv2.CAP_ANY)
?常用屬性
cap.isOpened()
檢查視頻源是否打開,返回值為True 或False
import cv2
cap=cv2.VideoCapture(index=0,apiPreference=cv2.CAP_MSMF)
if cap.isOpened():print('攝像頭已打開')while True:ret,frame=cap.read()cv2.imshow('test',frame)key=cv2.waitKey(1)if key==27:#按下esc健退出breakcap.release()cv2.destroyAllWindows()
else:print('攝像頭未打開')
cap.read()?
? ? ? ? 用來讀取視頻中的下一幀,返回值為(ret,frame) ret為是否成功,frame為圖像數據
????????cap.read()是我們處理視頻文件中最關鍵的函數,如果沒有這一步,那么根本無法處理視頻文件中的圖像。
import cv2
cap=cv2.VideoCapture(index=0,apiPreference=cv2.CAP_MSMF)
if cap.isOpened():print('攝像頭已打開')while True:ret,frame=cap.read()if not ret:breakcv2.imshow('test',frame)key=cv2.waitKey(1)if key==27:#按下esc健退出breakcap.release()cv2.destroyAllWindows()
else:print('攝像頭未打開')
cap.release()?
????????用來釋放視頻源,出現在cv2.destroyAllWindows()前。
import cv2
#這里是獲取實時視頻源,如果是讀取已有視頻文件cap=cv2.VideoCapture(filename='')
cap=cv2.VideoCapture(index=0)
if cap.isOpened():while True:ret,frame=cap.read()#...#...#....cv2.imshow('test',frame)key=cv2.waitKey(1)if key==27:#設定一個按鍵來結束循環,這里使用esc健的ASCII碼breakcap.release()cv2.destroyAllWindows()
else:print('攝像頭未打開')
視頻屬性控制?
?cap.get(propId)
? ? ? ? ?用來獲取當前視頻的屬性值,比如幀寬,高,FPS等。
????????這里我們以獲取當前幀率并標記在窗口內為例:
fps=cv2.get(cv2.CAP_PROP_FPS)
????????fps的類型為Float
import cv2
#這里是獲取實時視頻源,如果是讀取已有視頻文件cap=cv2.VideoCapture(filename='')
cap=cv2.VideoCapture(index=0)
if cap.isOpened():while True:ret,frame=cap.read()fps=cap.get(cv2.CAP_PROP_FPS)#...#...#....cv2.putText(img=frame,text=f'fps:{fps}',org=(50,50),fontFace=1,fontScale=3,color=(255,0,0))cv2.imshow('test',frame)key=cv2.waitKey(1)if key==27:#設定一個按鍵來結束循環關閉攝像頭,這里使用esc健的ASCII碼breakcap.release()cv2.destroyAllWindows()
else:print('攝像頭未打開')
最后,我將所有的本文所有的要點都總結在了下方這個表格里。
參數/方法?? | ??說明?? |
---|---|
??初始化?? | |
cap=cv2.VideoCapture() | 創建視頻捕獲對象,參數可以是設備索引(攝像頭)或視頻文件路徑。 |
??常用屬性?? | |
cap.isOpened() | 檢查視頻源是否成功打開,返回?True /False 。 |
cap.read() | 讀取下一幀,返回?(ret, frame) ,ret ?為是否成功,frame ?為圖像數據。 |
cap.release() | 釋放視頻源。 |
??視頻屬性控制?? | |
cap.get(propId) | 獲取視頻屬性值(如幀寬、高、FPS 等),propId ?為屬性標識。 |
cap.set(propId, value) | 設置視頻屬性值(部分屬性可修改)。 |
??常用屬性標識(propId)?? | |
cv2.CAP_PROP_FRAME_WIDTH | 幀的寬度(像素)。 |
cv2.CAP_PROP_FRAME_HEIGHT | 幀的高度(像素)。 |
cv2.CAP_PROP_FPS | 視頻的幀率(Frames Per Second)。 |
cv2.CAP_PROP_FRAME_COUNT | 視頻的總幀數(僅對文件有效)。 |
cv2.CAP_PROP_POS_MSEC | 當前幀的時間戳(毫秒,僅對文件有效)。 |
cv2.CAP_PROP_POS_FRAMES | 當前幀的索引(從 0 開始)。 |
??其他方法?? | |
cap.grab() | 快速抓取下一幀(不解碼),通常與?cap.retrieve() ?配合使用。 |
cap.retrieve() | 解碼并返回由?grab() ?抓取的幀。 |
cap.getBackendName() | 返回當前使用的后端名稱(如?FFMPEG 、DSHOW) 。 |