在OpenCL-OpenCV-Realtime-Threads中正确使用互斥锁? [英] Correctly using mutex in OpenCL-OpenCV-Realtime-Threads?

查看:87
本文介绍了在OpenCL-OpenCV-Realtime-Threads中正确使用互斥锁?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图通过GPU线程中的usb网络摄像头实时获取立体声视频流(比通过cpu获取和处理图像的速度更快),在第二个线程中处理所述流以获取人脸并控制在主要功能中通过键盘设置线程(稍后将实现). 此刻,代码正常运行了30秒,并正常运行(显示链接/链接"并在我的脸上绘制了一个矩形),然后由于"...未处理的异常(opencv_core249d.dll)"而崩溃.

Im trying to get a stereo-videostream in realtime via usb-webcams in a GPU-Thread (way faster than to get and process the images via cpu), processing said stream in a second thread to get the faces and control the threads via keyboard in the main-function (will be implemented later). At the moment the code runs properly (shows both Links/Rechts and draws a rectangle around my face) for ~30s and then crashes because of an "...unhandled exception (opencv_core249d.dll)".

我曾尝试使用互斥锁保护来处理变量链接"/"Rechts"和面孔,但是我不确定如何在Mat上下文中使用它们,因为我没有找到适用于OpenCV的任何示例.另外:我如何将链接/目录/面孔引用到线程是否正确/这是最快的线程安全变量吗?

Ive tried using mutex-lock-guard to handle the variables "Links"/"Rechts" and faces, but im not sure how to use them in Mat-context, because i didnt find any suitable examples for OpenCV. Also: is it correct how i reference Links/Rechts/faces to the thread/is it the fastest thread-safe-variety?

我的互斥锁尝试不包含在代码中.感谢您的帮助.

My mutex-trys are left out of the code. Thanks for any help.

#include <thread>
#include <iostream>
#include <functional>
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2/ocl/ocl.hpp"
#include <mutex>

using namespace std;
using namespace cv;

Mat Links = Mat::zeros(960,1080, CV_8UC3);                                          
Mat Rechts = Mat::zeros(960,1080, CV_8UC3);                                         
Mat facesMat =Mat::zeros(960,1080,CV_8UC3);                                         

std::vector<Rect> faces;

void change(Mat& Links, Mat& Rechts)
{
Mat captureFrame;
VideoCapture LeftCam(1);
VideoCapture RightCam(0);
LeftCam.set(CV_CAP_PROP_FRAME_WIDTH,1920);              
LeftCam.set(CV_CAP_PROP_FRAME_HEIGHT,1080);
RightCam.set(CV_CAP_PROP_FRAME_WIDTH,1920);
RightCam.set(CV_CAP_PROP_FRAME_HEIGHT,1080);

FileStorage fs, fs2, fs3, fs4;
Mat map1x, map1y, map2x, map2y; 
Mat mapi1x, mapi1y, mapi2x, mapi2y;
fs.open("mx1.xml", FileStorage::READ);
fs2.open("my1.xml", FileStorage::READ);
fs3.open("mx2.xml", FileStorage::READ);
fs4.open("my2.xml", FileStorage::READ);
fs["mx1"] >> map1x;
fs2["my1"] >> map1y;
fs3["mx2"] >> map2x;
fs4["my2"] >> map2y;
fs.release();
fs2.release();
fs3.release();
fs4.release();

ocl::oclMat map1xocl(map1x), map1yocl(map1y), map2xocl(map2x), map2yocl(map2y);

while (true)
{
    cv::Mat3b frame0, frame1, LeftframeRaw, RightframeRaw, LeftRoi, RightRoi, framecon;

    LeftCam >> frame0;
    RightCam >> frame1;
    LeftRoi = frame0(Rect(420,60,1080,960));                                                                    //960*1080 passend zuschneiden
    RightRoi = frame1(Rect(420,60,1080,960));
    ocl::oclMat Leftr(LeftRoi), Rightr(RightRoi), Leftt, Lefttf, Rightt, Righttf, LeftRemappedocl, RightRemappedocl;
    ocl::transpose(Leftr, Leftt);                                                                               //ACHTUNG: ocl::transpose src darf nicht dst-image sein, sonst gibts starke Bildartefakte!
    ocl::transpose(Rightr, Rightt);
    ocl::flip(Leftt, Lefttf, 1);                                                                                //ACHTUNG: ocl::flip src darf nicht dst-image sein, sonst gibts starke Bildartefakte!
    ocl::flip(Rightt, Rightt, 1);
    ocl::remap(Lefttf, LeftRemappedocl, map1xocl, map1yocl, CV_INTER_LINEAR, BORDER_CONSTANT, 0);
    ocl::remap(Rightt, RightRemappedocl, map2xocl, map2yocl, CV_INTER_LINEAR, BORDER_CONSTANT, 0);


    Links = LeftRemappedocl.clone();                                                                            //kopiere sauber in neues Mat: leer
    Rechts = RightRemappedocl.clone();                                                                          //kopiere sauber in neues Mat: leer
}
}

void facefind(Mat& f, vector<Rect>&e)
{
CascadeClassifier face_cascade;
face_cascade.load("haarcascade_frontalface_alt.xml");

while (true)
{
    Mat Lokalesf;
    Lokalesf = f.clone();
    Mat grau;
    cvtColor(Lokalesf, grau, CV_BGR2GRAY);
    equalizeHist(grau, grau);

    face_cascade.detectMultiScale(grau, faces, 1.1, 3, CASCADE_SCALE_IMAGE|CV_HAAR_SCALE_IMAGE, Size(30,30));

        e=faces;                                                                                        //kopiere sauber in neues vector<rect>
}
}

int main()
{
    Mat stereo;
    std::thread t1(change,std::ref(Links),std::ref(Rechts));
    std::thread t2(facefind,std::ref(Links),std::ref(faces));
    while (true)
    {
        for(int i = 0; i < faces.size(); i++)
        {
            Point pt1(faces[i].x + faces[i].width, faces[i].y + faces[i].height);
            Point pt2(faces[i].x, faces[i].y);

            rectangle(Links, pt1, pt2, cvScalar(0, 255, 0, 0), 1, 8, 0);
        }
        imshow("rechts", Rechts);
        imshow("links", Links);

        waitKey(10);
    }
    t1.join();
    t2.join();
    return 0;
}

我试图理解Mr.Worshipme的代码,并附上我的代码以使其工作.我在cv :: imshow和ROI中遇到有关size.width/height的两个断言错误,有人可以帮我吗?

I tried to understand the code from Mr.Worshipme and included my code to make it work. I get two assertion errors regarding size.width/height in cv::imshow and ROI, anyone can me help me out?

#include <memory>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <cmath>
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2/ocl/ocl.hpp"
#include <functional>

using namespace std;
using namespace cv;

typedef unsigned char uchar;
typedef unsigned int uint;

class FaceDetector
{
mutex imageLock, facesLock;
condition_variable imageAqcuired;
bool newImageAvailable;

Mat _img;
Mat _imgToWorkOn;
Mat _faceImages;

bool quit;
void acquireImage()
{

    Mat captureFrame;
    VideoCapture LeftCam(1);
    LeftCam.set(CV_CAP_PROP_FRAME_WIDTH,1920);              
    LeftCam.set(CV_CAP_PROP_FRAME_HEIGHT,1080);

    FileStorage fs, fs2;
    Mat map1x, map1y; 
    Mat mapi1x, mapi1y;
    fs.open("mx1.xml", FileStorage::READ);
    fs2.open("my1.xml", FileStorage::READ);
    fs["mx1"] >> map1x;
    fs2["my1"] >> map1y;
    fs.release();
    fs2.release();

    ocl::oclMat map1xocl(map1x), map1yocl(map1y);

    while (!quit)
    {
        unique_lock<mutex> ulock(imageLock);
        imageAqcuired.wait(ulock,[&](){return !newImageAvailable;}); //only take
//new image after current one was consumed

        cv::Mat3b frame0, frame1, LeftframeRaw, RightframeRaw, LeftRoi,     RightRoi,framecon;

            LeftCam >> frame0;
           LeftRoi=frame0(Rect(420,60,1080,960));                                                                   //960*1080 passend zuschneiden
        ocl::oclMat Leftr(LeftRoi), Leftt, Lefttf, LeftRemappedocl;
        ocl::transpose(Leftr, Leftt);                                                                               //ACHTUNG: ocl::transpose src darf nicht dst-image sein, sonst gibts starke Bildartefakte!
        ocl::flip(Leftt, Lefttf, 1);                                                                                //ACHTUNG: ocl::flip src darf nicht dst-image sein, sonst gibts starke Bildartefakte!
        ocl::remap(Lefttf, LeftRemappedocl, map1xocl, map1yocl, CV_INTER_LINEAR, BORDER_CONSTANT, 0);
        _img = LeftRemappedocl.clone();

        ulock.unlock();
        newImageAvailable = true;
        imageAqcuired.notify_one(); //notify that a new image is available
    }
}
void processImage()
{
    CascadeClassifier face_cascade;
    face_cascade.load("haarcascade_frontalface_alt.xml");

    while (!quit)
    {
        unique_lock<mutex> ulock(imageLock);
        imageAqcuired.wait(ulock,[&](){return newImageAvailable;}); //wait untill a new image is available
        _imgToWorkOn = _img;
        ulock.unlock();
        newImageAvailable = false;
        imageAqcuired.notify_one(); //notify the current image can be replaced by a newer one
        unique_lock<mutex> lockFace(facesLock);

        Mat grau;
        cvtColor(_imgToWorkOn, grau, CV_BGR2GRAY);
        equalizeHist(grau, grau);
        std::vector<Rect> faces;

        face_cascade.detectMultiScale(grau, faces, 1.1, 3, CASCADE_SCALE_IMAGE|CV_HAAR_SCALE_IMAGE, Size(30,30));

        for(int i = 0; i < faces.size(); i++)
        {
            Point pt1(faces[i].x + faces[i].width, faces[i].y + faces[i].height);
            Point pt2(faces[i].x, faces[i].y);

            rectangle(_imgToWorkOn, pt1, pt2, cvScalar(0, 255, 0, 0), 1, 8, 0);
        }
        _faceImages = _imgToWorkOn;

        lockFace.unlock();
    }
}

public:
FaceDetector() : newImageAvailable(false) {}
void start() {
    quit = false;
    thread t1(&FaceDetector::acquireImage,this);
    t1.detach();
    thread t2(&FaceDetector::processImage,this);
    t2.detach();
}
void stop() {
    quit = true;
}
Mat getImage() {
    lock_guard<mutex> lock(imageLock);
    return _img;
}

Mat getProcessedImage() {
    lock_guard<mutex> lock(facesLock);
    return _faceImages;
}
};


int main()
{
Mat img = Mat::zeros(960,1080, CV_8UC3);                                                //notwendig
Mat imgs = Mat::zeros(960,1080, CV_8UC3);                                               //notwendig
bool quit(false);
FaceDetector faceDet;
faceDet.start();
thread input([](bool &quitFlag) { getchar(); quitFlag = true; },ref(quit)); //stop on user press Enter
input.detach();
while (!quit) {
    Mat img = faceDet.getImage();

    imshow("links", img);

    Mat imgs = faceDet.getProcessedImage();

    imshow("gsichter", imgs);

    waitKey(1);
    this_thread::sleep_for(chrono::milliseconds(33)); //no need to show more than 30 fps...
}
faceDet.stop();
return 0;
}

再次编辑代码以允许按照建议的方式深层复制Mat图像(facetracker目前不执行任何操作,而ocl-mat-stuff/facecascade被删除以简化代码),并使代码正常工作,但是它的行为很奇怪.我的网络摄像头在运行时大约每500毫秒左右就会点亮一个led,它会点亮并通过imshow向我显示新图像,然后返回待机状态,尽管事实上它应该尽可能快地更新_img.我不知道如何在互斥环境中设置Videocapture,使其仅运行一次即可设置frame.width和height,然后作为网络摄像头图像缓冲区自由运行.继承人提到的代码:

Edit 2: Edited the code again to allow deep copys of the Mat-images as it was suggested (facetracker does nothing at the moment and ocl-mat-stuff/facecascade erased for code-simplicity) and got the code to work, but it behaves strangely. My webcam lights an led when it runs, about every 500ms or so it lights up and shows me an new image via imshow, then it goes back to standby, despite the fact that it should update _img as fast as it can. I dont know how to set up Videocapture in the mutex-environment to run only once to set frame.width and height and then run freely as the webcam-image-buffer. Heres the mentioned code:

#include <memory>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <cmath>
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2/ocl/ocl.hpp"
#include <functional>

using namespace std;
using namespace cv;

typedef unsigned char uchar;
typedef unsigned int uint;

class FaceDetector
{
mutex imageLock, facesLock;
condition_variable imageAqcuired;
bool newImageAvailable;

Mat _img;
Mat _imgToWorkOn;
Mat _faceImages;
bool quit;
int c;
void acquireImage()
{
    while (!quit)
    {

        unique_lock<mutex> ulock(imageLock);
        imageAqcuired.wait(ulock,[&](){return !newImageAvailable;}); //only take new image after current one was consumed
        VideoCapture captureDevice(0);
        if (c = 1)
        {
        captureDevice.set(CV_CAP_PROP_FRAME_WIDTH, 620);
        captureDevice.set(CV_CAP_PROP_FRAME_HEIGHT, 480);
        c = 0;
        }
        Mat captureFrame;
        captureDevice>>captureFrame;
        transpose(captureFrame,captureFrame);
        flip(captureFrame,captureFrame,1);

        _img = captureFrame.clone();

        ulock.unlock();
        newImageAvailable = true;
        imageAqcuired.notify_one(); //notify that a new image is available
    }
}
void processImage()
{
    while (!quit)
    {
        unique_lock<mutex> ulock(imageLock);
        imageAqcuired.wait(ulock,[&](){return newImageAvailable;}); //wait untill a new image is available
        _imgToWorkOn = _img.clone();
        ulock.unlock();
        newImageAvailable = false;
        imageAqcuired.notify_one(); //notify the current image can be replaced by a newer one
        unique_lock<mutex> lockFace(facesLock);
        //arbeit
        lockFace.unlock();
    }
}

public:
FaceDetector() : newImageAvailable(false) {}
void start() {
    quit = false;
    thread t1(&FaceDetector::acquireImage,this);
    t1.detach();
    thread t2(&FaceDetector::processImage,this);
    t2.detach();
}
void stop() {
    quit = true;
}
Mat getImage() {
    if (quit)
        return Mat();
    lock_guard<mutex> lock(imageLock);
    return _img;
}

Mat getProcessedImage() {
    if (quit)
        return Mat();
    lock_guard<mutex> lock(facesLock);
    return _faceImages;
}
};


int main()
{
bool quit(false);
int c = 1;
FaceDetector faceDet;
faceDet.start();
thread input([](bool &quitFlag) { getchar(); quitFlag = true; },ref(quit)); //stop on user press Enter
input.detach();
while (!quit) {


    Mat img = faceDet.getImage();
    Mat imgc = img.clone();

    imshow("links", imgc);

    /*
    imgs = faceDet.getProcessedImage();
    Mat imgsc = imgs.clone();

    imshow("gsichter", imgsc);
    */
    waitKey(30);
    this_thread::sleep_for(chrono::milliseconds(33)); //no need to show more than 30 fps...
}
faceDet.stop();
return 0;
}

推荐答案

我为您制作了一个示例代码,供您根据需要进行修改. 如果有任何一行不解释自己,欢迎您提出...

I made an example code for you to modify for your needs. If any line is not self explanatory, feel welcome to ask...

#include <memory>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <cmath>



using namespace std;

typedef unsigned char uchar;
typedef unsigned int uint;

class FaceDetector
{

    mutex imageLock, facesLock;
    condition_variable imageAqcuired;
    bool newImageAvailable;
    vector<uchar> _img;
    vector<uchar> _imgToWorkOn;
    vector<uchar> _faceImages;
    bool quit;
    void acquireImage()
    {
        while (!quit)
        {
            unique_lock<mutex> ulock(imageLock);
            imageAqcuired.wait(ulock,[&](){return !newImageAvailable;}); //only take new image after current one was consumed
            //aqcuire image from camera into _img here
            ulock.unlock();
            newImageAvailable = true;
            imageAqcuired.notify_one(); //notify that a new image is available
        }
    }
    void processImage()
    {
        while (!quit)
        {
            unique_lock<mutex> ulock(imageLock);
            imageAqcuired.wait(ulock,[&](){return newImageAvailable;}); //wait untill a new image is available
            _imgToWorkOn = _img;
            ulock.unlock();
            newImageAvailable = false;
            imageAqcuired.notify_one(); //notify the current image can be replaced by a newer one
            unique_lock<mutex> lockFace(facesLock);
            //process _imgToWorkOn, face detect... 
            lockFace.unlock();
        }
    }

public:
    FaceDetector() : _img(100000),_imgToWorkOn(100000), _faceImages(100000), newImageAvailable(false) {}
    void start() {
        quit = false;
        thread t1(&FaceDetector::acquireImage,this);
        t1.detach();
        thread t2(&FaceDetector::processImage,this);
        t2.detach();
    }
    void stop() {
        quit = true;
    }
    vector<uchar> getImage() {
        if (quit)
            return vector<uchar>();
        lock_guard<mutex> lock(imageLock);
        return _img;
    }

    vector<uchar> getProcessedImage() {
        if (quit)
            return vector<uchar>();
        lock_guard<mutex> lock(facesLock);
        return _faceImages;
    }
};


int main()
{
    bool quit(false);
    FaceDetector faceDet;
    faceDet.start();
    thread input([](bool &quitFlag) { getchar(); quitFlag = true; },ref(quit)); //stop on user press Enter
    input.detach();
    while (!quit) {
        vector<uchar> img = faceDet.getImage();
        if (img.size()) 
        {  /*show image*/ }  
        img = faceDet.getProcessedImage();
        if (img.size()) {  /*show image*/ }
        this_thread::sleep_for(chrono::milliseconds(33)); //no need to show more than 30 fps...
    }
    faceDet.stop();
    return 0;
}

这篇关于在OpenCL-OpenCV-Realtime-Threads中正确使用互斥锁?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆