C++/OpenCV 多线程简单同步

标签 c++ c multithreading opencv

这次我遇到了以下问题。我想通过将每个作为单独的线程启动来加速皮肤/背景分割。

这两个程序,不写入相同的变量,不从相同的变量读取。唯一重要的是同步主程序线程,等待两个程序(皮肤和背景)完成它们的工作,然后开始处理结果。

我所做的是:

在我的主类标题中:

HANDLE fgbg_codebookThread;
HANDLE skinsegThread;

然后在我的主循环函数中:

fgbg_codebookThread =( HANDLE ) _beginthread( fgbg_codebookThreadProc, 0, (void *)this );
skinsegThread =( HANDLE ) _beginthread( skinsegThreadProc, 0, (void *)this );

std::vector < HANDLE > threads;
threads.push_back(fgbg_codebookThread);
threads.push_back(skinsegThread);

if( threads.size() > 0 )
    WaitForMultipleObjects( threads.size(), & threads[ 0 ], TRUE, INFINITE );
cv::bitwise_and(fgbg_codebookResult,skinsegResult,mask);

我的过程函数看起来像:

static void __cdecl fgbg_codebookThreadProc( void * Args )
{
    mainApp* app = static_cast<mainApp*>(Args);

    app->fgbg_codebookProc();
    _endthread();
};

static void __cdecl skinsegThreadProc( void * Args )
{
    mainApp* app = static_cast<mainApp*>(Args);

    app->skinsegProc();
    _endthread();
};

在我看来,只要两个过程不以任何方式共享变量,它就可以正常工作。

但是:在大多数情况下,以下代码会引导我到达断点(在随机运行一段时间后),该断点指向 malloc.c __forceinline void * __cdecl _heap_alloc (size_t size) 函数或free.c void __cdecl _free_base (void * pBlock) 函数。

我是 C++ 线程方面的初学者,我以前从未使用过它,所以我不知道发生了什么。

这是我的线程程序的主体(可以肯定):

void fgbg_codebookProc()
{       
fgbg_codebook.process(fgbg_codebookFrame, &fgbg_codebookResult,frameNumber);        
}

void skinsegProc()
{                 skinseg.process(skinsegFrame,&skinsegResult,skinseg.lambda,skinseg.vThreshold);   
}




  void FGBG_CODEBOOK::process(cv::Mat input,cv::Mat *output, int nframes)
{
    IplImage* rawImage=cvCloneImage(&(IplImage)input);

    yuvImage = cvCloneImage(rawImage);
    ImaskCodeBook = cvCreateImage( cvGetSize(rawImage), IPL_DEPTH_8U, 1 );
    cvSet(ImaskCodeBook,cvScalar(255));
    cvCvtColor(yuvImage, yuvImage, CV_RGB2YCrCb );//YUV For codebook method

    model->modMin[0] = YUVmin[0];
    model->modMin[1] = YUVmin[1];
    model->modMin[2] = YUVmin[2];
    model->modMax[0] = YUVmax[0];
    model->modMax[1] = YUVmax[0];
    model->modMax[2] = YUVmax[0];

    //Basic learning of backgroundraw->width/2-100/2, raw->height/1.5-100/2),cvPoint(raw->width/2+100,raw->height/1.5+100)
    if( nframes-1 < nframesToLearnBG  )
        cvBGCodeBookUpdate( model, yuvImage);

    //Clean when learned
    if( nframes-1 == nframesToLearnBG  )
    {
        cvBGCodeBookClearStale( model, model->t/2 );
        calibration = false;
    }
    //Start finding foreground after learning
    if( nframes-1 >= nframesToLearnBG  )
    {
        // Find foreground by codebook method
        cvBGCodeBookDiff( model, yuvImage, ImaskCodeBook );

        // Update periodically
        /*if ((nframes-1) % 150 == 0)
        {
            cvBGCodeBookUpdate(model,yuvImage);
            //std::cout <<"update\n";
        }
        if ((nframes-1) % 300 == 0)
        {
            cvBGCodeBookClearStale(model,model->t/2);
            //std::cout <<"clear\n";
        }*/
    }

    cv::Mat(ImaskCodeBook).copyTo(*output);
    cvReleaseImage(&rawImage);
    cvReleaseImage(&yuvImage);
    cvReleaseImage(&ImaskCodeBook);
}


    void SKINSEG::process(cv::Mat src, cv::Mat *dst, double lambda, unsigned int vThreshold)
{

    skinsegResult = cv::Mat(480,640, CV_8UC1, cvScalar(0.));
    cv::cvtColor(src,frameHSV,CV_RGB2HSV);


    CvMat* Cs;
    CvMat* CsInv;
    CvMat* ms;


    Cs = cvCreateMat(2, 2, CV_32FC1);
    cvInitMatHeader(Cs, 2, 2, CV_32FC1, covMatrix);
    CsInv = cvCreateMat(2, 2, CV_32FC1);
    cvInvert(Cs, CsInv);
    ms = cvCreateMat(1, 2, CV_32FC1);
    cvInitMatHeader(ms, 1, 2, CV_32FC1, valAvg);

    CvMat* X = cvCreateMat(1, 2, CV_32FC1);
    CvMat* Xms = cvCreateMat(1, 2, CV_32FC1);
    CvMat* XmsT = cvCreateMat(2, 1, CV_32FC1);
    CvMat* XmsCsInv = cvCreateMat(1, 2, CV_32FC1);
    CvMat* XmsCsInvXmsT = cvCreateMat(1, 1, CV_32FC1);

    uchar* data = (uchar *)frameHSV.data; 
    uchar* dataMask = (uchar *)skinsegResult.data; 

    double temp[2];
    for (int j = 0; j < frameHSV.cols; j++) 
        for (int i = 0; i < frameHSV.rows; i++)
        {
            cvmSet( Xms,0,0,(double)data[i*frameHSV.step+j*frameHSV.channels()+0]- cvmGet(ms,0,0) );
            cvmSet( Xms,0,1,(double)data[i*frameHSV.step+j*frameHSV.channels()+1] - cvmGet(ms,0,1) );

            temp[0] = cvmGet(Xms,0,0);
            temp[1] = cvmGet(Xms,0,1);

            cvmSet(XmsT,0,0,cvmGet(Xms,0,0));
            cvmSet(XmsT,1,0,cvmGet(Xms,0,1));

            cvmSet(XmsCsInv,0,0,(cvmGet(Xms,0,0) * cvmGet(CsInv,0,0)) + (cvmGet(Xms,0,1) * cvmGet(CsInv,1,0)));
            cvmSet(XmsCsInv,0,1,(cvmGet(Xms,0,0) * cvmGet(CsInv,0,1)) + (cvmGet(Xms,0,1) * cvmGet(CsInv,1,1)));

            cvmSet(XmsCsInvXmsT,0,0,(cvmGet(XmsCsInv,0,0) * cvmGet(XmsT,0,0)) + (cvmGet(XmsCsInv,0,1) * cvmGet(XmsT,1,0)));


            double lam = cvmGet(XmsCsInvXmsT, 0, 0);
            dataMask[i*skinsegResult.step+j*skinsegResult.channels()] = (((double)data[i*frameHSV.step+j*frameHSV.channels()] >= vThreshold) && (lam < lambda)) ? 255 : 0;

    }
    skinsegResult.copyTo(*dst);

    // zwalniamy macierze
    cvReleaseMat(&XmsCsInvXmsT);
    cvReleaseMat(&XmsCsInv);
    cvReleaseMat(&XmsT);
    cvReleaseMat(&Xms);
    cvReleaseMat(&X);
    cvReleaseMat(&ms);
    cvReleaseMat(&CsInv);
    cvReleaseMat(&Cs);
}

我做错了什么?

最佳答案

尝试使用 createthread 或 beginthreadex 而不是 beginthread。看这里:

http://social.msdn.microsoft.com/Forums/vstudio/en-US/c727ae29-5a7a-42b6-ad0b-f6b21c1180b2/createthread-vs-beginthreadex?forum=vclanguage

或在这里:

Windows threading: _beginthread vs _beginthreadex vs CreateThread C++

我在您的代码中看到的另一件事。您将 cvInitMatHeader 与非空对象一起使用。这看起来我错了。看起来你的内存管理

void SKINSEG::process(cv::Mat src, cv::Mat *dst, double lambda, unsigned int vThreshold) 

函数错误。看看你的任务管理器,你会发现你的程序调用将填满你的所有内存。

关于C++/OpenCV 多线程简单同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20517836/

相关文章:

c++ - GDI+抖动问题

c++ - 仅显示具有正确扩展名的文件

c++ - 函数运算符的 undefined reference >>

c++ - 在没有图像文件本身作为源的情况下在 qt 窗口中有一个图像

c - 将列表转换为所需数组的最小步骤算法。 (仅使用 InsertAt 和 DeleteAt)

c - 为什么将具有不同参数类型的函数存储到具有 void* 参数 UB 的函数指针?

c - 如何在C中用多个字符替换字符串char指针中的字符?

java - 有条件等待

c - 如何在线程迭代次数不相等的 while 循环上使用 omp 屏障

c++ - 多线程应用程序在内存使用率高时崩溃并出现错误 R6016 或 0xC0000005