2013-06-07 17 views
10

Co zamierzam zrobić, to:śledzenie obiektów kolorowych w openCV wykrywa skórę

Naprawić kolorowy obiekt. Śledź w poprzek klatek wideo, wykorzystując histogram-backprojection z camshift. Używam następującego kodu i zawsze kończy się wykrywaniem skóry. Rozumiem, że popełniam jakiś strasznie prosty błąd. Byłoby pomocne, gdyby ktoś mógł to wskazać.

//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:

Czy sprawdzić edytowany część kodu, w którym podczas tworzenia histogramu Używam wartość barwy na masce w przedziale 0-180. Jeśli użyję zredukowanego zakresu 80-100, otrzymam wartości śmieci w komponentach i curr_box.

UPDATE: Wyjście zdjęć

Jest to zielony blob początkowo wykryta i powinny być śledzone przez cały nagrania.

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

To co się dzieje. Zielona plama jest całkowicie zaciemniona na obrazie maski, a zamiast tego skóra jest śledzona.

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

+0

Nie naprawiasz koloru, aby śledzić kolor skóry? To trochę tak wygląda. – Nallath

+0

Czy możesz podać próbki? Na przykład wideo wejściowe i wynik śledzenia. – cyriel

+0

@Nallath: Przypuszczam, że kolor skóry ma wartość H w zakresie 0-20 (popraw mnie jeśli się mylę). –

Odpowiedz

6

Przede wszystkim przepraszam za całe zamieszanie. W kodzie jest bardzo głupi błąd. Klonuję oryginalną ramkę po umieszczeniu na niej wypełnionego czerwonego prostokąta.

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

W związku z tym utworzony histogram jest zawsze dla koloru czerwonego. Rozwiązanie jest trywialne.