Visual Studio 2010 OpenCV 多线程垫不复制到另一个垫
Posted
技术标签:
【中文标题】Visual Studio 2010 OpenCV 多线程垫不复制到另一个垫【英文标题】:Visual Studio 2010 OpenCV Multithread Mat does not copy to another Mat 【发布时间】:2016-04-02 22:44:39 【问题描述】:大家下午好!
我一直在使用带有 OpenCV 的 Visual Studio 2010 来开发人脸识别代码。我试图通过两个线程来完成任务(我需要这样做,因为我将把它应用到一个更大的项目中),一个(主要)显示帧,第二个捕获(来自我笔记本电脑的网络摄像头)并将帧存储在 Mat 对象上(快速捕获)。
这里的不便之处在于第二个线程正在捕获帧,但主线程没有显示它们。我认为将 Mat 从捕获线程复制到主线程上的 Mat 存在问题(“current_frame”在我执行分配后似乎为空)
这是代码(我正在使用 Boost::Thread 进行多线程)
带有建议的新代码
全局声明
#include <iostream>
#include <stdio.h>
#include <boost\thread.hpp>
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;
boost::mutex mtx;
功能
void camCapture(VideoCapture& cap, Mat& frame, bool* Capture)
while (*Capture==true)
mtx.lock();
cap >> frame;
mtx.unlock();
if(frame.empty())
cout<<"No hay captura"<<endl;
else
cout<<"Frame capturado"<<endl;
cout << "camCapture finished\n";
return;
主要
int main()
try
VideoCapture cap(0); // open the default camera
Mat frame,current_frame, SFI, Input;
bool *Capture = new bool;
*Capture = true;
if (!cap.isOpened()) // check if we succeeded
return -1;
//your capture thread has started
boost::thread captureThread(camCapture, cap, frame, Capture);
while(1)
if(frame.empty())
cout<<"Frame en hilo principal vacio"<<endl;
else
cout<<"Frame en hilo principal capturado"<<endl;
mtx.lock();
current_frame = frame.clone();
mtx.unlock();
if(current_frame.empty())
cout<<"Current_Frame vacio"<<endl;
else
imshow("Streaming",current_frame);
if(waitKey(10)==27)break;
//Terminate the thread
captureThread.join();
catch(Exception & e)
cout<<e.what()<<endl;
return 0;
【问题讨论】:
存在多个问题。 1. 你必须通过引用函数来传递“帧”,否则你只会更新一个局部变量(如果 Mat 标头共享数据但很容易出错,可能仍然有效)。 2. 你也必须在 cap >> 框架周围锁定互斥锁。 3. 在主锁上,仅在 .clone() 行周围锁定互斥锁,以免在非关键代码期间阻塞。 4.您的线程是否在循环中调用 camCapture?看起来你的线程只捕获一个图像并在之后返回 5. 不确定 cap 是否也必须通过引用传递(我不知道复制的 VideoCapture 对象的行为) 感谢回复,我是新手,不懂那么多东西,我做了这样的更改,1.在函数上,通过引用传递对象“框架”和“cap”、void camCapture(VideoCapture &cap、Mat& frame、bool* Capture)。 2. mtx.lock();帽>>框架; mtx.unlock(); 3.mtx.lock(); current_image=frame.clone(); mtx.unlock(); 4.不,它没有,我知道当我调用 boost::thread captureThread(camCapture, cap, frame, Capture) 时,函数 camcapture 开始无限期地捕获帧(直到 bool变量捕获更改为假)。我必须在 while 循环中调用 capturethread 吗?因为如果我这样做,我也必须放入 captureThread.join()。当我使用 if(current_frame.empty()) 进行测试时,我进行了前 3 次更改并且 Mat 对象“current_image”仍然为空。再次感谢您的帮助。 我正在寻找的是创建一个线程来连续捕获帧并将其存储在同一帧上,然后,当主线程需要一个帧时,它将获得最新的帧而不是缓冲区中最旧的。(我认为消除了应用程序启动时的滞后) 【参考方案1】:根据Boost threads - passing parameters by reference,如果你想通过引用boost::thread函数来传递变量,你必须使用boost::ref(v)
。但你可以改用指针。
此外,您应该将互斥锁作为指针或引用变量传递给线程,而不是将其用作全局变量:
#include <iostream>
#include <stdio.h>
#include <boost/thread.hpp>
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;
boost::mutex mtx;
void camCapture(VideoCapture& cap, Mat& frame, bool* Capture)
while (*Capture == true)
mtx.lock();
cap >> frame;
mtx.unlock();
if (frame.empty())
cout << "No hay captura" << endl;
else
cout << "Frame capturado" << endl;
cout << "camCapture finished\n";
return;
int main()
try
VideoCapture cap(0); // open the default camera
Mat frame, current_frame, SFI, Input;
bool *Capture = new bool; // better not use a pointer here, but use a bool and pass the address or by reference.
*Capture = true;
if (!cap.isOpened()) // check if we succeeded
return -1;
//your capture thread has started
boost::thread captureThread(camCapture, boost::ref(cap), boost::ref(frame), Capture);
while (1)
mtx.lock();
current_frame = frame.clone();
mtx.unlock();
if (current_frame.empty())
cout << "Current_Frame vacio" << endl;
else
imshow("Streaming", current_frame);
if (waitKey(10) == 27)
// TODO: you should use a mutex (or an atomic type) here, too, maybe setting a bool is thread-safe, but this can't be guaranteed for each hardware!
*Capture = false;
break;
//Terminate the thread
captureThread.join();
// give memory free:
delete Capture;
catch (Exception & e)
cout << e.what() << endl;
return 0;
【讨论】:
上帝保佑你 Micka !...它完美运行...非常感谢您的帮助和时间...我在 main 上声明互斥锁,并通过 camCapture 函数的引用传递它(添加参数 boost::mutex& mtx。当我在 main 上将它作为参数调用时, boost::ref(mtx)) ...我还修改了我使用引用的每个变量(cap 和 frame)和添加它 boost::ref,就像你说的那样......以上是关于Visual Studio 2010 OpenCV 多线程垫不复制到另一个垫的主要内容,如果未能解决你的问题,请参考以下文章
Visual Studio 2010 的 opencv 2.4.3 配置问题
Visual Studio 2010下的OpenCV 2.4.10安装过程
如何在 Visual Studio 2010 中部署基于 OpenCV 的独立项目?
opencv 和 Visual Studio 2010 无法从子目录加载图像