番外2. OpenCV攝像頭捕獲與視頻處理與常見問題解決方案

      網友投稿 1785 2022-05-29

      本系列專欄寫作方式

      本系列專欄寫作將采用首創的問答式寫作形式,快速讓你學習到 OpenCV 的初級、中級、高級知識。

      2. OpenCV 中攝像頭捕獲與視頻處理

      OpenCV 除了應用在圖像處理領域外,還會應用到視頻處理領域,接下來我們就將學習到,如何通過Python OpenCV 對攝像頭捕獲或者視頻文件進行處理。

      視頻文件將從三個方向入手,分別是讀取文件,顯示視頻,保存視頻。

      本文將為你核心解決以下2個函數:cv2.VideoCapture 與 cv2.VideoWrite,基于這2個函數,會衍生出其它相關函數,具體參照下文。

      在 OpenCV 中操作攝像頭相關注意事項和解決方案

      攝像頭相較于視頻,差異在一個是實時圖像,一個是既定內容。如果想要捕獲到視頻,用到的是cv2.VideoCapture 函數,該函數的第一個參數是設備的索引號,如果你使用的是筆記本電腦,默認一般是0,表示的內置攝像頭,如果鏈接了外置,可以修改該數字即可。

      最簡單的測試代碼如下:

      import cv2 import numpy as np cap = cv2.VideoCapture(0) while True: ret, frame = cap.read() # 轉變成灰度圖 gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) cv2.imshow("frame", gray) if cv2.waitKey() & 0xFF == ord("x"): break # 關閉攝像 cap.release() cv2.destroyAllWindows()

      該代碼在運行時,如果你電腦未安裝攝像頭或者驅動異常,都會導致報錯,例如下述BUG

      error: (-215:Assertion failed) !_src.empty() in function 'cv::cvtColor'

      該問題雖然報錯出現在 cv2.cvtColor函數,但是原因是 frame 為空,即cap.read()讀取失敗導致的。

      這里在實際編碼過程中,需要增加一個判斷,cap.read() 函數會返回一個狀態布爾值,如果讀取到數據,返回真,否則返回假,測試如下代碼(下述代碼的停止,需要按鍵盤上的CTRL+C ):

      import cv2 import numpy as np cap = cv2.VideoCapture(0) while True: ret, frame = cap.read() print(ret) # 關閉攝像 cap.release() cv2.destroyAllWindows()

      測試完畢之后,我們修改本文一開始的代碼,讓其更加健壯。

      while True: ret, frame = cap.read() if ret: # 轉變成灰度圖 gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) cv2.imshow("frame", gray) # pass ...

      這里存在一個常見,但是及容易被忽視的問題,就是很多時候,我們并不知道電腦上有沒有攝像頭,或者攝像頭的設備號,該如何進行操作。

      你可以按照下述代碼進行檢測:

      import cv2 import numpy as np for cn_num in range(0, 5): cap = cv2.VideoCapture(cn_num) if cap.isOpened(): break

      以上代碼運行的原理是,按照順序依次打開設備 0~5,當發現攝像頭被成功打開,返回跳出。

      上述代碼還提及了一個新的函數 cap.isOpened,該函數用來檢測攝像頭是否初始化(能被打開),初始化成功返回 True。

      在 OpenCV 中操作視頻文件相關注意事項和解決方案

      其實操作視頻文件與操作攝像頭操作基本一致,唯一修改的就是cv2.VideoCapture 函數設備號即可。

      這里將設備號修改為視頻文件路徑。

      接下來,我們先看一段代碼,認識基本用法。

      import numpy as np import cv2 cap = cv2.VideoCapture('test.mp4') while cap.isOpened(): ret, frame = cap.read() # gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) cv2.imshow('frame', frame) if cv2.waitKey(25) & 0xFF == 27: break cap.release() cv2.destroyAllWindows()

      其中最需要注意的一個地方,不是 cv2.VideoCapture(‘test.mp4’) 函數讀取文件,而是 cv2.waitKey(25),這個地方需要設置好對應的視頻,如果數值特別小,例如 1,視頻就會快速播放,設置太高播放又會變慢,一般建議設置為 25。

      當然,上述代碼注釋的部分,如果取消,就會變成一個灰度視頻。

      甚至可以直接將視頻進行翻轉,用到函數為:cv2.flip(frame, 0),

      import numpy as np import cv2 cap = cv2.VideoCapture('test.mp4') while cap.isOpened(): ret, frame = cap.read() if ret == True: frame = cv2.flip(frame, 0) cv2.imshow('frame', frame) if cv2.waitKey(25) & 0xFF == 27: break cap.release() cv2.destroyAllWindows()

      上述代碼運行如下:

      接下來我們用視頻來學習一下一些操作屬性的方法。

      cv2.VideoCapture.get(propId) 可以訪問視頻的某些功能,其中 propId 是一個從0到18的數字,每個數字表示視頻的屬性。

      取值清單如下(該清單只作為查詢參考使用):

      0 - cv2.CAP_PROP_POS_MSEC: 視頻文件的當前位置(ms);

      1 - cv2.CAP_PROP_POS_FRAMES:從0開始索引幀,幀位置;

      2 - cv2.CAP_PROP_POS_AVI_RATIO:視頻文件的相對位置(0表示開始,1表示結束);

      3 - cv2.CAP_PROP_FRAME_WIDTH:視頻流的幀寬度;

      4 - cv2.CAP_PROP_FRAME_HEIGHT: 視頻流的幀高度;

      5 - cv2.CAP_PROP_FPS:幀率;

      6 - cv2.CAP_PROP_FOURCC : 編解碼器四字符代碼;

      7 - cv2.CAP_PROP_FRAME_COUNT :視頻文件的幀數;

      8 - cv2.CAP_PROP_FORMAT:retrieve()返回的Mat對象的格式;

      9 - cv2.CAP_PROP_MODE :后端專用的值,指示當前捕獲模式;

      10 - cv2.CAP_PROP_BRIGHTNESS :圖像的亮度,僅適用于支持的相機;

      11 - cv2.CAP_PROP_CONTRAST :圖像對比度,僅適用于相機;

      12 - cv2.CAP_PROP_SATURATION:圖像飽和度,僅適用于相機;

      13 - cv2.CAP_PROP_HUE:圖像色調,僅適用于相機;

      14 - cv2.CAP_PROP_GAIN:圖像增益,僅適用于支持的相機;

      15 - cv2.CAP_PROP_EXPOSURE:曝光,僅適用于支持的相機;

      16 - cv2.CAP_PROP_CONVERT_RGB:布爾標志,指示是否應將圖像轉換為RGB;

      17 - cv2.CAP_PROP_WHITE_BALANCE:目前不支持;

      18 - cv2.CAP_PROP_RECTIFICATION:立體攝像機的整流標志。

      有了上述清單,可以獲取視頻較多的屬性值了,例如獲取寬度與高度。

      cap = cv.VideoCapture('test.mp4') print("寬度:%s,高度:%s" % (cap.get(3), cap.get(4)))

      有 get 方法,對應的就存在 set 函數,函數原型如下:

      cap.set(propId,value) # 進行修改,value 是修改后的值

      但這個地方要注意下,上面 set 函數只對采集攝像頭有用,如果讀取的是視頻文件,上述內容就不在起作用了。

      如果你還是希望實現修改視頻文件的窗口大小,那可以使用下述方案。

      cv2.namedWindow("frame", 0) cv2.resizeWindow("frame", 800,300)

      如果想希望查看視頻播放的當前位置、幀率、幀數,可以直接使用下述代碼。

      time = cap.get(cv2.CAP_PROP_POS_MSEC) fps = cap.get(cv2.CAP_PROP_FPS) total_frames = cap.get(cv2.CAP_PROP_FRAME_COUNT)

      當然,使用屬性值也可以。

      time = cap.get(0) fps = cap.get(5) total_frames = cap.get(7)

      在 OpenCV 中捕獲視頻并保存

      圖片的保存使用函數 cv2.imwrite即可實現,但視頻保存,需要與cv2.VideoCapture對應著,創建一個 VideoWriter對象,而且還需要確定文件的名稱,視頻 FourCC 編碼,頻率,幀大小,isColor標簽,該標簽如果為 True 則保存彩色圖,否則是灰度圖。

      首先對 FourCC 進行一下說明,該編碼是一個4字節碼,表示的是視頻編碼格式。

      例如對于 MJPG,它有兩種寫法。

      注意這是 OpenCV 3 寫法,網上現在大多數博客都是 OpenCV 2 寫法。

      cv2.VideoWriter_fourcc('M', 'J', 'P', 'G') cv2.VideoWriter_fourcc(*'MJPG')

      常見編碼說明:

      MJPG編碼器編碼的視頻非常大;

      X264 編碼器編碼的視頻很小;

      XVID編碼器優先選擇,質量較高且體積較小。

      cv2.VideoWriter函數原型如下:

      cv2.VideoWriter( filename, fourcc, fps, frameSize[, isColor] )

      相關參數:

      filename:視頻保存文件名稱;

      fourcc:視頻編解碼器的4字節代碼;

      番外2. OpenCV 中攝像頭捕獲與視頻處理與常見問題解決方案

      fps:幀率;

      frameSize:幀大小;

      isColor:如果為True,則視頻為彩色,否則為灰度視頻,默認為True。

      測試代碼如下,代碼之后跟相關問題的說明。

      import numpy as np import cv2 cap = cv2.VideoCapture("test.mp4") width = int(cap.get(3)) height = int(cap.get(4)) fps = cap.get(5) # FourCC 編碼是 XVID fourcc = cv2.VideoWriter_fourcc(*'XVID') out = cv2.VideoWriter("test1.avi", fourcc, fps, (width, height)) while 1: ret, frame = cap.read() if frame is None: break else: # 對每一幀都進行處理 # frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) out.write(frame) cv2.imshow("video", frame) k = cv2.waitKey(25) & 0xFF if k == 27: break cap.release() out.release() cv2.destroyAllWindows()

      在調用函數 cv2.VideoWriter("test1.avi", fourcc, fps, (width, height)) 的時候,注意需要 (width, height) 必須是整數,需要強制轉換一下。

      其中 20 是 fps ,如果想保存成灰度視頻,按照下述代碼修改即可。

      out = cv2.VideoWriter("test1.avi", fourcc, fps, (width, height),False) # ...... # 注意在讀取每一幀的時候,都要轉換成灰度圖 frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # ......

      如果在編碼時出現如下錯誤,注意是 frameSize 參數設置的問題

      VideoWriter() missing required argument 'frameSize' (pos 5)

      對應的代碼位置按照如下修改即可

      out = cv2.VideoWriter("test1.avi", fourcc, fps, (int(width), int(height)))

      下一個常見的問題是,如果不是讀取視頻文件,直接采集的攝像頭數據,使用 fps = cap.get(5) 是無法獲取到具體的 fps 值的,此時只能進行手動設定。

      該值的設定需要依據自己電腦的配置,一般設置為10~20即可。

      OpenCV 視頻

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:JVM筆記-前端編譯與優化
      下一篇:Java基礎 第三節 第十九課
      相關文章
      亚洲人成人无码网www电影首页 | 亚洲日韩精品一区二区三区无码| 亚洲高清乱码午夜电影网| 亚洲mv国产精品mv日本mv| 亚洲国产日韩在线人成下载 | 人人狠狠综合久久亚洲高清| 亚洲a∨国产av综合av下载| 色天使亚洲综合一区二区| 国产精品亚洲五月天高清| 日韩精品成人亚洲专区| 亚洲高清成人一区二区三区| 亚洲精品久久久www| 亚洲熟女乱综合一区二区| 国产亚洲成人在线播放va| 亚洲一区二区三区影院| 亚洲精品无码av人在线观看| 亚洲国产AV无码专区亚洲AV| 亚洲Av熟妇高潮30p| 久久亚洲精品成人无码网站| 亚洲白色白色永久观看| 国产精品亚洲精品| 亚洲成av人无码亚洲成av人| 亚洲国产精品国产自在在线| 久久久久亚洲AV综合波多野结衣 | 亚洲综合欧美色五月俺也去| 亚洲AV成人一区二区三区在线看| 亚洲午夜精品一区二区麻豆| 亚洲avav天堂av在线网毛片| 亚洲AV无码乱码在线观看| 国产aⅴ无码专区亚洲av麻豆| 亚洲国产精品无码久久一区二区| 亚洲色图国产精品| 亚洲免费视频观看| 亚洲精品国产摄像头| 亚洲国产电影av在线网址| 亚洲精品少妇30p| 亚洲无线一二三四区| 亚洲av成人中文无码专区| 久久久久亚洲av成人无码电影 | 在线亚洲精品视频| 亚洲色成人中文字幕网站|