目前项目需要对网络摄像头进行实时视觉算法检测。
遇到问题:
在使用抓取VideoCaptureRTSP流的过程中,若需要对图像进行处理,则最后的显示结果画面就会表现出高延迟,然后卡住,很快崩溃;
直观感受:
图像处理速度远不如VideoCapture抓取速度,然后感觉是有内置缓存的,导致卡顿,延迟;对VideoCapture进行等待处理,效果不佳;
解决思路:
采用多线程的方式,为VideoCapture单独开一个线程,自动抓取图像,并且存储到一个容器中,容器若满了自动更新容器,清理掉前面的图像,存储最新的图像;
然后主线程直接生成对象,调用get函数获取到容器中的数据;
实现代码: QT c++版
VideoCapture的线程类
opencvcap.h
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <QThread>
#include <QMutex>
using namespace cv;
using namespace std;
class OpencvCap :public QThread
{
Q_OBJECT
public:
OpencvCap(const char* url);
~OpencvCap();
void put_frame(Mat frame);
bool get_frame(Mat &frame);
private:
void run() override;
//缓存容器
vector<Mat> m_vec_frame;
//互斥锁
QMutex m_mutex;
//videocapture
VideoCapture m_cap;
};
opencvcap.cpp
#include "opencvcap.h"
OpencvCap::OpencvCap(const char* url)
{
m_cap.open(url);
}
OpencvCap::~OpencvCap()
{
m_cap.release();
}
void OpencvCap::run()
{
if(!m_cap.isOpened())
{
qDebug("cannot open the videocapture\n");
return ;
}
Mat current_frame;
while(true)
{
m_cap >> current_frame;
if(current_frame.empty())
{
qDebug("frame empty\n");
return ;
}
put_frame(current_frame);
waitKey(20);
}
}
void OpencvCap::put_frame(Mat frame)
{
m_mutex.lock();
// 这边采用的更简单粗暴的清理方式,可以根据实际情况自定义清理方式
if(m_vec_frame.size() >5)
m_vec_frame.clear();
//存入容器
m_vec_frame.push_back(frame);
m_mutex.unlock();
return;
}
bool OpencvCap::get_frame(Mat &frame)
{
m_mutex.lock();
if(m_vec_frame.size() < 1)
return false;
else
{
//从容器中取图像
frame = m_vec_frame.back();
}
m_mutex.unlock();
return true;
}
main
实际上,这部分是分散开来的,集中起来只是方便理解
int main()
{
//创建对象,初始化
OpencvCap *m_opencvcap;
m_opencvcap = new OpencvCap("rtsp://admin:abc123456@192.168.1.64/h264/ch1/main/av_stream");
//开始线程
m_opencvcap->start();
Mat frame;
while(true)
{
bool ret = m_opencvcap->get_frame(frame);
if(ret == false || frame.empty())
return 0;
//处理图像······
imshow("windows",frame);
}
}