Partage

Filtre de détection de contour de Sobel

Le 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.
Publicité
Le 20 novembre 2010 à 17:25:50
Le 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
http://jacen92.free.fr
Le 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.
Le 21 novembre 2010 à 11:14:10

A ce moment, regardes les sources d'OpenCV. ;)
Le 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.

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

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)
Le 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 ...
Le 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)
Le 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;
}

Le 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??

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é.
  • Editeur
  • Markdown