視頻寫入 (FourCC,?VideoWriter
)?
1.?VideoWriter_fourcc
?- 視頻編碼器四字符代碼
# OpenCV 3.x, 4.x
fourcc = cv2.VideoWriter_fourcc('M','J','P','G')fourcc = cv2.VideoWriter_fourcc(*'H264')fourcc = cv2.VideoWriter_fourcc(*'MJPG')
- ?FourCC?: 代表 ?Four ?Character ?Code,是一個4字節的代碼,用于指定視頻流的編碼格式(Codec)?。它決定了視頻數據如何被壓縮。
- 定義一個視頻編碼器(Codec)。視頻編碼器負責將連續的圖像幀壓縮成視頻流,顯著減小文件大小。
常用 FourCC 代碼
- Video Codecs by FOURCC - fourcc.org
- ?**
'XVID'
?: MPEG-4 編碼器。兼容性好,文件大小適中,是最常用**的選擇之一。 - ?**
'MJPG'
**?: Motion-JPEG 編碼器。質量高,但文件非常大。 - ?**
'H264'
?: H.264/AVC 編碼器。壓縮效率極高(文件小),質量好。?需要系統安裝 H.264 編碼器支持**?(如 Windows 上的 OpenH264 或 x264)。 - ?**
'MP4V'
**?: MPEG-4 視頻編碼器。常用于?.mp4
?文件。 - ?**
'AVC1'
**?: 另一種表示 H.264 的方式。 - ?**
'DIVX'
**?: DivX 編碼器(基于 MPEG-4)。
常用 FourCC 代碼與推薦的文件擴展名對應表
- 文件擴展名?: 如?
.avi
,?.mp4
,?.mov
,用于指定容器格式(Container)?。容器是一個“包裝盒”,里面可以存放由特定編碼器壓縮的視頻流、音頻流、字幕等信息。 - ?關鍵點在于:FourCC 編碼器和文件擴展名容器之間并沒有嚴格的、一對一的強制綁定關系,但存在廣泛認可和兼容的“最佳實踐”組合。?
- 選擇一個不常見的組合(例如,在?
.mp4
?文件里使用?XVID
?編碼)可能會導致某些播放器無法識別或播放。
FourCC 代碼 | 推薦文件擴展名 | 說明與常見用途 |
---|---|---|
?**'XVID' **? | .avi | ?最常用、兼容性最好的組合之一。XVID 是一個開源的 MPEG-4 視頻編碼器,生成的?.avi ?文件可以在絕大多數設備和播放器上播放。文件大小和質量平衡得很好。 |
?**'MJPG' **? | .avi | Motion-JPEG 編碼,將每一幀都壓縮為一張 JPEG 圖片。?視頻質量很高,但文件體積非常大。常用于對質量要求極高且不介意文件大小的場景。 |
?**'H264' **? | .mp4 | H.264/AVC 編碼,?當今最流行的編碼標準。壓縮效率極高(在相同質量下文件更小)。?注意?:OpenCV 可能需要系統安裝額外的開源庫(如 OpenH264 或 x264)才能使用此編碼器。 |
?**'AVC1' **? | .mp4 | 本質上是 H.264 編碼的另一種表示方法。行為與?'H264' ?類似。 |
?**'MP4V' **? | .mp4 | 代表 MPEG-4 視頻(Part 2),與 H.264(Part 10)不同。壓縮效率通常不如 H.264,但兼容性可能更好。 |
?**'DIVX' **? | .avi | DivX 編碼器(也是基于 MPEG-4)。曾非常流行,現在多用于歷史遺留項目。 |
?**'FMP4' **? | .mp4 | FFmpeg 的 MPEG-4 編碼器。如果你的 OpenCV 編譯時包含了 FFmpeg 支持,可能會用到。 |
?**'PIM1' **? | .avi | MPEG-1 編碼。非常老的格式,文件大,質量一般,現較少使用。 |
?**'X264' **? | .mp4 | 特指使用 x264 庫(一個優秀的開源 H.264 編碼器實現)。這通常需要從源碼自定義編譯 OpenCV 才能直接使用。 |
?選擇建議?:
- ?為了最大兼容性?:使用 ?**
'XVID'
? + ?.avi
**。這是 OpenCV 中最可靠、問題最少的輸出組合,幾乎總能成功。 - ?為了更小的文件?:使用 ?**
'H264'
? 或'AVC1'?
+ ?.mp4
**。這是目前網絡傳輸和存儲的標準格式。但需要確保你的 OpenCV 環境支持它(否則會寫入失敗或生成空文件)。 - 高質量,不介意文件大小:'MJPG' +??
.avi
**。
最重要的步驟?:
在編寫代碼時,始終檢查?VideoWriter
?對象是否通過?isOpened()
?方法成功打開。如果首選的高效編碼器(如 H.264)不可用,則回退到兼容性更好的編碼器(如 XVID)。這是一種良好的編程實踐,可以增強代碼的健壯性。
fourcc = cv2.VideoWriter_fourcc(*'H264')
out = cv2.VideoWriter('test.mp4', fourcc, 20.0, (640, 480))
if not out.isOpened():print("錯誤:無法使用 H264 編碼器!將回退到 XVID。")fourcc = cv2.VideoWriter_fourcc(*'XVID')out = cv2.VideoWriter('test.avi', fourcc, 20.0, (640, 480))
2.?VideoWriter
?- 視頻寫入器
- 創建一個對象,用于將連續的圖像幀寫入視頻文件。
out = cv2.VideoWriter(filename, fourcc, fps, frame_size[, isColor])
語法:
filename
: 要保存的視頻文件路徑(包括擴展名,如?'output.avi'
?或?'result.mp4'
)。fourcc
: 由?VideoWriter_fourcc
?創建的編碼器對象。fps
: 視頻的幀率(每秒幀數)。應與輸入源(如攝像頭或視頻文件)的幀率匹配或根據需求設定。frame_size
: 視頻幀的尺寸,以元組形式表示?(width, height)
。?必須與你要寫入的每一幀圖像的尺寸完全一致!??isColor
?(可選): 指定是否為彩色視頻。默認為?True
。如果寫入灰度幀,設為?False
?可能更高效。
?核心方法?:
- ?**
out.write(frame)
**?: 將一幀圖像(frame
,一個 NumPy 數組)寫入視頻文件。這是循環中最常用的方法。 - ?**
out.release()
?: ?非常重要!?**? 在完成所有幀的寫入后,必須調用此方法來正確關閉視頻文件,釋放資源并確保文件完整可播。忘記調用會導致視頻文件損壞或無法播放。
3. 完整工作流程示例
import cv2# 1. 打開攝像頭 (輸入源)
cap = cv2.VideoCapture(0) # 0 表示默認攝像頭# 2. 獲取攝像頭參數 (用于設置VideoWriter)
fps = cap.get(cv2.CAP_PROP_FPS) # 獲取攝像頭幀率
# 如果攝像頭返回0,設置一個合理的幀率 (如20)
if fps <= 0:fps = 20.0
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) # 獲取幀寬度
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) # 獲取幀高度
frame_size = (width, height)# 3. 定義視頻編碼器 (FourCC) 和創建 VideoWriter 對象 (輸出)
fourcc = cv2.VideoWriter_fourcc(*'XVID') # 使用XVID編碼器, 注意 '*' 解包
# 創建輸出文件 'output.avi'
out = cv2.VideoWriter('output.avi', fourcc, fps, frame_size)# 4. 循環處理每一幀
while cap.isOpened():# 讀取一幀ret, frame = cap.read()if not ret:print("無法從攝像頭讀取幀!")break# 例如:將幀轉換為灰度圖 (實際項目中替換為你的AI模型推理)processed_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# 5. 將處理后的幀寫入輸出視頻文件out.write(processed_frame) # 寫入處理后的幀# 6. (可選) 在本地顯示結果cv2.imshow('Processed Video', processed_frame)# 按 'q' 鍵退出if cv2.waitKey(1) & 0xFF == ord('q'):break# 7. 釋放資源 (非常重要!)
cap.release() # 釋放攝像頭
out.release() # 釋放VideoWriter,確保文件正確關閉
cv2.destroyAllWindows() # 關閉所有窗口
print("視頻已保存為 'output.avi'")
4.詳解?cv2.waitKey(1)
:圖像刷新與鍵盤輸入的完美結合
cv2.waitKey(1)
?是 OpenCV 圖像處理中一個看似簡單但極其重要的函數,它在實時應用中扮演著關鍵角色。- 函數原型:
- retval = cv2.waitKey([, delay])
- 參數:
- delay: 等待鍵盤事件的時間(以毫秒為單位)。默認值為0。
- 返回值:
- retval: 返回按下的鍵的ASCII碼值。如果沒有按鍵被按下,則返回-1。
4.1 ?圖像窗口刷新機制?
cv2.waitKey()
?是 OpenCV 窗口系統的事件處理核心- 調用此函數會強制刷新所有通過?
cv2.imshow()
?顯示的窗口? - 沒有這個調用,窗口會顯示為灰色或顯示舊內容,無法更新為最新圖像幀
4.2???鍵盤事件檢測?
- 函數會檢測并返回最近按下的按鍵的 ASCII 碼值?
- 參數?
1
?表示等待時間為 ?1 毫秒,這是一個非阻塞式等待 - 在等待期間,它會檢查是否有按鍵事件發生
4.3?waitKey(0)
?- 無限等待
- 程序會暫停,直到用戶按下任意鍵
- 常用于靜態圖像顯示場景
- 示例:顯示一張圖片后等待用戶按鍵關閉窗口
4.4?waitKey(1)
?- 短時等待(推薦用于實時應用)
- 等待 ?1 毫秒后繼續執行
- 在等待期間檢查按鍵事件
- 保持程序流暢運行的同時響應按鍵
- ?最佳實踐?:在視頻處理循環中使用
4.4??waitKey(25)
?- 控制幀率
- 等待 25 毫秒 ≈ 40 FPS (1000ms/25ms)
- 可用于控制視頻播放速度
4.5?& 0xFF
waitKey()
?返回的是 ?32 位整數?- 在 64 位系統上,高位可能包含無關數據
& 0xFF
?操作只保留最低的 8 位(一個字節)- 確保我們只獲取有效的 ASCII 碼值