当前位置: 首页 > news >正文

Python视频处理基础

"""
Python OpenCV 视频处理基础详解
包含:VideoCapture 读取、VideoWriter 写入、逐帧处理、FPS 控制
"""
import cv2
import numpy as np
import time
import os


def process_frame(frame, effect='gray'):
"""对单帧图像应用不同的处理效果"""
if effect == 'gray':
# 转为灰度图并转回三通道以保持视频格式
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
return cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR)
elif effect == 'edge':
# Canny 边缘检测效果
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (3, 3), 0)
edges = cv2.Canny(blurred, 50, 150)
return cv2.cvtColor(edges, cv2.COLOR_GRAY2BGR)
elif effect == 'negative':
# 颜色取反(底片效果)
return cv2.bitwise_not(frame)
elif effect == 'mosaic':
# 局部马赛克效果(对中心区域做像素化)
h, w = frame.shape[:2]
frame_out = frame.copy()
cx, cy, size = w // 2, h // 2, 40
roi = frame_out[cy - size:cy + size, cx - size:cx + size]
small = cv2.resize(roi, (10, 10), interpolation=cv2.INTER_LINEAR)
mosaic = cv2.resize(small, (size * 2, size * 2),
interpolation=cv2.INTER_NEAREST)
frame_out[cy - size:cy + size, cx - size:cx + size] = mosaic
return frame_out
return frame


# ========== 1. 打开视频文件或摄像头 ==========
# 参数可以是视频文件路径、摄像头 ID(0 表示默认摄像头)或 URL
input_path = 'input_video.mp4' # 如文件不存在,尝试打开摄像头
cap = cv2.VideoCapture(input_path)
if not cap.isOpened():
print(f"无法打开视频文件 {input_path},尝试打开摄像头...")
cap = cv2.VideoCapture(0) # 0 为默认摄像头

if not cap.isOpened():
print("无法打开任何视频源,生成模拟视频用于演示。")
# 创建一个虚拟帧来源
fps = 30
width, height = 640, 480
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter('output_video.mp4', fourcc, fps, (width, height))
# 生成 150 帧模拟动画
for i in range(150):
frame = np.zeros((height, width, 3), dtype=np.uint8)
cv2.circle(frame, (320, 240), 50 + i % 100,
(0, 255 * i // 150, 255), -1)
out.write(frame)
if i % 30 == 0:
print(f"生成模拟帧: {i // 30 + 1}s")
out.release()
print("模拟视频已生成。重新读取...")
cap = cv2.VideoCapture('output_video.mp4')

# ========== 2. 获取视频属性信息 ==========
fps = cap.get(cv2.CAP_PROP_FPS) # 帧率(每秒帧数)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) # 画面宽度
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) # 画面高度
total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) # 总帧数
duration = total_frames / fps if fps > 0 else 0 # 视频总时长(秒)

print(f"视频信息: {width}x{height}, {fps:.2f} FPS, "
f"{total_frames} 帧, 时长 {duration:.1f}s")

# ========== 3. 设置 VideoWriter 用于输出 ==========
# fourcc 指定编码格式,'mp4v' 对应 MP4 容器
output_path = 'processed_video.mp4'
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))

# ========== 4. 逐帧读取、处理并写入 ==========
frame_count = 0
start_time = time.time()
effects_cycle = ['gray', 'edge', 'negative', 'mosaic']

while True:
ret, frame = cap.read()
if not ret:
break # 视频结束或读取失败

# 根据帧号循环切换效果
effect = effects_cycle[(frame_count // 60) % len(effects_cycle)]
processed = process_frame(frame, effect)

# 在帧上叠加当前信息(帧号和效果名称)
info_text = f"Frame: {frame_count} Effect: {effect}"
cv2.putText(processed, info_text, (20, 40),
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2)

# 写入输出视频
out.write(processed)
frame_count += 1

# 控制处理速度:保持与视频原始 fps 同步
elapsed = time.time() - start_time
expected_frames = int(elapsed * fps)
if frame_count > expected_frames:
time.sleep(1.0 / fps)

# 按帧率显示进度(每 30 帧输出一次)
if frame_count % 30 == 0:
progress = frame_count / total_frames * 100 if total_frames else 0
print(f"处理进度: {frame_count}/{total_frames} ({progress:.1f}%)")

# ========== 5. 释放资源 ==========
cap.release()
out.release()
cv2.destroyAllWindows()

elapsed_total = time.time() - start_time
print(f"\n视频处理完成!")
print(f"处理帧数: {frame_count}")
print(f"实际帧率: {frame_count / elapsed_total:.2f} FPS")
print(f"输出文件: {output_path}")
print(f"视频处理基础演示完成,涵盖读取、处理、写入和 FPS 控制。")

http://www.zskr.cn/news/1430692.html

相关文章:

  • 从‘记不住’到‘忘不掉’:Cookie、Session与Token,你的Web登录方案选对了吗?
  • 前后桥独立电驱动装载机状态估计及转矩优化控制方案【附仿真】
  • 终极游戏隐身指南:掌控你的在线状态,专注每一场战斗
  • ESP32C3串口没反应?别慌,可能是Flash Mode和USB CDC这两个开关没设对
  • Weka 3.8.6安装后别闲置!从‘打开文件’到‘生成报告’:一份给新手的保姆级避坑指南
  • Claude Code上手案例 - - 三分钟实现博客系统
  • 企业级Gemini采购决策指南:如何用Gartner级TCO模型压降41%年许可支出
  • 别再傻傻分不清!RS232、RS485、RS422接口实物接线与电平转换保姆级图解
  • AI视频版权归属争议爆发!78%创作者正面临下架风险(2024司法判例白皮书首发)
  • 复古旋转拨号盘改造:基于CD4017/4026计数器与Arduino的脉冲信号处理实践
  • Android系统启动过程分析
  • 如何快速提升游戏效率:D3KeyHelper暗黑3终极自动化工具完整指南
  • 照着用就行:盘点2026年抢手爆款的的AI论文工具
  • ZLT X21 CPE的IP Passthrough模式实测:让你的NAS/软路由直接拿到公网IP,实现完美端口转发
  • 告别“正在编译”:Nessus v10.9.4插件更新效率优化与资源监控实战
  • 深入高通QMI的‘黑匣子’:用QXDM和日志分析一次失败的通信
  • 金融科技四大核心技术解析:区块链、AI、物联网与AR/VR如何重塑银行业
  • 避开这5个Scratch编程思维误区,你的蓝桥杯省赛成绩还能再提50分 | 以2023中级组真题为例
  • 从游戏引擎到无人机:聊聊四元数解欧拉角为啥比直接算更靠谱
  • 从HTTP报文到数据库查询:拆解TinyWebServer中用户登录注册的完整链路(C++/MySQL)
  • 打造四个九的在线CRM:从0到1构建99.99%可用性的核心架构
  • 5分钟免费解锁LOL国服所有皮肤:R3nzSkin换肤工具完整指南
  • 戴尔G15笔记本散热控制终极指南:用开源工具彻底告别AWCC
  • 一文搞懂:Kubernetes核心概念与实战——从Pod到Deployment、Service,云原生基础设施的第一课
  • Universal Pokemon Randomizer ZX:终极宝可梦游戏体验重塑指南
  • 商业智能BI系统哪个更好:2026年自助分析与行业覆盖能力全面横评 - 科技焦点
  • PyG安装别再踩坑了!手把手教你根据PyTorch和CUDA版本精准安装PyTorch Geometric
  • 把 VS Code Remote 的体验带到 Neovim
  • 从BOLA到dash.js:一个经典ABR算法是如何成为播放器默认选项的?
  • 手滑格式化/误删文件怎么办?实测DiskGenius免费版数据恢复全流程(附成功率分析)