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 无法从子目录加载图像

OpenCV 程序无法启动,因为 Visual Studio 2010 中缺少 MSVCP110D.dll

Visual Studio 2010 OpenCV 多线程垫不复制到另一个垫