OpenCV读取视频产生稳定延迟情况的解决方案(二) Solution for reading pictures with stable delay by OpenCV

OpenCV读取视频产生稳定延迟情况的解决方案(二)

Solution for reading pictures with stable delay by OpenCV

最近在做对代码的延时标定,发现了一个问题,图像处理已经达到了20ms每循环,但OpenCV的视频帧整体延时了500ms,并且第一帧收帧时如果在500ms以内就imshow帧,则出现错误中断。
搜寻了很久解决方案,有用的相关链接是以下两个:

https://blog.csdn.net/qq_24345721/article/details/102544550
https://blog.csdn.net/sazass/article/details/106946915

Opencv的videocapture库在开启后,会将照片数据不断存入缓冲区,而代码会将该缓冲区从时间最早的那张图片开始处理,如果代码处理速度小于存缓冲区的速度,则缓冲区的照片一直是满的,程序一直取的是缓冲区最早的那张照片,因此会出现几百毫秒的延迟。

解决方案:
新建一个线程,在该线程创建一个Vector < Mat >容器,并不停地将OpenCV缓冲区的照片以堆栈的形式存到该容器中,而主线程的处理程序以取栈顶的方式从容器中取出要处理的照片,因此,主程序将一直处理的是最新的照片。

#include <opencv2\opencv.hpp>  
#include <opencv2\core.hpp>
#include <opencv2\highgui\highgui.hpp>  
#include <opencv2\imgproc\imgproc.hpp>  
#include <iostream>  
#include <stdio.h>  
#include <thread>
#include <mutex>
#include <time.h>
#include ...

using namespace cv;
using namespace std;
//缓存容器
vector<Mat> m_vec_frame;
//互斥锁
mutex m_mutex;
//videocapture
VideoCapture capture;

void run();
bool get_frame(Mat &frame);
void put_frame(Mat frame);
int main(int argc, char* argv)
{
	Mat frame;
	//开始线程
	thread th1(run);//实例化一个线程对象th1,使用函数t1构造,然后该线程就开始执行了
	th1.detach();
	Sleep(2000);//要等待一段时间等线程一初始化完成,容器里会是空的,这里等待2000ms
	while (1)
	{
		bool ret = get_frame(frame);
		if (ret == false || frame.empty()) {
			cout << "false!" << endl;
		}
		cv::imshow("【视频1】", frame);
		waitKey(50);
	}
	return 0;
}

void run()
{
	capture.open(1);
	capture.set(CV_CAP_PROP_FOURCC, CV_FOURCC('M', 'J', 'P', 'G'));//参照解决方案(一)
	capture.set(CV_CAP_PROP_FRAME_WIDTH, 1600);  //设置捕获视频的宽度
	capture.set(CV_CAP_PROP_FRAME_HEIGHT, 1200);  //设置捕获视频的高度
	if (!capture.isOpened())                         //判断是否成功打开相机
	{
		cout << "captureOpen failed!" << endl;
	}
	Mat current_frame;
	capture >> current_frame;
	resize(current_frame, current_frame, Size(current_frame.cols / 2, current_frame.rows / 2), 0, 0, INTER_LINEAR);
	Sleep(50);//初始化一定要有这个初步等待延时
	while (1)
	{
		capture >> current_frame;
		resize(current_frame, current_frame, Size(current_frame.cols / 2, current_frame.rows / 2), 0, 0, INTER_LINEAR);//1600*1200太大了,缩小到800*600
		if (current_frame.empty())
		{
			cout << "frame empty\n" << endl;
			return;
		}
		put_frame(current_frame);
	}
}

void put_frame(Mat frame)
{
	m_mutex.lock();
	// 这边采用的更简单粗暴的清理方式,可以根据实际情况自定义清理方式
	if (m_vec_frame.size() >3)//测试后发现3的延时最小
		m_vec_frame.clear();
	//存入容器
	m_vec_frame.push_back(frame);
	m_mutex.unlock();
	return;
}

bool 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;
}

总结:

  1. 通过解决方案(一)和(二),OpenCV延时从500ms降低到160ms,我的大实验循环也是150ms,是一个量级的,可行。
  2. 剩下的160ms个人认为是硬件延时,不能再减少了。如果有新想法的朋友,欢迎留言讨论。
  • 9
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值