为什么需要多线程处理视频流
在之前有写过一篇文章Python环境下OpenCV视频流的多线程处理方式,上面简单记录了如何使用Python实现对OpenCV视频流的多线程处理。简单来说,在目标检测等任务中,如果视频流的捕获、解码以及检测都在同一个线程中,那么很可能出现目标检测器实时性不高导致的检测时延问题。使用多线程处理,将视频帧的捕获和解码放在一个线程,推理放在一个线程,可以有效缓解时延的问题,使得目标检测的实时性看似有所提升。
C++的多线程处理方式
C++的处理方式与Python大致相同,但却可能遇到一些问题,如使用OpneCV多线程时X11库报错、OpenCV显示卡死等问题,这些问题可能的解决方法会在后面简单提一下。在本文中,使用的多线程是c++11中引入的thread标准库,实现方式则包括函数封装和类封装两种。
函数封装的实现方式
函数封装的实现方式相比类封装要更为简洁,当然可复用性也会降低。简单的示例代码如下:
// video_test.cpp
#include <iostream>
#include <thread>
#include <mutex>
#include <atomic>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
static std::mutex mutex;
static std::atomic_bool isOpen;
static void cameraThreadFunc(int camId, int height, int width, cv::Mat* pFrame)
{
cv::VideoCapture capture(camId);
capture.set(cv::CAP_PROP_FOURCC, CV_FOURCC('M', 'J', 'P', 'G'));
capture.set(cv::CAP_PROP_FRAME_WIDTH, width);
capture.set(cv::CAP_PROP_FRAME_HEIGHT, height);
capture.set(cv::CAP_PROP_FPS, 30);
if (!capture.isOpened()) {
isOpen = false;
std::cout << "Failed to open camera with index " << camId << std::endl;
}
cv::Mat frame;
while (isOpen) {
capture >> frame;
if (mutex.try_lock()) {
frame.copyTo(*pFrame);
mutex.unlock();
}
cv::waitKey(5);
}
capture.release()