Partage
  • Partager sur Facebook
  • Partager sur Twitter

Filtre de détection de contour de Sobel

    20 novembre 2010 à 17:25:50

    Bonjour à tous, je suis amené à appliquer manuellement le filtre sobel sur une image en openCV mais quelque chose m'échappe ..
    voici le bout de code intéressant :

    //Initialisation 
    
    	//Image de base et niveau de gris
    	IplImage* img = cvLoadImage("1.jpg");
    	IplImage* imgnvg = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
    
    	//Résultat du filtre Sobel
    	IplImage* sobelx = cvCloneImage(imgnvg);
    	IplImage* sobely = cvCloneImage(imgnvg);
    	IplImage* sobel = cvCloneImage(imgnvg);
    
    	//Masque de convolution
    	CvMat* Gx = cvCreateMat(3, 3, CV_32FC1);
    	CvMat* Gy = cvCreateMat(3, 3, CV_32FC1);
    	
    	cvSet(Gx, cvScalar (0));
    
    	cvmSet(Gx,0,0,1);
    	cvmSet(Gx,0,2,-1);
    	cvmSet(Gx,1,0,2);		// | 1  0 -1 |
    	cvmSet(Gx,1,2,-2);		// | 2  0 -2 |
    	cvmSet(Gx,2,0,1);		// | 1  0 -1 |
    	cvmSet(Gx,2,2,-1);
    
    	cvSet(Gy, cvScalar (0));
    
    	cvmSet(Gy,0,0,1);
    	cvmSet(Gy,0,1,2);
    	cvmSet(Gy,0,2,1);		// | 1  2  1 |
    	cvmSet(Gy,2,0,-1);		// | 0  0  0 |
    	cvmSet(Gy,2,1,-2);		// |-1 -2 -1 |
    	cvmSet(Gy,2,2,-1);
    
    	// Conversion en niveaux de gris
    	int flip = 0;
        if( img->origin != IPL_ORIGIN_TL )
            flip = CV_CVTIMG_FLIP;
    
        cvConvertImage(img, imgnvg, flip);
    
    
    	//CONVOLUTION
    	cvFilter2D (imgnvg, sobelx, Gx);
    	cvFilter2D (imgnvg, sobely, Gy);
    


    Théoriquement le filtre de sobel s'applique comme ceci : (A étant l'image source)

    Image utilisateur

    Image utilisateur

    Donc pour le moment j'ai les 2 matrices, je les ai appliquées à mon image de départ mais je ne comprend pas comment faire la racine carrée de 2 images au carré :)

    Merci d'avance.
    • Partager sur Facebook
    • Partager sur Twitter
      20 novembre 2010 à 23:33:47

      salut je di sa comme sa mais le detecteur de contour est deja coder dans OpenCV il me semble...
      regarde dans les exemples
      • Partager sur Facebook
      • Partager sur Twitter
      http://jacen92.free.fr
        21 novembre 2010 à 9:41:37

        oui oui je sais il existe la fonction cvSobel qui applique le filtre à une image mais comme je l'ai précisé plus haut je dois faire le filtre manuellement.
        • Partager sur Facebook
        • Partager sur Twitter
          21 novembre 2010 à 11:14:10

          A ce moment, regardes les sources d'OpenCV. ;)
          • Partager sur Facebook
          • Partager sur Twitter
            21 novembre 2010 à 11:28:16

            En fait, une fois que tu as tes deux images, il faut prendre le module des images pixel à pixel.

            <math>\(\forall (i,j) \in G, G(i,j) = \sqrt{G_x(i,j)^2 + G_y(i,j)^2}\)</math>

            Ensuite, n'oublie pas de normaliser à 255 si tu veux pouvoir afficher ton image (je ne sais pas si openCV permet de le faire automatiquement)
            • Partager sur Facebook
            • Partager sur Twitter
              22 novembre 2010 à 17:07:11

              Bonjour et merci pour vos réponses voici ce que j'ai essayer de faire :

              for(int ligne=0; ligne<sobelx->width; ligne++)
              	{
              		for(int colonne=0; colonne<sobelx->height; colonne++)
              		{
              			d = 0;
              			d2 = 0;
              
              			for(int x=0; x<sobelx->width; x++)  
              			{
              				scalaire = cvGet2D(sobelx, ligne, x);
              				a = scalaire.val[0];
              				scalaire2 = cvGet2D(sobelx, x, colonne); 
              				b = scalaire2.val[0];
              				c = a * b;
              				d = d+c;
              
              				scalaire3 = cvGet2D(sobely, ligne, x);
              				a2 = scalaire3.val[0];
              				scalaire4 = cvGet2D(sobely, x, colonne); 
              				b2 = scalaire4.val[0];
              				c2 = a2 * b2;
              				d2 = d2+c2;
              			}
              
              			//Racine carrée 
              			int somme = d + d2;
              			double dd = somme;
              			//printf ("D vaut : %lf \n", dd);
              			double result;
              			result = sqrt (dd);
              			//printf ("sqrt(%lf) = %lf\n", dd, result );
              			int final = result;
              			//printf ("Final vaut : %d \n", final);
              			scalaire5.val[0] = final;
              			cvSet2D(sobel, colonne, ligne, scalaire5);
              		}
              	}
              


              Donc voila quand je lance ce code j'ai une image bizarre qui n'a rien avoir avec mon image de départ.
              Toutes mes images sont en : IPL_DEPTH_8U au cas ou le problème pourrait venir de la.
              Et avec ce code j'ai essayé d'appliquer la fonction "normaliser" qu'il y a dans le tuto openCV sur ce site et
              j'obtiens une image toute noire ...
              • Partager sur Facebook
              • Partager sur Twitter
                22 novembre 2010 à 23:05:55

                Oula !! c'est quoi ce code ?? ça ne convolu rien avec rien !!

                1. Tu dois balayer chaque pixel de l'image (comme tu le fait avec ta double boucle for)
                2. Tu dois (pour chaque pixel) calculer la valeur du pixel après avoir appliqué un filtre de sobel en X et en Y (tu as donc 2 valeurs) (ici, tu as encore un double boucle for qui récupère les voisin du pixel en cours de traitement afin d'appliquer le filtre de convolution)
                3. Tu dois calculer la racine carré de la somme des carré de ces 2 pixels calculé. La nouvelle valeur, tu la stockes dans une nouvelle image.

                Remarque : Attention aux pixels de bords (tu ne pourras pas calculer le gradient de ces pixels)
                • Partager sur Facebook
                • Partager sur Twitter
                  23 avril 2013 à 19:37:01

                  essai ca :

                  // Détection des contours en utilisant, les opérateurs de Sobel

                  #include<stdio.h>
                  #include<stdlib.h>
                  #include<cv.h>
                  #include<highgui.h>

                  #define SEUIL 35
                  #define NOMIMAGE  "coins.png"

                  int main (int argc, char *argv[])
                  {
                      float xFilter[9]={-1,-2,-1,
                                         0, 0, 0,
                                         1, 2, 1 };
                      float yFilter[9]={-1, 0, 1,
                                        -2, 0, 2,
                                        -1, 0, 1 };
                   
                      IplImage* img=cvLoadImage(NOMIMAGE,CV_LOAD_IMAGE_GRAYSCALE);
                      if(!img){
                          printf("\n Ouverture impossible (%s)",NOMIMAGE);
                          exit(0);
                      }   
                     
                      IplImage* cont = cvCreateImage( cvGetSize(img), 8, 1 );
                      IplImage* grayL = cvCreateImage( cvGetSize(img), 8, 1 );
                      IplImage* tmp1=cvCreateImage(cvGetSize(grayL),IPL_DEPTH_32F,1);
                      IplImage* tmp2=cvCreateImage(cvGetSize(grayL),IPL_DEPTH_32F,1);

                      IplImage* res32=cvCreateImage(cvGetSize(grayL),IPL_DEPTH_32F,1);
                      IplImage* res8 =cvCreateImage(cvGetSize(grayL),IPL_DEPTH_8U,1);
                   
                      CvMat k1 = cvMat(3,3,CV_32FC1,xFilter);
                      CvMat k2 = cvMat(3,3,CV_32FC1,yFilter);
                       //créer l'image contour   
                    
                      // lisser, sinon beaucoup de faux cercles seront détectés
                      cvSmooth(img,grayL, CV_GAUSSIAN,5,5);
                     
                      // Préparer la matrice image à filter
                       cvConvert(grayL,tmp1);
                      cvConvert(grayL,tmp2);

                      // Convolution par les deux filtres
                      cvFilter2D( tmp1 ,tmp1, &k1);
                      cvFilter2D( tmp2 ,tmp2, &k2);
                   
                      // Calcul de l'image gradient (G(x,y)=(Gx(x,y)^2 + Gy(x,y)^2)^(1/2)
                      cvPow(tmp1,tmp1,2.0);
                      cvPow(tmp2,tmp2,2.0);
                      cvAdd(tmp1,tmp2,res32,NULL);
                      cvPow(res32,res32,0.5);
                     
                      // Normalisation du résultat pour avoir un résultat dans [0, 255]
                      double InputMin, InputMax;
                      cvMinMaxLoc( res32, &InputMin, &InputMax );
                      cvConvertScale ( res32, res32, 255.0 / (InputMax -InputMin), -InputMin);
                        
                      // Conversion et binarisation
                      cvConvert(res32,res8);
                      cvThreshold(res8,res8,SEUIL,255,CV_THRESH_BINARY);
                   
                      // Affichage des résultats
                      cvNamedWindow("Image originale", CV_WINDOW_AUTOSIZE);
                      cvMoveWindow("Image originale", 100, 100);
                      cvShowImage("Image originale",img);
                   
                      cvNamedWindow("Image Contour", CV_WINDOW_AUTOSIZE);
                      cvMoveWindow("Image Contour", 150, 150);
                      cvShowImage("Image Contour",res8);
                        cvNamedWindow( "Après lissage", 1 );
                      cvShowImage( "Après lissage", grayL );
                   
                      cvWaitKey(0);
                       cvReleaseImage(&img);
                      cvReleaseImage(&res8);
                     
                      return 0;
                  }

                  • Partager sur Facebook
                  • Partager sur Twitter
                    23 avril 2013 à 19:38:53

                    svvvvvvvvvvvp quelqu'un c'est comment appliquer le filtre de roberts en utilisant des filtres gaussiens pour la detection des conteurs d'une image??
                    • Partager sur Facebook
                    • Partager sur Twitter
                      13 avril 2016 à 22:38:52

                      bonjour a tous, je veu un programme sur la detction de contour avec c++ qui va marché qui pourra m'aidée svp :)

                      • Partager sur Facebook
                      • Partager sur Twitter

                      Filtre de détection de contour de Sobel

                      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                      × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                      • Editeur
                      • Markdown