OpenCV中的颜色物体跟踪一直在检测肤色。

10

我的打算如下:

固定一个有颜色的物体,使用直方图反向投影法和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中获得垃圾值。

更新:

输出图片

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

这是最初检测到的绿色斑点,应该在整个记录过程中跟踪

发生了什么。在掩码图像中,绿色斑点被完全变黑,而皮肤被跟踪。

发生了什么。在掩码图像中,绿色斑点被完全变黑,而皮肤被跟踪


你不是要把颜色固定在皮肤颜色上吗?看起来有点像这样。 - Nallath
我刚刚检查了一下,皮肤的 H 值确实在 10-30 的范围内。 - Nallath
请检查代码的编辑部分,其中在创建直方图时,我使用了掩码的色调值,范围为0-180。如果我使用缩小的范围80-100,则组件和curr_box中会得到垃圾值。 - Hrishikesh_Pardeshi
是的,使用Mac进行科学编程是一个巨大的错误。 - Tyler Durden
@TylerDurden 不太明白你的意思。我没有使用 Macintosh 机器。你能否澄清一下你的意思? - Hrishikesh_Pardeshi
显示剩余3条评论
1个回答

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);

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接