在 Windows 下用 Python 和 OpenCV 做视频分析程序,如何加速?

从视频中提取数据,开启视频窗口的话每秒处理 5-6 帧,一小时视频要 5-6 小时处理完,我想慢点也没关系,但是 cpu 占用率只有 2%。这就不让我淡定了,明显是偷懒了,安排了多线程,好像也是不能提升速度,请问 windows 就是不会给 python 太多资源么?我开了几路脚本一起做,cpu 仍然占用率也很低。这是怎么回事?
在 Windows 下用 Python 和 OpenCV 做视频分析程序,如何加速?

33 回复

用的是 GPU?


在Windows下用Python和OpenCV加速视频分析,核心是减少CPU解码负担并利用硬件加速。最直接有效的方法是使用OpenCV的cv2.VideoCapture时指定后端为支持硬解的CAP_MSMF(Media Foundation)或CAP_DSHOW(DirectShow),并设置cv2.CAP_PROP_HW_ACCELERATION。如果硬件支持,这能显著降低CPU占用。

不过,OpenCV的硬解支持有时不太稳定。更可靠的方案是使用ffmpeg-pythonPyAV库,它们对硬件解码(如NVIDIA的NVDEC、Intel的QSV)支持更好。你可以先用ffmpeg硬解,再把帧传给OpenCV处理。

这里给你个用ffmpeg-python硬解结合OpenCV的完整例子:

import cv2
import ffmpeg
import numpy as np

def decode_hw(video_path, hw_device='cuda'):  # 也可用 'dxva2' 或 'qsv'
    # 使用ffmpeg硬件解码,输出原始BGR帧
    probe = ffmpeg.probe(video_path)
    video_info = next(s for s in probe['streams'] if s['codec_type'] == 'video')
    width = video_info['width']
    height = video_info['height']

    process = (
        ffmpeg
        .input(video_path, hwaccel=hw_device, hwaccel_output_format='cuda')  # 硬解到GPU
        .output('pipe:', format='rawvideo', pix_fmt='bgr24', vcodec='rawvideo')
        .run_async(pipe_stdout=True, pipe_stderr=True)
    )

    while True:
        in_bytes = process.stdout.read(width * height * 3)
        if not in_bytes:
            break
        # 将字节数据转为numpy数组(仍在CPU内存)
        frame = np.frombuffer(in_bytes, np.uint8).reshape([height, width, 3])
        
        # 这里进行你的OpenCV处理,例如:
        # gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        # ... 你的分析逻辑
        
        yield frame

    process.wait()

# 使用示例
for frame in decode_hw('your_video.mp4', hw_device='dxva2'):  # Windows常用dxva2
    cv2.imshow('Frame', frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cv2.destroyAllWindows()

另外,如果分析算法不复杂,可以试试用OpenCV的cv2.cuda模块把处理也放到GPU上,但注意这需要额外编译支持CUDA的OpenCV。

简单说,优先用ffmpeg硬解,比折腾OpenCV后端更靠谱。

放代码

不敢放,太丑了,流程比较简单,识别轮廓,拟和椭圆和质点,记录 csv,甚至没有定义函数。

没有就是 cpu。

用的是机械硬盘?或者内存比较小?

上异步,分分钟跑满你的 cpu。

多线程改为多进程

计算密集的任务试试多进程

是不是时间消耗在 IO 操作上了

试着多将几帧一次性读入内存看看行不行?运行的时候看下资源占用率是不是硬盘开销比较大,如果你 CPU 相当牛叉有十几个核可以试试用 MATLAB 并行。

5/6 帧一秒,视频好歹也 25 帧一秒最少

我说的是处理速度,不是播放速度,一小时视频 5 个小时处理完没毛病

建议用 go 或者 rust

  1. 可以只处理部分帧(关键帧?); 2. 每帧太大的话,降采样变小点;

是处理速度

如果只是线、椭圆检测啥的,OpenCV 好像提供跟踪,应该快点吧。

应该是 io 没跟上,导致 cpu 工作不饱和

换 c++

OpenCV 的 Python 绑定,调的也是 C++。

我觉得可能是,其实硬盘没有跟忙。

初级菜鸟,还不会那些语言。我也不会多进程,就是在系统下一次运行了 9 个脚本分别处理 9 个视频。发现内存占用多了一些,cpu 仍然是 2-10%。关闭 imshow 函数会快一点,大概是 3 个小时能处理一个小时视频。 采样量已经非常小了 288:100。我觉得可能是 io 的问题

请问具体是哪个函数呢?

把事情分解开来做

比如一段视频,2000 帧,提取出 100 帧出来,把这个时间算一下,花了多长时间
然后分析其中 1 帧,看多长时间,

这样来找出瓶颈在哪里,

如果 cpu 利用率不高,可以开 50 个进程,同时分析 50 帧嘛

给自己一个入 1080 的理由

首先,和 GPU 没关系,上 1080 也没用,不单独写针对 GPU 的特定版本是在 CPU 上跑的;
其次,换 GO 和 RUST,也要 OpenCV 支持,现在只支持 python、Java、C 和 C++;
最后没有代码的话,猜测是 IO 跟不上或者后面一直在等前面处理完?
建议一次读入比如 10 张图像,开 10 个线程并行处理。语言换 C++也行,速度会快一点。

谢谢,我试下

CPU 不高肯定是非 CPU 瓶颈,你得先找出瓶颈再分析。。。

上 tbb 直接让你的 cpu 100%

放代码出来看看。。如果处理是可并行的,可以考虑多线程,or 用 gpu 来加速,但做这些可能都还是用 C++来做方便些

There are at least 5 types of tracker algorithms that can be used:

- MIL
- BOOSTING
- MEDIANFLOW
- TLD
- KCF

[OpenCV: Introduction to OpenCV Tracker]( http://docs.opencv.org/3.1.0/d2/d0a/tutorial_introduction_to_tracker.html )

多线程换多进程。。

加时延统计 慢慢分析

回到顶部