使用 Opencv 加速从摄像头读取视频帧

Posted

技术标签:

【中文标题】使用 Opencv 加速从摄像头读取视频帧【英文标题】:Speed up reading video frames from camera with Opencv 【发布时间】:2021-01-06 07:38:51 【问题描述】:

目前,我在 Python 中实现了我的应用程序,以通过 USB 读取相机帧。我使用 Opencv,但对于 60fps 和 1920x1080 分辨率的相机,我无法捕捉到这个速度。我尝试了一些东西:cv2.VideoCapture(0, cv2.CAP_FFMPEG),但我无法获取帧(捕获读取返回 False)。您能否提出任何解决方案或方法来提高整体速度甚至在 GPU 中处理它们。

    # Opencv 3.4.9 & Python 3.6.9
    import cv2    
    capture = cv2.VideoCapture(0, cv2.CAP_FFMPEG)

    while True:
        ret, frame = capture.read()
        if ret:
            cv2.imshow('Demo', frame)
            cv2.waitKey(1)

Opencv 是从源代码构建的:

#!/usr/bin/env bash

set -e

VERSION='3.4.9'
DOWNLOAD_URL="https://github.com/opencv/opencv/archive/$VERSION.zip"
CONTRIB_DOWNLOAD_URL="https://github.com/opencv/opencv_contrib/archive/$VERSION.zip"
CURRENT_DIR="$(pwd)"
config_opencv_with_cuda() 
  cmake -D CMAKE_BUILD_TYPE=RELEASE \
        -D CMAKE_INSTALL_PREFIX=/usr/local \
        -D INSTALL_PYTHON_EXAMPLES=OFF \
        -D WITH_CUDA=ON \
        -D ENABLE_FAST_MATH=1 \
        -D CUDA_FAST_MATH=1 \
        -D WITH_CUBLAS=1 \
        -D WITH_V4L=ON \
        -D WITH_FFMPEG=ON \
        -D WITH_GSTREAMER=ON \
        -D BUILD_opencv_cnn_3dobj=OFF \
        -D BUILD_opencv_dnn_modern=OFF \
        -D OPENCV_EXTRA_MODULES_PATH=$CURRENT_DIR/opencv_contrib-$VERSION/modules \
        -D BUILD_DOCS=OFF \
        -D BUILD_PERF_TESTS=OFF \
        -D BUILD_TESTS=OFF \
        -D BUILD_EXAMPLES=OFF ..

echo 'Uninstalling pip installation'
pip3 uninstall opencv-python opencv-contrib-python

echo 'Installing dependencies'
apt-get update && apt-get install -y \
  build-essential cmake pkg-config \
  libjpeg-dev libtiff5-dev libpng12-dev \
  libavcodec-dev libavformat-dev libswscale-dev libv4l-dev \
  libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev \
  libxvidcore-dev libx264-dev \
  libgtk2.0-dev libgtk-3-dev \
  gfortran

wget -O opencv.zip "$DOWNLOAD_URL"
wget -O opencv_contrib.zip "$CONTRIB_DOWNLOAD_URL"
unzip opencv.zip && unzip opencv_contrib.zip
cd opencv-$VERSION
mkdir build
cd build

if [[ -d /usr/local/cuda ]]; then
  config_opencv_with_cuda
else
  config_opencv_without_cuda
fi

make -j $(nproc)
make install
ldconfig

【问题讨论】:

yozr 代码长什么样子? @Micka 请检查我上面的代码,很简单 您可以尝试删除 imshow 和 waitkey 并仅计算帧数和秒数吗?对于 60 fps,可能需要使用更快的异步图像显示。您在哪种设备上运行代码?一帧的所有处理时间只有 17 毫秒! @Micka 我知道这个例子的 imshow 效果,但我想尝试更改为 opencv 的 ffmpeg 后端,但我得到的是 VideoCapture 总是返回 False,我无法使用 cv2 获取帧.VideoCapture(0, cv2.CAP_FFMPEG) 抱歉,不知道 ffnpeg videocapture 是否适用于所有情况。目前您的问题标题具有误导性。 【参考方案1】:

您无法捕捉到这种速度的原因是VideoCapture 阻塞了应用程序,而下一帧正在被读取、解码和返回。

如果我没记错的话,您正在从 USB 读取电影文件。

您可以使用FileVideoStream 对象来加速您的帧。 FileVideoStream 使用queue 结构进行读取、解码和返回。因此,应用程序在处理过程中不会被阻塞。

你需要安装imutils

点子:pip install imutils 蟒蛇:conda install -c conda-forge imutils

示例用法:

import cv2
from imutils.video import FileVideoStream as Fvs

fvs = Fvs(path="usb.mp4").start()

four_cc = cv2.VideoWriter_fourcc(*"mp4v")
writer = cv2.VideoWriter("out.mp4", four_cc, 60,
                         (1920, 1080), isColor=True)

while True:
    frame = fvs.read()

    # You write your processing code below here
    

    # If you are sure each usb frame size is (1920, 1080) comment the below state.
    frame = cv2.resize(frame, (1920, 1080))

    writer.write(frame)
    cv2.imshow("out", frame)

    if cv2.waitKey(0) & 0xFF == ord("q"):
        break

cv2.destroyAllWindows()
fvs.stop()
writer.release()

【讨论】:

感谢您的回答,但是如何使 cv2 VideoCapture 与 FFMPEG 后端一起工作? 好吧,如果您打算使用 VideoCapture,您将来会遇到速度问题。因此我写了这个答案

以上是关于使用 Opencv 加速从摄像头读取视频帧的主要内容,如果未能解决你的问题,请参考以下文章

如何opencv读取摄像头并保存每一帧图像?

如何opencv读取摄像头并保存每一帧图像

OpenCV利用Flask+Python+OpenCV实现摄像头读取图像帧网页视频流

opencv 保存摄像头视频 如何设置帧率

opencv学习之路读取视频,读取摄像头

Qt 视频采集