Lepszy algorytm dla filtra krawędzi w programowaniu wideo

Nadal pracuję nadostatni program i chociaż w końcu dowiedziałem się, jak rozwiązać problem (jak filtrować największy kontur), mam teraz nowe pytanie, a raczej problem.

Jak widać, używam algorytmu Canny'ego do przeszukiwania krawędzi wideo. Ale obiekt, którego użyję do wykrywania, nie ma określonego koloru, więc gdy kolor obiektu jest mniej więcej taki sam jak kolor otoczenia (na przykład, jeśli obiekt jest srebrny, a tło białe), krawędź obiektu zniknie i nie będę mógł uzyskać kontur obiektu.

Na razie przetestuję każdy algorytm filtrowania krawędzi dostępny w OpenCV, ale aby skrócić moją pracę, potrzebuję twojej pomocy, aby polecićnajlepszy (lub przynajmniej lepszy) algorytm niż canny. Teraz przetestowałem Sobela, ale wynik nie jest lepszy niż Canny'ego. Jeśli to możliwe, połącz mnie z dobrym przykładem.

Kod:

int main( int argc, char** argv )
{
CvCapture *cam;
CvMoments moments;
CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* contours = NULL;
CvSeq* contours2 = NULL;
CvPoint2D32f center;
int i;

cam=cvCaptureFromCAM(0);
if(cam==NULL){
    fprintf(stderr,"Cannot find any camera. \n");
    return -1;
}
while(1){
    IplImage *img=cvQueryFrame(cam);
    if(img==NULL){return -1;}
    IplImage *src_gray= cvCreateImage( cvSize(img->width,img->height), 8, 1);
    cvCvtColor( img, src_gray, CV_BGR2GRAY );
    cvSmooth( src_gray,  src_gray, CV_GAUSSIAN, 5, 11);
    cvCanny(src_gray, src_gray, 70, 200, 3);

    cvFindContours( src_gray, storage, &contours, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, cvPoint(0,0));
    if(contours==NULL){ contours=contours2;}
    contours2=contours;
    CvSeq* current_contour = contours;
    double largestArea = 0;
    CvSeq* largest_contour = NULL;
    while (current_contour != NULL){
        double area = fabs(cvContourArea(current_contour,CV_WHOLE_SEQ, false));       
        if(area > largestArea){
            largestArea = area;
            largest_contour = current_contour;
        }
        current_contour = current_contour->h_next;
    }

    cvMoments(largest_contour, &moments, 1);

    double m_00 = cvGetSpatialMoment( &moments, 0, 0 );
    double m_10 = cvGetSpatialMoment( &moments, 1, 0 );
    double m_01 = cvGetSpatialMoment( &moments, 0, 1 );
    float gravityX = (m_10 / m_00)-150;
    float gravityY = (m_01 / m_00)-150;
    if(gravityY>=0&&gravityX>=0&&m_00>=3000){
        printf("center point=(%.f, %.f), Area = %.f \n",gravityX,gravityY,m_00); }


    if(m_00>=3000){
        CvScalar color = CV_RGB(250,0,0);
        cvDrawContours(img,largest_contour,color,color,-1,-1, 8, cvPoint(0,0));
    }

    cvShowImage( "Input", img );
    cvShowImage( "Contours", src_gray );
    cvClearMemStorage(storage);
    if(cvWaitKey(33)>=0) break;
}
cvDestroyWindow("Contours");
cvDestroyWindow("Source");
cvReleaseCapture(&cam);
}

... i wreszcie długo oczekiwane przykładowe zdjęcia:

Po pierwsze, dobry (mój czarny portfel)

Po drugie, niepowodzenie (pomarańczowe pole)

I wreszcie kolejna porażka (białe pudełko)

P.S., Niektóre notatki:

Obiekt nie ma określonego kształtu, koloru ani rozmiaru, więc IMO najlepiej jest znaleźć krawędź obiektu zamiast filtrować go według kolorów.Przytrzymam przedmiot, więc może mój palec może spowodować zmianę lub zniknięcie krawędzi obiektu.Pracuję nad programem do przetwarzania wideo, więc im krótszy czas przetwarzania i im mniejsza moc obliczeniowa, tym lepiej.Mój program odfiltruje największy kontur i wypełni go kolorem czerwonym (patrz pierwsze zdjęcie).

Z góry dziękuję. Twoje zdrowie

questionAnswers(1)

yourAnswerToTheQuestion