opencv VideoCapture抓取RTSP高延迟,崩溃解决方法

目前项目需要对网络摄像头进行实时视觉算法检测。
遇到问题:
在使用抓取VideoCaptureRTSP流的过程中,若需要对图像进行处理,则最后的显示结果画面就会表现出高延迟,然后卡住,很快崩溃;
直观感受:
图像处理速度远不如VideoCapture抓取速度,然后感觉是有内置缓存的,导致卡顿,延迟;对VideoCapture进行等待处理,效果不佳;
解决思路:
采用多线程的方式,为VideoCapture单独开一个线程,自动抓取图像,并且存储到一个容器中,容器若满了自动更新容器,清理掉前面的图像,存储最新的图像;
然后主线程直接生成对象,调用get函数获取到容器中的数据;

实现代码: QT c++版
VideoCapture的线程类
opencvcap.h

#include 
#include 
#include 
#include 
#include 


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 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:[email protected]/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);	
		
	}
}

你可能感兴趣的:(QT,opencv)