openCV中的颜色对象跟踪可以持续检测皮肤

时间:2013-06-07 13:29:55

标签: c++ c algorithm opencv image-processing

我打算做的事情如下:

修复彩色物体。使用带有camshift的直方图反投影方法在视频帧中跟踪它。我使用以下代码,它总是最终检测到皮肤。我知道我犯了一些非常简单的错误。如果有人能指出它会很有帮助。

//I have included only the integral parts of code. There are no compilation errors.

    int lowerH =80, upperH =100, lowerS =80, upperS =255, lowerV =80, upperV =255;

    CvScalar output_min =cvScalar(lowerH, lowerS, lowerV, 0); //Color Track
    CvScalar output_max =cvScalar(upperH, upperS, upperV, 0);

    CvScalar output_min2 =cvScalar(0, lowerS, lowerV, 0); //Color Track
    CvScalar output_max2 =cvScalar(180, upperS, upperV, 0);

    while(true){
        frame =cvQueryFrame(capture);

        cvCvtColor(frame, output, CV_BGR2HSV);
        cvInRangeS(output, output_min, output_max, output_mask);

        blobs =CBlobResult(output_mask, NULL, 0);
        blobs.Filter(blobs, B_EXCLUDE, CBlobGetArea(), B_LESS, 35);

        int num_blobs =blobs.GetNumBlobs();
        for(int i=0; i<num_blobs;++i){
            currentBlob = blobs.GetBlob( i );                
            sortedBlobs.push_back(currentBlob);
        }

        if(num_blobs){
            sort(sortedBlobs.begin(), sortedBlobs.end(), local::sortBlobs);
            CvRect blobRect =sortedBlobs[0].GetBoundingBox();

            initX =blobRect.x;
            initY =blobRect.y;
            initWidth =blobRect.width;
            initHeight =blobRect.height;
            initFrame =cvCloneImage(frame);
        }

            int c=cvWaitKey(40);
        if((char)c ==27)break;
    }

    CvRect selection;
    selection.x = initX;
    selection.y = initY;
    selection.width = initWidth;
    selection.height = initHeight;

    CvHistogram *hist;
    int hist_bins = 30;          
    float hist_range[] = {0, 180}; 
    float* range = hist_range;
    hist = cvCreateHist(1, &hist_bins, CV_HIST_ARRAY, &range, 1);           

    cvCvtColor(initFrame, output, CV_BGR2HSV);
    cvInRangeS(output, output_min2, output_max2, output_mask);
    cvSplit(output, hue, 0, 0, 0);

    cvSetImageROI(hue, selection);
    cvSetImageROI(output_mask, selection);

    cvCalcHist(&hue, hist, 0, output_mask);
    float max_val = 0.f;
    cvGetMinMaxHistValue(hist, 0, &max_val, 0, 0 );
    cvConvertScale(hist->bins, hist->bins,
                 max_val ? 255.0/max_val : 0, 0);

    cvResetImageROI(hue);
    cvResetImageROI(output_mask);


    CvBox2D curr_box;
    CvRect prev_rect =selection;
    CvConnectedComp components;
    bool rectFlag =false;
    CvPoint Pt =cvPoint(0,0), prevPt =cvPoint(0,0);
    int clearCounter =0;
    while(true){
        frame =cvQueryFrame(capture);
        if(!frame)break;

        cvCvtColor(frame, output, CV_BGR2HSV);
        cvInRangeS(output, output_min2, output_max2, output_mask);
        cvSplit(output, hue, 0, 0, 0);

        cvCalcBackProject(&hue, prob, hist);
        cvAnd(prob, output_mask, prob, 0);

        cvCamShift(prob, prev_rect, cvTermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 20, 1), &components, &curr_box);

        prev_rect = components.rect;
        curr_box.angle = -curr_box.angle;

        cvEllipseBox(frame, curr_box, CV_RGB(255,0,0), 3, CV_AA, 0);

        int c=cvWaitKey(40);
        if((char)c ==27)break;
    }

编辑:

检查编辑的代码部分,其中在创建直方图时,我使用0-180范围内的掩码的色调值。如果我使用80-100的缩小范围,我会在组件和curr_box中获得垃圾值。

更新: 输出图像

这是最初检测到的绿色斑点,应在整个录制过程中进行跟踪。

This is the green blob detected initially and should be tracked throughout the recording

这就是发生的事情。绿色斑点在蒙版图像中完全变黑,而是跟踪皮肤。

This is what happens. The green blob is completely blacked out in the mask image and instead the skin is tracked

1 个答案:

答案 0 :(得分:6)

首先,为所有的困惑道歉。代码中有一个非常愚蠢的错误。我将一个填充的红色矩形放在上面后克隆原始框架。

    CvPoint pt1, pt2;
    pt1.x = blobRect.x;  
    pt1.y = blobRect.y;  
    pt2.x = blobRect.x + blobRect.width;  
    pt2.y = blobRect.y + blobRect.height;

    cvRectangle( frame, pt1, pt2, cvScalar(0, 0, 255, 0), CV_FILLED, 8, 0 );

    initX =blobRect.x;
    initY =blobRect.y;
    initWidth =blobRect.width;
    initHeight =blobRect.height;
    initFrame =cvCloneImage(frame);

因此,创建的直方图始终为红色。解决方案很简单。