Ca doit pas être quelquechose d'impossible tout de même :)
Version imprimable
Ca doit pas être quelquechose d'impossible tout de même :)
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.
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:
je sais pas si je t'ai bien compris ?Code:
1
2
3
4
5 for (int i=0; i<nl-1; i++) { for (int j=0; j<nc-1; j++ ) {
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:
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
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.Code:
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; }
Je ne vois pas ce qui pourrait faussé le résultat ?
Merci
je serais tenter de dire une approximation conversion float/int ou un truc du genre (jolie travail au passage :ccool: le résultat est loin d'être dégeu)
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.
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
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.
Salut,
Merci pour les infos glen désolé du retard effectivement je vais revoir mon code et je vous tiendrais au courant. Merci à tous.