Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

color object tracking in openCV keeps detecting the skin

What I intend to do is as follows:

Fix a colored object. Track it across video frames using histogram-backprojection approach with camshift. I use the following code and it always ends up detecting the skin. I understand I am making some terribly simple mistake. It would be helpful if someone could point it out.

//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;
    }

EDIT:

Do check the edited part of code wherein while creating the histogram I am using hue value for the mask in the range 0-180. If I use the reduced range 80-100, I get garbage values in components and curr_box.

UPDATE : Output images

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

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.

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

like image 921
Hrishikesh_Pardeshi Avatar asked Jun 07 '13 13:06

Hrishikesh_Pardeshi


1 Answers

First of all, apologies for all the confusion. There is a very silly bug in the code. I am cloning the original frame after placing a filled red rectangle onto it.

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

Hence, the histogram that is created is always for the red color. The solution is trivial.

like image 155
Hrishikesh_Pardeshi Avatar answered Oct 11 '22 13:10

Hrishikesh_Pardeshi