教你用python操作攝像頭以及對影片流的處理

qwer1030274531發表於2020-10-23

實驗介紹

此次實驗幫助大家利用 OpenCV 去讀取攝像頭的影片流,你可以直接使用筆記本本身的攝像頭,也可以用 USB 連線直接的攝像頭。如果你在操作過程中,攝像頭讀取失敗, 實驗中還為你提供了幾個問題排查步驟。當然,對影片進行操作時還需要講解影片相關的編解碼格式以及特定幀的讀取。在實驗的最後,還提供了 OpenCV 的專案實戰:影片錄製與影片讀取。

知識點

  • 影片錄製
  • 影片編解碼格式
  • 影片讀取以及特定幀的讀取

影片錄製

使用 OpenCV 錄製影片,主要涉及 OpenCV 的 VideoWrite 物件。錄製影片的第一步要例項化一個 VideoCapture 物件,用於從攝像頭讀入圖片。建立一個 VideoCapture 物件的程式碼如下:

cap = cv2.VideoCapture(0)1

類 VideoCapture 的兩個常見建構函式:

<VideoCaputrue object> = cv2.VideoCapture(filename)1
  • 功能:開啟影片檔案;
  • 引數filename:影片檔名。
<VideoCaputrue object> = cv2.VideoCapture(index)1
  • 功能:開啟相機裝置;
  • 引數index:相機裝置ID,當只有一個相機時,給0即可。

OpenCV 中影片錄製需要藉助 VideoWriter 物件, 將從 VideoCapture 中讀入圖片,不斷地寫入到 VideoWrite 的資料流中。建立 VideoWriter物件的程式碼如下:

out = cv2.VideoWriter('video_record.avi', codec, fps, frameSize)1

此次實驗選擇膝上型電腦內建的攝像頭,從中捕獲影片並顯示影片流。首先實現捕獲一張圖片。基本思路是首先開啟相機,再判斷相機是否開啟,相機開啟成功後,捕獲一幀影像,然後 imshow 顯示,最後關閉相機。具體程式碼如下:

import cv2
cap = cv2.VideoCapture(0)if cap.isOpened():
    ret,frame = cap.read()
    cv2.imshow('frame',frame)
    cv2.waitKey(3000)cap.release()cv2.destroyAllWindows()12345678

相機捕獲的一幀影像如圖所示:

影片編解碼格式

在寫入影片的時候, 我們必須指定影片的編解碼格式,這裡我們指定為 MJPG 格式。指定影片編解碼方式為 MJPG 的程式碼如下:

codec = cv2.VideoWriter_fourcc(*'MJPG')1

在講解影片的編解碼格式之前,我們先來學習一下  FourCC 。

FourCC 全稱 Four-Character Codes ,代表四字元程式碼 (four character code), 它是一個 32 位的標示符,其實就是 typedef unsigned int FOURCC 。FourCC 是一種獨立標示影片資料流格式的四字元程式碼。

FourCC 支援的所有影片編解碼的格式都可以在  FourCC 官網上查閱。

在指定影片的編解碼格式為 MJPG 格式之後,我們還需要指定影片的幀率跟視窗大小。指定寫入幀率為 30 以及視窗大小的程式碼如下: xian/

fps = 30.0frameSize = (640, 480)12

初始化 VideoWriter 的時候,將這些引數傳入到其中。並指定輸出影片檔案的名稱。我們將輸出影片檔案的名稱命名為 video.avi ,具體程式碼如下:

out = cv2.VideoWriter('video.avi', codec, fps, frameSize)1

影片錄製演示完整程式碼 /guiyang/

接下來,就是要不斷的從 VideoCapture 中讀入圖片,然後寫入到VideoWrite 的資料流中。不斷的向影片輸出流寫入幀影像的程式碼如下: /chongqing/

out.write(frame)1

在影片錄製結束後,為了節省資源,我們需要釋放已經佔用的資源,具體程式碼實現如下:

cap.release()out.release()12

影片錄製演示完整程式碼如下:

import numpy as npimport cv2
cap = cv2.VideoCapture(0)codec = cv2.VideoWriter_fourcc(*'MJPG')fps = 20.0frameSize = (640, 480)out = cv2.VideoWriter('video.avi', codec, fps, frameSize)print("按鍵Q-結束影片錄製")while(cap.isOpened()):
    ret, frame = cap.read()
    if ret==True:
        out.write(frame)
        cv2.imshow('frame',frame)
        if cv2.waitKey(1) == ord('q'):
            break
    else:
        breakcap.release()out.release()cv2.destroyAllWindows()1234567891011121314151617181920

影片讀取以及特定幀的讀取

影片讀取函式介紹及實現 /video/

讀入影片的時候,我們仍然需要使用 VideoCapture 物件,只不過傳入的不再是攝像頭的 ID 了,需要改成影片檔案的路徑。讀取影片流的時候可以逐幀讀取捕獲實現的影像。此時讀入影片流的程式碼如下:

cap = cv2.VideoCapture('video.avi')1

OpenCV 提供了介面 VideoWriter 用於影片的儲存,具體函式表示如下:

<VideoWriter object> = cv.VideoWriter( filename, fourcc, fps, frameSize[, isColor] )1

函式引數:

  • filename:給要儲存的影片起個名字;

  • fourcc:指定影片編解碼器的4位元組程式碼;

    【(‘P’,‘I’,‘M’,‘1’)是MPEG-1編解碼器】
    【(‘M’,‘J’,‘P’,'G ')是一個運動jpeg編解碼器】

  • fps:幀率;

  • frameSize:幀大小。

從影片檔案中播放影片,更改相機索引與影片檔名。 在顯示幀時,選擇適當的  cv2.waitKey()時間,如果該值太小,影片會非常快,如果它太大,影片會很慢(這可以用來慢動作顯示影片)。 正常情況下,25 毫秒即可。具體影片讀取的原始碼如下: hebei/

import numpy as npimport cv2
cap = cv2.VideoCapture('video.avi')while(True):
    ret, frame = cap.read()
    if ret:
        cv2.imshow('frame',frame)
    else:
        print("影片讀取完畢或者影片路徑異常")
        break
    if cv2.waitKey(25) & 0xFF == ord('q'):
        breakcap.release()cv2.destroyAllWindows()1234567891011121314

影片寫入完成,命名為 video.avi ,結果展示如下:

捕獲.PNG

image4.gif

影片特定幀的讀取(透過幀數間隔擷取影片幀)

透過影片的幀數間隔擷取影片的每一幀,自己設定幀間隔為 20 ,即每隔 20 幀擷取一幀影像,並將我們擷取的每一幀儲存到我們自定義的資料夾中,這裡儲存的資料夾為程式碼存在的路徑下 capture_image 資料夾裡。具體實現的程式碼如下: heilongjiang/

import cv2
cap = cv2.VideoCapture("video.avi")c = 1frameRate = 20while(True):
	ret, frame = cap.read()
	if ret:
		if(c % frameRate == 0):
			print("開始擷取影片第:" + str(c) + " 幀")
			cv2.imwrite("./capture_image/" + str(c) + '.jpg', frame)
		c += 1
		cv2.waitKey(0)
	else:
		print("所有幀都已經儲存完成")
		breakcap.release()12345678910111213141516

執行結果如下,將展示我們擷取的影片幀數間隔:

影片幀擷取.PNG

如圖為影片擷取的最後一幀影像:
last_frame.png

注意:讀入影片檔案和儲存圖片的路徑,都要使用“\\”,使用“/”或者“\”會出現開啟檔案報錯。

攝像頭讀取失敗-問題排查

如果你執行上文的原始碼的時候,出現報錯。

你可以按照下面提供的思路自行檢查一下。

  1. 驅動問題 有的攝像頭可能存在驅動問題,需要安裝相關驅動,或者檢視攝像頭是否具有UAC免驅協議。
  2. USB介面相容性問題 USB2.0介面接了一個USB3.0的攝像頭,也是不支援的(這隻針對用 USB 連線攝像頭的,用筆記本自帶的攝像頭可忽略)。
  3. 裝置掛載問題 攝像頭沒有被掛載,如果是虛擬機器需要手動勾選裝置。
  4. 硬體問題 在就是檢查一下USB線跟電腦USB介面。
  5. 影片壓縮格式的問題 部分影片壓縮格式在OpenCV中不支援。

實驗總結 anhui/

初學者可能對 OpenCV 處理會很頭暈,因為它涉及到的函式有很多,每一個函式會有不同的用法,如果要透過 OpenCV 去呼叫攝像頭完成任務,就需要去學習這些內容。此次實驗從影片錄取、影片讀取再到影片特定幀的讀取一步一步帶你實現,裡面對相關函式也講解的非常透徹,相關引數也進行了說明,涉及到實踐的地方已經幫你把相關的原始碼給出,學習不會有障礙。當然,實驗最後也給出了攝像頭讀取失敗問題的排查步驟,讓你在學習的過程中能夠得到滿足。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30239065/viewspace-2729032/,如需轉載,請註明出處,否則將追究法律責任。

相關文章