使用Python?+?OpenCV提取和保存視頻幀
引言
在計(jì)算機(jī)視覺(jué)、機(jī)器學(xué)習(xí)和圖像處理應(yīng)用中,從視頻中處理圖像幀是一個(gè)常見(jiàn)的任務(wù)。Python提供了一些強(qiáng)大的庫(kù)和工具,使我們能夠輕松地從視頻中提取幀并對(duì)其進(jìn)行處理。
百度百科: OpenCV是一個(gè)基于Apache2.0許可(開(kāi)源)發(fā)行的跨平臺(tái)計(jì)算機(jī)視覺(jué)和機(jī)器學(xué)習(xí)軟件庫(kù),可以運(yùn)行在Linux、Windows、Android和Mac OS操作系統(tǒng)上。它輕量級(jí)而且高效——由一系列 C 函數(shù)和少量 C++ 類(lèi)構(gòu)成,同時(shí)提供了Python、Ruby、MATLAB等語(yǔ)言的接口,實(shí)現(xiàn)了圖像處理和計(jì)算機(jī)視覺(jué)方面的很多通用算法。
環(huán)境準(zhǔn)備
使用 OpenCV 庫(kù)從視頻中提取特定幀并保存為圖像文件,首先需要確保安裝了必要的庫(kù)。
注意??:OpenCV庫(kù)為 opencv-python ,導(dǎo)入OpenCV語(yǔ)法為 import cv2
pip install opencv-python numpy matplotlib
代碼實(shí)現(xiàn)
注意??:運(yùn)行代碼需通過(guò)命令行的方式
import cv2
import os
import argparse
from datetime import timedelta
from pathlib import Path
def extract_frames(video_path, output_dir, frame_interval=None, time_interval=None, prefix="frame"):
"""
從視頻中提取幀并保存到指定目錄
參數(shù):
video_path: 視頻文件路徑
output_dir: 輸出目錄
frame_interval: 幀間隔(每多少幀提取一幀)
time_interval: 時(shí)間間隔(秒)
prefix: 輸出文件名前綴
"""
# 檢查視頻文件
if not os.path.isfile(video_path):
print(f"錯(cuò)誤: 視頻文件 '{video_path}' 不存在")
return
# 創(chuàng)建輸出目錄 確保輸出目錄存在
os.makedirs(output_dir, exist_ok=True)
# 打開(kāi)視頻文件
cap = cv2.VideoCapture(video_path)
if not cap.isOpened():
print(f"錯(cuò)誤: 無(wú)法打開(kāi)視頻文件 {video_path}")
return
# 獲取視頻文件名(不含擴(kuò)展名)作為默認(rèn)前綴
if prefix is None:
video_name = Path(video_path).stem # 例如: "input" from "input.mp4"
prefix = video_name
# 獲取視頻屬性
fps = cap.get(cv2.CAP_PROP_FPS)
frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
duration = frame_count / fps
print(f"視頻信息:")
print(f" 視頻路徑: {video_path}")
print(f" 幀率: {fps:.2f} fps")
print(f" 總幀數(shù): {frame_count}")
print(f" 分辨率: {width}x{height}")
print(f" 時(shí)長(zhǎng): {timedelta(seconds=duration)}")
# 確定提取間隔
if frame_interval is not None:
interval = frame_interval
use_frame_interval = True
print(f"將每 {interval} 幀提取一幀")
elif time_interval is not None:
interval = max(1, int(time_interval * fps)) # 確保至少1幀
use_frame_interval = True
print(f"將每 {time_interval} 秒({interval}幀)提取一幀")
else:
interval = 1
use_frame_interval = True
print("將提取所有幀")
# 開(kāi)始提取幀
frame_number = 0
saved_count = 0
print("\n開(kāi)始提取幀...")
while True:
ret, frame = cap.read()
if not ret:
break
# 檢查是否應(yīng)該保存當(dāng)前幀
if use_frame_interval and frame_number % interval == 0:
save_path = os.path.join(output_dir, f"{prefix}_{frame_number:06d}.jpg")
cv2.imwrite(save_path, frame)
saved_count += 1
frame_number += 1
cap.release()
print(f"完成提取: 共處理 {frame_number} 幀,保存 {saved_count} 張到 {output_dir}")
def main():
parser = argparse.ArgumentParser(description='從視頻中提取幀并保存')
parser.add_argument('--video_dir', help='視頻所在目錄(處理目錄下所有視頻)')
parser.add_argument('--video_path', help='單個(gè)視頻文件路徑(與video_dir互斥)')
parser.add_argument('--output_dir', help='輸出目錄')
group = parser.add_mutually_exclusive_group()
group.add_argument('--frame_interval', type=int, help='幀間隔(每多少幀提取一幀)')
group.add_argument('--time_interval', type=float, help='時(shí)間間隔(秒)')
parser.add_argument('--prefix', help='輸出文件名前綴(默認(rèn)為視頻文件名)')
parser.add_argument('--extensions', default='mp4,mkv,avi,mov', help='允許的視頻擴(kuò)展名,逗號(hào)分隔')
args = parser.parse_args()
# 驗(yàn)證輸入?yún)?shù)
if not args.video_dir and not args.video_path:
parser.error("請(qǐng)指定 --video_dir 或 --video_path")
# 獲取視頻文件列表
video_files = []
if args.video_dir:
if not os.path.exists(args.video_dir):
print(f"錯(cuò)誤: 視頻目錄 {args.video_dir} 不存在")
return
allowed_extensions = set(args.extensions.lower().split(','))
for entry in os.scandir(args.video_dir):
if entry.is_file() and entry.name.lower().split('.')[-1] in allowed_extensions:
video_files.append(entry.path)
if not video_files:
print(f"錯(cuò)誤: 在目錄 {args.video_dir} 中未找到支持的視頻文件")
return
else:
if not os.path.exists(args.video_path):
print(f"錯(cuò)誤: 視頻文件 {args.video_path} 不存在")
return
video_files = [args.video_path]
print(f"找到 {len(video_files)} 個(gè)視頻文件需要處理")
# 處理每個(gè)視頻
for video_path in video_files:
video_name = Path(video_path).stem
# 使用視頻名作為默認(rèn)前綴(除非用戶(hù)指定了全局前綴)
prefix = args.prefix if args.prefix else video_name
extract_frames(
video_path,
args.output_dir, # 直接使用用戶(hù)指定的輸出目錄,不再創(chuàng)建子目錄
args.frame_interval,
args.time_interval,
prefix
)
if __name__ == "__main__":
main()
運(yùn)行 命令行工具
你可以通過(guò)以下命令行方式運(yùn)行這個(gè)視頻幀提取程序。
程序支持兩種模式:①單視頻處理和②批量處理目錄中的所有視頻。
1 處理單個(gè)視頻文件
bash 命令
python [代碼名] --video_path 視頻路徑 --output_dir 輸出目錄 [其他參數(shù)]
示例:
提取 input.mp4 的幀,每秒提取一幀,保存到 frames/ 目錄:
python frame.py --video_path input.mp4 --output_dir frames/ --time_interval 1.0
2 批量處理目錄中的所有視頻
bash 命令
python frame.py --video_dir 視頻目錄 --output_dir 輸出目錄 [其他參數(shù)]
示例:
處理 videos/ 目錄下的所有視頻(默認(rèn)支持 mp4、mkv、avi、mov 格式),每 30 幀提取一幀,保存到 frames/ 目錄:
python frame.py --video_dir videos/ --output_dir frames/ --frame_interval 30
完整幫助信息
查看所有可用參數(shù):
python frame.py --help
結(jié)語(yǔ)
使用Python和OpenCV提取視頻幀是一項(xiàng)強(qiáng)大而靈活的技術(shù),適用于各種計(jì)算機(jī)視覺(jué)和多媒體處理任務(wù)。本文介紹的方法從基礎(chǔ)到高級(jí),覆蓋了大多數(shù)實(shí)際應(yīng)用場(chǎng)景。通過(guò)調(diào)整參數(shù)和結(jié)合其他Python庫(kù),您可以構(gòu)建更復(fù)雜的視頻處理流程。
到此這篇關(guān)于使用Python + OpenCV提取和保存視頻幀的文章就介紹到這了,更多相關(guān)OpenCV提取和保存視頻幀內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python 讀取攝像頭數(shù)據(jù)并保存的實(shí)例
今天小編就為大家分享一篇python 讀取攝像頭數(shù)據(jù)并保存的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-08-08
Python的Tqdm模塊實(shí)現(xiàn)進(jìn)度條配置
這篇文章主要介紹了Python的Tqdm模塊實(shí)現(xiàn)進(jìn)度條配置,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02
dpn網(wǎng)絡(luò)的pytorch實(shí)現(xiàn)方式
今天小編就為大家分享一篇dpn網(wǎng)絡(luò)的pytorch實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-01-01
使用Python實(shí)現(xiàn)PDF與SVG互轉(zhuǎn)
SVG(可縮放矢量圖形)和PDF(便攜式文檔格式)是兩種常見(jiàn)且廣泛使用的文件格式,本文將詳細(xì)介紹如何使用?Python?實(shí)現(xiàn)?SVG?和?PDF?之間的相互轉(zhuǎn)換,感興趣的可以了解下2025-02-02
Python OpenCV 針對(duì)圖像細(xì)節(jié)的不同操作技巧
這篇文章主要介紹了Python OpenCV 針對(duì)圖像細(xì)節(jié)的不同操作,包括圖像像素的說(shuō)明,圖像屬性信息的獲取與修改以及圖像通道的知識(shí)(包括拆分通道和合并通道),需要的朋友可以參考下2021-08-08
python利用線(xiàn)程生成不同尺寸的縮略圖實(shí)例詳解
這篇文章主要介紹了python利用線(xiàn)程生成不同尺寸的縮略圖,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-05-05
django 發(fā)送手機(jī)驗(yàn)證碼的示例代碼
本篇文章主要介紹了django 發(fā)送手機(jī)驗(yàn)證碼的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-04-04

