Marr Hildreth
1 |
/*********************************************************************************** |
2 |
ImAnalyse : software in image processing and image analysis |
3 |
|
4 |
Copyright (C) 10 juillet 2008 <Vincent MORARD> |
5 |
Version: 2.1 |
6 |
Contact: vincent<POINT>morard<AROBAS>cpe<POINT>fr |
7 |
Website: http://ImAnalyse.free.fr |
8 |
Website: http://pistol.petesampras.free.fr |
9 |
|
10 |
This program is free software: you can redistribute it and/or modify |
11 |
it under the terms of the GNU General Public License as published by |
12 |
the Free Software Foundation, either version 3 of the License, or |
13 |
(at your option) any later version. |
14 |
|
15 |
This program is distributed in the hope that it will be useful, |
16 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 |
GNU General Public License for more details. |
19 |
|
20 |
You should have received a copy of the GNU General Public License |
21 |
along with this program. If not, see <http://www.gnu.org/licenses/ |
22 |
**********************************************************************************/ |
23 |
//****************************************************************************** |
24 |
//MarrHildreth |
25 |
//Cette fonction permet de calculer les contours suivant la méthode décrite par |
26 |
//Marr et Hildreth. Le principe est de calculer la derivée seconde de l'image et |
27 |
//de rechercher les zéros de cette image. |
28 |
//Pour ce faire, on calcule le laplacien de l'image. (Les dimensions de ce |
29 |
//filtre peuvent être changées suivant la valeur du paramètre d'entrée de |
30 |
//cette fonction.) Ce paramètre correspond à l'écart type du bruit. Plus s est |
31 |
//grand et plus le filtrage sera important. Il y aura donc moins de contours. |
32 |
//****************************************************************************** |
33 |
//************************************************************************* |
34 |
//Marr |
35 |
//On procède à tout le traitement dans cette fonction. |
36 |
//Calcul des coefficients du filtre Laplacian |
37 |
//convolution avec l'image initiale |
38 |
//et recherche des zéros de l'image obtenue |
39 |
//************************************************************************* |
40 |
#include "../CImage.h" |
41 |
#include "../AdvancEdge.h" |
42 |
|
43 |
bool CImage::MarrHildreth(CImage *ImgDest,float S) |
44 |
{ |
45 |
float **Img=0,s=(float)(S-0.8); |
46 |
|
47 |
|
48 |
int taille,i,j,n; |
49 |
|
50 |
float **Lissage=0,**LGaussian=0; |
51 |
|
52 |
if(hBmp==0){ |
53 |
MessageBox(NULL,"MarrHildreth : L'image source est vide", |
54 |
NULL,MB_OK|MB_ICONWARNING); |
55 |
return 0; |
56 |
} |
57 |
|
58 |
if(ImgDest != 0 && ImgDest != this) |
59 |
ImgDest->Copy(this); |
60 |
|
61 |
|
62 |
if(ImgDest == 0) |
63 |
ImgDest=this; |
64 |
GetBitmapBits(hBmp,Width*Height*4,ucBits); |
65 |
|
66 |
|
67 |
//Création d'un filtre gaussien et d'un filtre correspondant à la dérivé d'un filtre |
68 |
//gaussien de taille 2*taille*1 |
69 |
taille = (int)(3.35*s+0.33); |
70 |
n=2*taille+1; |
71 |
|
72 |
LGaussian=AllocT_float(n,n); |
73 |
|
74 |
//Création du masque avec la fonction LoG |
75 |
for(i=0;i<n;i++) |
76 |
for(j=0;j<n;j++) |
77 |
LGaussian[i][j]=LoG(Distance((float)i,(float)j,(float)taille,(float)taille),s); |
78 |
|
79 |
|
80 |
//Convolution de l'image initiale avec le masque en X et en Y |
81 |
Lissage=AllocT_float(Width,Height); |
82 |
|
83 |
Convo(LGaussian,n,n,Lissage); |
84 |
|
85 |
|
86 |
//localisation des passages à zero |
87 |
ImgDest->ZeroCrossing(Lissage); |
88 |
SetBitmapBits(ImgDest->hBmp,Width*Height*4,ImgDest->ucBits); |
89 |
|
90 |
|
91 |
DesAllocT_float(Lissage,Width); |
92 |
DesAllocT_float(LGaussian,n); |
93 |
|
94 |
return 1; |
95 |
} |
96 |
|
97 |
//**************************************************************************** |
98 |
//ZeroCrossing |
99 |
//Cette fonction effectue la multiplication de deux pixels voisin et si le |
100 |
//résultat est négatif alors cela signifie qu'il y a eu un passage par zero. |
101 |
//**************************************************************************** |
102 |
void CImage::ZeroCrossing(float **Laplacian) |
103 |
{ |
104 |
|
105 |
int i,j; |
106 |
|
107 |
for(i=1;i<Width-1;i++) |
108 |
for(j=1;j<Height-1;j++) |
109 |
{ |
110 |
SetPixel(i,j,0,0,0); |
111 |
if(Laplacian[i-1][j]*Laplacian[i+1][j]<0) |
112 |
{SetPixel(i,j,255,255,255);continue;} |
113 |
|
114 |
if(Laplacian[i][j-1]*Laplacian[i][j+1]<0) |
115 |
{SetPixel(i,j,255,255,255);continue;} |
116 |
|
117 |
if(Laplacian[i+1][j-1]*Laplacian[i-1][j+1]<0) |
118 |
{SetPixel(i,j,255,255,255);continue;} |
119 |
|
120 |
if(Laplacian[i-1][j-1]*Laplacian[i+1][j+1]<0) |
121 |
{SetPixel(i,j,255,255,255);continue;} |
122 |
|
123 |
} |
124 |
|
125 |
|
126 |
|
127 |
} |
128 |
|
129 |
//*************************************************************************** |
130 |
//Convo |
131 |
//Convolution de l'image Img par le noyau Mask. Le resulat est stoker dans la |
132 |
//variable Res |
133 |
//*************************************************************************** |
134 |
void CImage::Convo(float **Mask,int MaskLargeur,int MaskHauteur,float **Res) |
135 |
{ |
136 |
int i,j,k,l; |
137 |
float x; |
138 |
for(i=MaskLargeur/2;i<Width-MaskLargeur/2;i++) |
139 |
for(j=MaskHauteur/2;j<Height-MaskHauteur/2;j++) |
140 |
{ |
141 |
|
142 |
x=0.0; |
143 |
for(k=0;k<MaskLargeur;k++) |
144 |
for(l=0;l<MaskHauteur;l++) |
145 |
x+=Mask[k][l]*(float)GetPixel(i+k-MaskLargeur/2,j+l-MaskHauteur/2,GRAY); |
146 |
|
147 |
Res[i][j]=x; |
148 |
} |
149 |
|
150 |
} |
151 |
|
152 |
|
153 |
float LoG(float x, float Sigma) |
154 |
{ |
155 |
float x1; |
156 |
x1=Gauss(x,Sigma); |
157 |
return (x*x-2*Sigma*Sigma)/(pow(Sigma,4)) *x1; |
158 |
|
159 |
} |
160 |
|
161 |
float Distance(float a, float b,float c,float d) |
162 |
{ |
163 |
return Norm(a-c,b-d); |
164 |
} |
lien1 lien2 lien3