目标检测用到的异步多线程处理(1)-之异步处理 完整工程下载
采用C11以上语法支持
这里为了好说明问题就不用ffmpeg ,保证代码足够简单易懂以下还是用opencv的VideoCapture描述为主.
通常在目标检测分析处理中大致思路是下面这样的:
如下:
//视频模拟camera
void testCPUvideo(const char* name)
{
cv::VideoCapture vcap;
cv::Mat fps_curr;
vcap.open(name);
vcap.set(CAP_PROP_POS_FRAMES, 1);
if (!vcap.isOpened())
return ;
while (true)
{
vcap >> fps_curr;
if (fps_curr.empty())
return ;
//DNN(fps_curr, my_objinfo); //目标检测
//draw(fps_curr, my_objinfo); //解析my_objinfo绘制框
cv::namedWindow("CPU_Video_play", cv::WINDOW_OPENGL); //gl
cv::imshow("CPU_Video_play", fps_curr);
//pushrtsp(fps_curr,1920,1080); //推出去rtsp
cv::waitKey(1);
}
cv::waitKey(0);
}
这是一个明显的单线程线性的处理方法,很多事情在同步阻塞下是不能操作的,这也导致了中间不能插入太多要求.真正项目上是力不从心的.
下面对上面做一个改进.将解码->处理->渲染(显示)分别拆开到独立线程处理.如下图:
![](https://img-blog.csdnimg.cn/2021012909262520.jpg)
void testMutiThread(const char* name)
{
//数据结构
using MAT = cv::Mat;
using MyFrame = struct
{
std::queue<MAT> image_data_queue; //解码数据
std::mutex decode_mutex;
std::queue<MAT> process_data_queue; //处理数据
std::mutex process_mutex;
std::queue<MAT> draw_data_queue; //渲染数据
std::mutex draw_mutex;
};
static MyFrame m_Frame;
std::atomic_bool brun1(true), brun2(true), brun3(true);
auto CollectTd = [&]
{
cv::VideoCapture vcap;
MAT capture264;
vcap.open(name); //打开文件
vcap.set(cv::CAP_PROP_POS_FRAMES, 1);
if (!vcap.isOpened())
return;
int numflag(0);
while (true)
{
std::string strnum = std::to_string(numflag++);
vcap >> capture264; //此处模拟相机采集数据
if (!capture264.empty())
{
std::lock_guard<std::mutex> lock_guard(m_Frame.decode_mutex);
cout << "CollectThread image_data>> " << strnum << endl;
m_Frame.image_data_queue.push(capture264);
}
else {
brun1 = brun2 = brun3 = false;
break;
}
this_thread::sleep_for(std::chrono::milliseconds(30));
}
};
auto DecodeTd =[&]
{
while (brun1)
{
if (!m_Frame.image_data_queue.empty())
{
MAT image_data;
{
std::lock_guard<std::mutex> lock_guard(m_Frame.decode_mutex);
image_data = m_Frame.image_data_queue.front();
m_Frame.image_data_queue.pop();
cout << "DecodeThread image_data<< " << endl;
}
//从收到的数据进行解码,解码后送到处理线程
MAT process_data = image_data;
{
std::lock_guard