IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

OpenCV Discussion :

Filtre convolutionnel sur une image en niveaux de gris


Sujet :

OpenCV

  1. #21
    Membre confirmé
    Profil pro
    Developer
    Inscrit en
    Juin 2004
    Messages
    194
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Developer

    Informations forums :
    Inscription : Juin 2004
    Messages : 194
    Par défaut
    Ca doit pas être quelquechose d'impossible tout de même

  2. #22
    Membre chevronné
    Inscrit en
    Mars 2010
    Messages
    439
    Détails du profil
    Informations forums :
    Inscription : Mars 2010
    Messages : 439
    Par défaut
    Citation Envoyé par Aliveli Voir le message
    Ca doit pas être quelquechose d'impossible tout de même
    peut être que si ^^ non c'est tout à fait faisable, j'ai pas le temps d'analyser ton algo pour ma part mais si tu respectes bien la convolution (la formule mathématique) et tes carrés de pixels je vois pas pourquoi ca ne fonctionnerais pas.

  3. #23
    Membre expérimenté
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2009
    Messages
    141
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2009
    Messages : 141
    Par défaut
    Je crois que je vois d'ou viens l'erreur. Essaye de faire ce que tu fais en remettant l'initialisation des boucles a 0 et allant a nl-1 et nc-1. Ensuite dans tes boucles traite les effets de bord parceque sinon tu a des valeurs aberentes qui se baladent et qui se repercutent partout sur l'image. Dis-moi si tu comprends pas ce que je veux dire parceque je sais pas si je suis tres clair.

  4. #24
    Membre confirmé
    Profil pro
    Developer
    Inscrit en
    Juin 2004
    Messages
    194
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Developer

    Informations forums :
    Inscription : Juin 2004
    Messages : 194
    Par défaut
    Merci glen mais en essayant avec les boucles intialisés tel que tu demandes le programme plante lorsque la matrice kernel fait le -1 pour les pixels du bord. Ce qui me parait normal.
    J'avais ceci comme boucles:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
        for (int i=0; i<nl-1; i++)
    	{
    		for (int j=0; j<nc-1; j++ ) 
    		{
    je sais pas si je t'ai bien compris ?

    Deplus vous l'aurai remarqué je suis passé en grayscale, c plus facile avce une image grise qu'en couleur pour commencer.


    Le 1er code ci-dessous semble être proche du résultat avec Opencv mais c'est pas encore ça ( voir images ).

    //CODE MANUEL
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
     
    #include <stdio.h>
    #include <cv.h>
    #include <cvaux.h>
    #include <highgui.h>
     
    #define edge_w 3
    #define edge_h 3    
     
    // int -> unsigned char => OK
    // unsigned char -> float => OK
    float kernel[edge_w][edge_h]={{-1,-1,-1},{-1,9,-1},{-1,-1,-1}}; //filtre
     
    int round(float a) {
    	return int(a + 0.5);
    	}
     
    int main()
    {
    	IplImage* test=0;
    	CvCapture* capture = 0;
    	IplImage* gaussian=0;
    	cvNamedWindow( "Image normal loaded", 1 );
    	cvNamedWindow( "gaussian loaded", 1 );
     
        //IplImage* img = cvLoadImage("baby-child.jpg",CV_LOAD_IMAGE_COLOR);
    	IplImage* img = cvLoadImage("boat.jpg",CV_LOAD_IMAGE_GRAYSCALE); 
     
        int nl= img->height; // number of lines
        int nc= img->width * img->nChannels; // total number of element per line
        int step= img->widthStep/sizeof(uchar); // effective width
     
    	IplImage* gs = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U  ,1);
     
    	// get the pointer to the image buffer
        unsigned char *data= reinterpret_cast<unsigned char *>(img->imageData);
    	unsigned char *datags= reinterpret_cast<unsigned char *>(gs->imageData);
     
    	cvShowImage( "Image normal loaded", img );
    	cvWaitKey(2);
    	Sleep(3000);
     
    // MANUEL
        for (int i=1; i<nl-2; i++)
    	{
    		for (int j=1; j<nc-2; j++ ) //for (int j=0; j<nc-1; j += image->nChannels) 
    		{
    			double accumulation = 0;
    			double weightsum = 0; 
    			int sum = 0;
     
    			bool bord = false;
     
    			//int pos = ((i*nc) +j ) * img->nChannels;
    			int pos = i*step+j;
     
    			for(int ii=-1;ii<=1;ii++)
    			{
    				for(int jj=-1;jj<=1;jj++)
    				{   
    				int posf=  (i+ii)*step+j+jj;
     
    					int k =  data[posf];
    					accumulation += k * (kernel[1+ii][1+jj]);
    					weightsum += kernel[1+ii][1+jj];
     
    					}//end loop i
     
    					if (accumulation < 0)
    						//datags[pos] = round(accumulation/weightsum)*-1;
    						datags[pos] =((round(accumulation/weightsum)*-1)>255)?255:round(accumulation/weightsum)*-1; 
    					//	datags[pos] =(((accumulation)*-1)>255)?255:(accumulation)*-1; 
    					else
    						//datags[pos] = round(accumulation/weightsum);
    						datags[pos] =(round(accumulation/weightsum)>255)?255:round(accumulation/weightsum);
    						//datags[pos] = (accumulation>255)?255:accumulation;
    			}//end loop j
     
    		}
     
    	}
     
    	cvShowImage( "gaussian loaded", gs );
    	cvWaitKey(15000);
     
    	Sleep(20);
    	cvReleaseImage(&img);
    	cvReleaseImage(&gs);
     
    	return 0;
    }

    Et voici le code OPENCV

    //CODE OPENCV
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
     
    #include <stdio.h>
    #include <cv.h>
    #include <cvaux.h>
    #include <highgui.h>
     
    #define edge_w 3
    #define edge_h 3    
     
    // int -> unsigned char => OK
    // unsigned char -> float => OK
    float kernel[edge_w][edge_h]={{-1,-1,-1},{-1,9,-1},{-1,-1,-1}}; //filtre
     
    int round(float a) {
    	return int(a + 0.5);
    	}
     
    int main()
    {
    	IplImage* test=0;
    	CvCapture* capture = 0;
    	IplImage* gaussian=0;
    	cvNamedWindow( "Image normal loaded", 1 );
    	cvNamedWindow( "gaussian loaded", 1 );
     
        //IplImage* img = cvLoadImage("baby-child.jpg",CV_LOAD_IMAGE_COLOR);
    	IplImage* img = cvLoadImage("boat.jpg",CV_LOAD_IMAGE_GRAYSCALE); 
     
        int nl= img->height; // number of lines
        int nc= img->width * img->nChannels; // total number of element per line
        int step= img->widthStep/sizeof(uchar); // effective width
     
    	IplImage* gs = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U  ,1);
     
    	// get the pointer to the image buffer
        unsigned char *data= reinterpret_cast<unsigned char *>(img->imageData);
    	unsigned char *datags= reinterpret_cast<unsigned char *>(gs->imageData);
     
    	cvShowImage( "Image normal loaded", img );
    	cvWaitKey(2);
    	Sleep(3000);
     
     
    // AVEC OPENCV
    	CvMat* kernelmat = cvCreateMat( 3, 3, CV_32FC1);
    	cvmSet( kernelmat, 0,0, -1 ); 
    	cvmSet( kernelmat, 0,1, -1 );
    	cvmSet( kernelmat, 0,2, -1 );
    	cvmSet( kernelmat, 1,0, -1 );
    	cvmSet( kernelmat, 1,1,  9 );
    	cvmSet( kernelmat, 1,2, -1 ); 
    	cvmSet( kernelmat, 2,0, -1 );
    	cvmSet( kernelmat, 2,1, -1 );
    	cvmSet( kernelmat, 2,2, -1 );
    	//cvFilter2D( imggray, gsgray, kernelmat);
    	cvFilter2D( img, gs, kernelmat);
     
     
    	cvShowImage( "gaussian loaded", gs );
    	cvWaitKey(15000);
     
    	Sleep(20);
    	cvReleaseImage(&img);
    	cvReleaseImage(&gs);
     
    	return 0;
    }
    La capture pour les 2 code est en annexe il semble que le résultat gaussien avec opencv semble plus correct que celui codé manuel.

    Je ne vois pas ce qui pourrait faussé le résultat ?

    Merci
    Images attachées Images attachées   

  5. #25
    Membre chevronné
    Inscrit en
    Mars 2010
    Messages
    439
    Détails du profil
    Informations forums :
    Inscription : Mars 2010
    Messages : 439
    Par défaut
    je serais tenter de dire une approximation conversion float/int ou un truc du genre (jolie travail au passage le résultat est loin d'être dégeu)

  6. #26
    Membre expérimenté
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2009
    Messages
    141
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2009
    Messages : 141
    Par défaut
    Moi je vois ca differement, je suis presque sur que tout ca ca vient de la maniere de traiter l'effet de bord. La meilleure chose que tu puisse faire pour avoir le resultat identique a celui d'opencv c'est d'aller voir le code de cvFilter2D() par exemple et de voir comment eux ils le traitent. Il y a plusieurs solutions possibles (les ignorer, les traiter de maniere speciale en y appliquant un kernel reduit pour l'occasion,...). Je suis sur que dans le cas d'un filtre de convolution, rien que la repercution de ces resultats peuvent cree ce genre de differences dans le resultat.

  7. #27
    Membre confirmé
    Profil pro
    Developer
    Inscrit en
    Juin 2004
    Messages
    194
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Developer

    Informations forums :
    Inscription : Juin 2004
    Messages : 194
    Par défaut
    Merci snowpy ,

    Par effet de bord, on sous entend donc qu'une zone mémoire est altérée est ce bien cela et quel opérateur provoquerait cela? Peut être dans les conversions.

    Seul endroit suspect que j'ai vu c'est ici :

    accumulation += k * (kernel[1+ii][1+jj]);

    et donc j'ai déclaré les variables accumulation et weightsum en float mais ça ne semble pas corriger, dois-je caster mes variables?

    Merci

  8. #28
    Membre expérimenté
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2009
    Messages
    141
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2009
    Messages : 141
    Par défaut
    Non effet de bord dans le domaine du traitement d'image c'est que les pixels qui se trouvent aux bords de l'image doivent etre traites differement quand on applique un filtre de convolution par exemple. Regarde vite fait sur les tutoriels C++, ca t'apprendra en soit mais il y a une petite explication sur l'effet de bord quand on applique un filtre median a une image

    Dis moi si t'as encore des problemes avec ca mais sinon tu regarde le code de FilterEngine::proceed(). Tu pourras voir comment OpenCv traite les effets de bord.
    Edit:
    Je viens de voir aussi que tout autour de ton image t'as une bande noire ce qui veut dire que ta boucle ne tourne pas correctement. L'erreur que tu rencontrais viens justement de cette histoire d'effet de bord, si tu le prends en compte les boucles que je t'ai conseille marcheront.

  9. #29
    Membre confirmé
    Profil pro
    Developer
    Inscrit en
    Juin 2004
    Messages
    194
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Developer

    Informations forums :
    Inscription : Juin 2004
    Messages : 194
    Par défaut
    Salut,

    Merci pour les infos glen désolé du retard effectivement je vais revoir mon code et je vous tiendrais au courant. Merci à tous.

Discussions similaires

  1. Réponses: 9
    Dernier message: 03/03/2015, 14h57
  2. cvConvertScale sur une image en niveaux de gris
    Par dudux dans le forum OpenCV
    Réponses: 2
    Dernier message: 09/06/2011, 12h13
  3. Réponses: 3
    Dernier message: 14/04/2007, 21h30
  4. Détection de visages dans une image en niveaux de gris
    Par bert_ dans le forum Traitement d'images
    Réponses: 12
    Dernier message: 04/04/2007, 18h04

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo