視頻抽幀
視頻文件是多媒體數據中比較常見的一種,也是入門門檻比較高的一個領域。視頻數據相關的領域任務包括視頻物體檢測、視頻物體追蹤、視頻分類、視頻檢索和視頻摘要抽取等。
視頻數據與圖像數據非常類似,都是由像素點組成的數據。在視頻數據在非音頻部分基本上可以視為多幀(張)圖像數據的拼接,即三維圖像的組合。由於視頻數據與圖像數據的相似性,在上述列舉的視頻領域任務中大都可以借助圖像方法來完成。
文本將講解視頻抽幀的幾種方法,具體包括以下幾種抽幀方式:
- 抽取視頻關鍵幀(IPB幀)
- 抽取視頻場景轉換幀
- 按照時間進行均勻抽幀
- 抽取制定時間的視頻幀
在進行講解具體的抽幀方式之前,我不得不介紹下FFmpeg。FFmpeg是一套可以用來編碼、解碼、合成和轉換音頻和視頻數據的開源軟件,提供了非常全面的音視頻處理功能。如果你的工作內容是視頻相關,那么ffmpeg是必須要掌握的軟件了。FFmpeg提供了常見音視頻和編解碼方式,能夠對眾多的音視頻格式進行讀取,基本上所有的軟件都會借助FFmpeg來完成音視頻的讀取操作。
FFmpeg的學習資料可以參考:
# 查看視頻信息
> ffmpeg -i 666051400.mp4
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '666051400.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf57.56.100
Duration: 00:17:02.00, start: 0.000000, bitrate: 374 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p,
Metadata:
handler_name : VideoHandler
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz
Metadata:
handler_name : SoundHandler
At least one output file must be specified
抽取視頻關鍵幀(IPB幀)
視頻關鍵幀(Video Keyframes)是用於視頻壓縮和視頻編解碼的幀,視頻關鍵幀是包含了完整信息的幀,其他的非關鍵幀將會使用與關鍵幀的差值進行壓縮。視頻幀具體可以分為IPB幀三種:
- I幀表示關鍵幀,是最完整的幀畫面,一般視頻封面都選擇I幀;
- P幀單預測幀,利用之前的I幀或P幀,采用運動預測的方式進行幀間預測編碼;
- B幀雙向預測幀,利用雙向幀進行預測編碼;
一般情況下關鍵幀`I幀`是信息最多的幀,也是用途最多的幀。在視頻檢索和視頻分類任務中一般都借助`I幀`來完成,在一個時長60s的視頻中,可以抽取得到16個I幀、84個P幀和184個B,I幀數量少包含的信息卻是最多的。
- 使用ffprobe提取出IPB幀的時間:
ffprobe -i 666051400.mp4 -v quiet -select_streams v -show_entries frame=pkt_pts_time,pict_type
- 抽取IPB幀到jpg圖片:
# 抽取I幀
ffmpeg -i 666051400.mp4 -vf "select=eq(pict_type\,I)" -vsync vfr -qscale:v 2 -f image2 ./%08d.jpg
# 抽取P幀
ffmpeg -i 666051400.mp4 -vf "select=eq(pict_type\,P)" -vsync vfr -qscale:v 2 -f image2 ./%08d.jpg
# 抽取B幀
ffmpeg -i 666051400.mp4 -vf "select=eq(pict_type\,B)" -vsync vfr -qscale:v 2 -f image2 ./%08d.jpg
由於ffmpeg抽取幀並無法按照時間戳來命名,需要手動將ffprobe提取出來的幀時間與抽取幀的圖片進行對應重命名。關鍵幀具體的定義和用途可以參考:https://en.wikipedia.org/wiki/Key_frame
抽取視頻場景轉換幀
在視頻中可以按照視頻的鏡頭切換可以將視頻分為不同的場景(scene boundaries),為了直觀感受可以觀看下面一個視頻。
http://www.scikit-video.org/stable/_static/scene_cuts.mp4
視頻場景抽取算法一般是使用幀間的相似差異程度來衡量,如果視頻幀大於某一個閾值則認為是一個新的場景,否則不是一個新的場景。在scikit-video中提供了顏色相似度和邊緣相似度兩種度量方式,思路非常簡單:
https://github.com/scikit-video/scikit-video/blob/master/skvideo/measure/scene.py
但是在我自己試驗的過程中發現scikit-video中的場景檢測非常慢,一個視頻需要幾分鍾才能計算得到結果。后來在閱讀ffmpeg文檔過程中發現,ffmpeg早就有場景檢測的命令,而且速度飛快。
# https://ffmpeg.org/ffmpeg-filters.html#select_002c-aselect
# 其中0.1表示幀為新場景的概率
ffmpeg -i 666051400.mp4 -filter:v "select='gt(scene,0.1)',showinfo" -f null - 2>&1
scikit-video的場景檢測速度慢是以下原因:scikit-video中場景檢測的實現方式是讀取所有的視頻幀,這個步驟非常耗時;而ffmpeg能夠根據視頻幀的壓縮情況來選擇性讀取幀,速度就非常快了。但是scikit-video庫還是很直觀的,我也從庫源代碼學習到了很多。
如果ffmpeg有對應的功能命令,優先使用ffmpeg來完成。
均勻抽幀
# -r 指定抽取的幀率,即從視頻中每秒鍾抽取圖片的數量。1代表每秒抽取一幀。
ffmpeg -i 666051400.mp4 -r 1 -q:v 2 -f image2 ./%08d.000000.jpg
抽取制定時間的幀
# 耗時0.07s
ffmpeg -ss 00:00:30 -i 666051400.mp4 -vframes 1 0.jpg
# 耗時0.68s
ffmpeg -i 666051400.mp4 -ss 00:00:30 -vframes 1 0.jpg
為什么上述兩個命令時間差距這么大呢,也就是-i與-ss的位置換了一下。區別就是如果-ss在前面,則會使用關鍵幀信息來進行索引,則會非常快。
文章來自:https://zhuanlan.zhihu.com/p/85895180?utm_source=wechat_session&utm_medium=social&utm_oi=46204255731712