2 votes

Meilleur algorithme pour le filtre de bordure dans la programmation vidéo

Je travaille toujours sur le dernier programme et bien que j'aie enfin trouvé comment résoudre le problème (sur comment filtrer le plus grand contour), j'ai maintenant une nouvelle question, ou plutôt un problème.

Comme vous pouvez le voir, j'utilise l'algorithme de Canny pour rechercher les bords dans la vidéo. Mais l'objet que j'utiliserai pour la détection n'a pas de couleur particulière, donc lorsque la couleur de l'objet est à peu près la même que celle de l'arrière-plan (par exemple si l'objet est argenté et l'arrière-plan est blanc), le bord de l'objet disparaîtra et je ne pourrai pas obtenir le contour de l'objet.

Pour le moment, je vais tester chaque algorithme de filtrage de bord disponible dans OpenCV mais pour abréger mon travail, j'ai besoin de votre aide pour recommander le meilleur (ou du moins meilleur) algorithme que Canny. J'ai déjà testé Sobel mais le résultat n'est pas meilleur que celui de Canny. Si possible, veuillez me fournir quelques bons exemples à titre de référence.

Le code:

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,"Impossible de trouver de caméra. \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("point central=(%.f, %.f), Surface = %.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( "Entrée", img );
    cvShowImage( "Contours", src_gray );
    cvClearMemStorage(storage);
    if(cvWaitKey(33)>=0) break;
}
cvDestroyWindow("Contours");
cvDestroyWindow("Source");
cvReleaseCapture(&cam);
}

...et enfin, les images d'exemple tant attendues:

Premièrement, celle de qualité (mon portefeuille noir) La bonne

Deuxièmement, l'échec (une boîte orange) Échec

Et enfin, un autre échec (une boîte blanche) Échec blanc

P.S., Quelques notes:

  • L'objet n'a pas de forme, couleur ou taille particulière donc à mon avis, le mieux est de trouver le bord de l'objet plutôt que de le filtrer par couleur.
  • Je tiendrai l'objet donc peut-être que mon doigt peut provoquer un changement ou une disparition du bord de l'objet.
  • Je travaille sur un programme de traitement vidéo donc plus le temps de traitement est court et moins la puissance de traitement est nécessaire, mieux c'est.
  • Mon programme filtrera le plus grand contour et le remplira de couleur rouge (voir la première image).

Merci d'avance. Cordialement

1voto

misha Points 10541

Votre problème n'est pas l'algorithme de détection des bords. Votre problème est que vous codez en dur les paramètres de l'algorithme et vous vous attendez à ce qu'il fonctionne magiquement pour toutes les images que vous lui lancez. De plus, lisser l'image avant d'utiliser cvCanny est inutile, car l'opérateur de Canny effectue déjà le lissage pour vous.

Puisque maintenant il est un peu plus clair ce que vous voulez accomplir, je peux vous faire une suggestion : travaillez avec la vidéo au lieu de regarder chaque image individuellement. Si la caméra est fixe et que la main avec l'objet se déplace, alors détecter la forme est trivial grâce à la soustraction de l'arrière-plan. Si la caméra n'est pas fixe, vous pouvez quand même détecter la main (lien PDF) et travailler à partir de là. Utilisez également toute autre connaissance spécifique à l'application que vous pourriez posséder (par exemple, l'objet sera au milieu de l'écran, la main sera en dessous de l'objet).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X