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

时间:2013-12-11 11:25:34

标签: 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)函数。 / p>

我是初学者,当涉及到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);
}

我做错了什么?

1 个答案:

答案 0 :(得分:1)

尝试使用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) 

功能错误。看看你的任务经理,你会发现你的程序调用只会填满你所有的记忆。