程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Python:使用PyAV提取視頻關鍵幀

編輯:Python

Python:使用PyAV提取視頻關鍵幀

  • 1.軟件環境️
  • 2.問題描述
  • 3.解決方法
  • 4.結果預覽

1.軟件環境️

Windows10 教育版64位
Python 3.6.3
PyAV 8.0.3

2.問題描述

在提取視頻文件的關鍵內容時,手動查看會非常耗時。即使你快進視頻,一個小時的視頻也需要超過10分鐘;通常,一秒鐘的視頻包含24幀圖像。如果你能捕獲視頻中的關鍵幀key frame,你可以把它理解成論文裡面的摘要,看完關鍵幀就知道這個視頻主要在講什麼了),尤其是在長時間拍攝類似鏡頭的場景中,對圖像進行重復數據消除將有助於過濾掉大多數噪聲幀,並最大程度地提取視頻的核心內容。

隨著短視頻越來越流行,視頻的內容分析與文本的內容分析一樣重要。然而,如果每個分析師都想看每一段視頻,那就需要太多時間。即使使用快進功能,節省的時間仍然不夠。此外,由於人為疏忽,內容分析會出現錯誤和遺漏。相較於基於文本的內容分析,會發現一個主要的區別:查看文本內容可以一目十行,並且沒有強制的前後時間線。相反,觀看流媒體必須消耗流媒體的長度。然後我們會有一個問題:我們能一目了然地看到流媒體嗎?事實上,視頻流中的大量信息是冗余的,並且信息量非常低。信息量僅集中在一個關鍵幀(也稱為信息幀I幀)圖片中。如果你把這些圖片一張一張地放在面前,你也可以做到像文本內容一樣一目十行,減少人為疏忽。

關於視頻的相關概念可以看一下這個博客:
音視頻pts、dts基本概念及理解

那麼有沒有什麼方法能夠高效的提取視頻的關鍵幀呢?

3.解決方法

當然有啦,這就是我們今天的主角——PyAV

PyAVFFmpegPythonic 綁定,其目標是提供FFmpeg 底層庫的所有功能。 PyAV 通過容器、流、數據包、編解碼器和幀直接和精確地訪問視頻媒體。同時,它能夠方便的和其他庫進行對接,並幫助您從其他包(例如 NumpyPillow)獲取和修改數據,提取視頻關鍵幀就更不在話下了!
不廢話了,直接上代碼:

''' =========================================== @author: jayce @file: extract_video_keyframes_av.py @time: 2022/4/11 21:42 =========================================== '''
import av
import os
import shutil
path_to_video = r'E:\Code\Python\extract_video_keyframes\test video.mp4'
output_dir = r'E:\Code\Python\extract_video_keyframes\pyav'
# # 提取全部幀
# container = av.open(path_to_video)
#
# for frame in container.decode(video=0):
# frame.to_image().save(r'E:\Code\Python\比例尺鑒定\20220410比例尺鑒定\extract_video_keyframes\pyav\frame-%04d.png' % frame.index)
def extract_video_keyframes(path_to_video, output_dir):
try:
os.makedirs(output_dir, exist_ok=True)
# 提取關鍵幀
with av.open(path_to_video) as container:
# 表示我們只想查看關鍵幀
stream = container.streams.video[0]
stream.codec_context.skip_frame = 'NONKEY'
for frame in container.decode(stream):
print(frame)
# 使用frame.pts的原因是frame.index對skip_frame沒有意義,因為關鍵幀是從所有的幀中抽取中獨立的圖像,而pts顯示的就是這些獨立圖像的index;
# DTS(Decoding Time Stamp):即解碼時間戳,這個時間戳的意義在於告訴播放器該在什麼時候解碼這一幀的數據。
# PTS(Presentation Time Stamp):即顯示時間戳,這個時間戳用來告訴播放器該在什麼時候顯示這一幀的數據。
frame.to_image().save(os.path.join(output_dir, 'temporary-image-{:04d}.png'.format(frame.pts)))
except Exception as e:
print('Program error occurred:{}'.format(repr(e)))
if __name__ == "__main__":
extract_video_keyframes(path_to_video, output_dir)
# shutil.rmtree(output_dir)

4.結果預覽

​​​


渣男!都看到這裡了,還不趕緊點贊評論收藏走一波?


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved