Hough.cpp
1 |
/*********************************************************************************** |
2 |
ImAnalyse : software in image processing and image analysis |
3 |
|
4 |
Copyright (C) 27 avril 2008 <Vincent MORARD> |
5 |
Version: 2.0 |
6 |
Contact: vincent<POINT>morard<AROBAS>cpe<POINT>fr |
7 |
Website: http://pistol.petesampras.free.fr |
8 |
|
9 |
This program is free software: you can redistribute it and/or modify |
10 |
it under the terms of the GNU General Public License as published by |
11 |
the Free Software Foundation, either version 3 of the License, or |
12 |
(at your option) any later version. |
13 |
|
14 |
This program is distributed in the hope that it will be useful, |
15 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 |
GNU General Public License for more details. |
18 |
|
19 |
You should have received a copy of the GNU General Public License |
20 |
along with this program. If not, see <http://www.gnu.org/licenses/ |
21 |
**********************************************************************************/ |
22 |
#include "CImage.h" |
23 |
|
24 |
|
25 |
|
26 |
//Incrementation des pixels appartennant au cercle =>Hough |
27 |
bool CImage::DrawCircle(int Rayon,int Xoffset,int Yoffset) |
28 |
{ |
29 |
if(hBmp==0){ |
30 |
MessageBox(NULL,"DrawCircle: L'image source est vide", |
31 |
NULL,MB_OK|MB_ICONWARNING); |
32 |
return 0; |
33 |
} |
34 |
double i,x=1,y=0; |
35 |
double ytmp,xtmp; |
36 |
|
37 |
//recupération des pixels |
38 |
GetBitmapBits(hBmp,Width*Height*4,ucBits); |
39 |
|
40 |
double Pas=3.14159/(3*Rayon); |
41 |
for(i=0;i<PI/2;i+=Pas) |
42 |
{ |
43 |
xtmp=(x*cos(i)+y*sin(i)); |
44 |
ytmp=(-x*sin(i)+y*cos(i)); |
45 |
|
46 |
SetPixelInc((int)(xtmp*Rayon+ Xoffset),(int)(ytmp*Rayon+Yoffset)); |
47 |
SetPixelInc((int)(-xtmp*Rayon+ Xoffset),(int)(ytmp*Rayon+Yoffset)); |
48 |
SetPixelInc((int)(xtmp*Rayon+ Xoffset),(int)(-ytmp*Rayon+Yoffset)); |
49 |
SetPixelInc((int)(-xtmp*Rayon+ Xoffset),(int)(-ytmp*Rayon+Yoffset)); |
50 |
|
51 |
} |
52 |
|
53 |
SetBitmapBits (hBmp,(Width*Height)*4,ucBits); |
54 |
|
55 |
return true; |
56 |
} |
57 |
|
58 |
//Dessin d'un cercle sur l'image avec les couleur R,G, et B |
59 |
bool CImage::DrawCircle(int Rayon,int Xoffset,int Yoffset,int R,int G,int B) |
60 |
{ |
61 |
if(hBmp==0){ |
62 |
MessageBox(NULL,"DrawCircle: L'image source est vide", |
63 |
NULL,MB_OK|MB_ICONWARNING); |
64 |
return 0; |
65 |
} |
66 |
double i,x=1,y=0; |
67 |
double ytmp,xtmp; |
68 |
|
69 |
//recupération des pixels |
70 |
GetBitmapBits(hBmp,Width*Height*4,ucBits); |
71 |
|
72 |
double Pas=3.14159/(3*Rayon); |
73 |
for(i=0;i<PI/2;i+=Pas) |
74 |
{ |
75 |
xtmp=(x*cos(i)+y*sin(i)); |
76 |
ytmp=(-x*sin(i)+y*cos(i)); |
77 |
|
78 |
SetPixel((int)(xtmp*Rayon+ Xoffset),(int)(ytmp*Rayon+Yoffset),R,G,B); |
79 |
SetPixel((int)(-xtmp*Rayon+ Xoffset),(int)(ytmp*Rayon+Yoffset),R,G,B); |
80 |
SetPixel((int)(xtmp*Rayon+ Xoffset),(int)(-ytmp*Rayon+Yoffset),R,G,B); |
81 |
SetPixel((int)(-xtmp*Rayon+ Xoffset),(int)(-ytmp*Rayon+Yoffset),R,G,B); |
82 |
|
83 |
} |
84 |
|
85 |
SetBitmapBits (hBmp,(Width*Height)*4,ucBits); |
86 |
if(R!=B || R!=G) |
87 |
ImgType=RGBi; |
88 |
return true; |
89 |
} |
90 |
|
91 |
//Retourne la valeur max de l'image d'accumulation creer par Hough |
92 |
int CImage::Count(int *X,int *Y) |
93 |
{ |
94 |
int Max=0,Pos,i,j; |
95 |
|
96 |
for(j=0;j<Height;j++) |
97 |
for(i=0;i<Width*4;i+=4) |
98 |
{ |
99 |
Pos=i+j*Width*4; |
100 |
if(ucBits[Pos]+256*ucBits[Pos+1]>Max) |
101 |
{ |
102 |
Max=ucBits[Pos]+256*ucBits[Pos+1]; |
103 |
*X=i/4; |
104 |
*Y=j; |
105 |
} |
106 |
} |
107 |
|
108 |
return Max; |
109 |
} |
110 |
|
111 |
//Calcule de la transformée de Hough en connaissant un rayon précis |
112 |
//Pour chaque point blanc de l'image, on trace le cercle de rayon R. |
113 |
//Ces cercles convergerons sur le centre du cercle s'il est de rayon R. |
114 |
bool CImage::HoughCircle(int RayonSearch,CImage *ImgDest) |
115 |
{ |
116 |
if(hBmp==0){ |
117 |
MessageBox(NULL,"HoughCircle: L'image source est vide", |
118 |
NULL,MB_OK|MB_ICONWARNING); |
119 |
return 0; |
120 |
} |
121 |
if(ImgType!=BIN){ |
122 |
MessageBox(NULL,"HoughCircle: L'image source DOIT etre binaire", |
123 |
NULL,MB_OK|MB_ICONWARNING); |
124 |
return 0; |
125 |
} |
126 |
|
127 |
if(ImgDest!=0 && ImgDest!=this) |
128 |
ImgDest->Copy(this); |
129 |
if(ImgDest==0) |
130 |
ImgDest=this; |
131 |
|
132 |
int i,j; |
133 |
ImgDest->Fill(0,0,0); |
134 |
for(j=0;j<Height;j++) |
135 |
for(i=0;i<Width;i++) |
136 |
if(ucBits[4*(i+j*Width)]==255) |
137 |
ImgDest->DrawCircle(RayonSearch,i,j); |
138 |
|
139 |
|
140 |
return true; |
141 |
} |
142 |
|
143 |
//Recherche dans un interval de rayon, la valeur max de l'accumulateur |
144 |
//Permet de trouver le meilleur cercle dans un interval. |
145 |
bool CImage::HoughCircleCompute(int RayonMin,int RayonMax,CImage *ImgDest,int *X,int *Y,int *Rayon) |
146 |
{ |
147 |
if(hBmp==0){ |
148 |
MessageBox(NULL,"HoughCircle: L'image source est vide", |
149 |
NULL,MB_OK|MB_ICONWARNING); |
150 |
return 0; |
151 |
} |
152 |
if(ImgType!=BIN){ |
153 |
MessageBox(NULL,"HoughCircle: L'image source DOIT etre binaire", |
154 |
NULL,MB_OK|MB_ICONWARNING); |
155 |
return 0; |
156 |
} |
157 |
|
158 |
if(ImgDest!=0 && ImgDest!=this) |
159 |
ImgDest->Copy(this); |
160 |
if(ImgDest==0) |
161 |
ImgDest=this; |
162 |
|
163 |
int MaxAcc=-1,R,Acc,NewX,NewY; |
164 |
CImage ImgTmp; |
165 |
for(R=RayonMin;R<=RayonMax;R++) |
166 |
{ |
167 |
int i,j; |
168 |
ImgDest->Fill(0,0,0); |
169 |
for(j=0;j<Height;j++) |
170 |
{ |
171 |
for(i=0;i<Width;i++) |
172 |
if(ucBits[4*(i+j*Width)]==255) |
173 |
ImgDest->DrawCircle(R,i,j); |
174 |
} |
175 |
|
176 |
|
177 |
Acc=ImgDest->Count(&NewX,&NewY); |
178 |
if(Acc>MaxAcc) |
179 |
{ |
180 |
MaxAcc=Acc; |
181 |
*X=NewX; |
182 |
*Y=NewY; |
183 |
*Rayon=R; |
184 |
ImgTmp.Copy(ImgDest); |
185 |
} |
186 |
|
187 |
} |
188 |
*X+=1; |
189 |
*Y+=1; |
190 |
ImgDest->Copy(&ImgTmp); |
191 |
ImgTmp.Nettoyage(); |
192 |
return true; |
193 |
} |
194 |
|
195 |
|
196 |
|
197 |
//Ajout d'un bruit uniforme sur l'image |
198 |
bool CImage::BruitUniforme(int Amplitude,CImage *ImgDest) |
199 |
{ |
200 |
if(hBmp==0){ |
201 |
MessageBox(NULL,"BruitUniforme : L'image source est vide", |
202 |
NULL,MB_OK|MB_ICONWARNING); |
203 |
return 0; |
204 |
} |
205 |
|
206 |
if(ImgDest!=0 && ImgDest!=this) |
207 |
ImgDest->Copy(this); |
208 |
if(ImgDest==0) |
209 |
ImgDest=this; |
210 |
|
211 |
if(Amplitude == 0 )return 1; |
212 |
int x; |
213 |
//recupération des pixels |
214 |
GetBitmapBits(hBmp,Width*Height*4,ucBits); |
215 |
|
216 |
for(int i=0;i<Width*Height*4;i+=4) |
217 |
{ |
218 |
x=rand()%Amplitude-Amplitude/2; |
219 |
ImgDest->ucBits[i]=Limit(ucBits[i]+x); |
220 |
ImgDest->ucBits[i+1]=Limit(ucBits[i+1]+x); |
221 |
ImgDest->ucBits[i+2]=Limit(ucBits[i+2]+x); |
222 |
|
223 |
} |
224 |
//recupération des pixels |
225 |
SetBitmapBits(ImgDest->hBmp,Width*Height*4,ImgDest->ucBits); |
226 |
return 1; |
227 |
|
228 |
} |
229 |
//Scale entre 0 et 255 |
230 |
bool CImage::HoughContrasteAuto(CImage *ImgDest) |
231 |
{ |
232 |
if(hBmp==0){ |
233 |
MessageBox(NULL,"HoughContrasteAuto : L'image source est vide", |
234 |
NULL,MB_OK|MB_ICONWARNING); |
235 |
return 0; |
236 |
} |
237 |
|
238 |
if(ImgDest!=0 && ImgDest!=this) |
239 |
ImgDest->Copy(this); |
240 |
if(ImgDest==0) |
241 |
ImgDest=this; |
242 |
|
243 |
|
244 |
//recupération des pixels |
245 |
GetBitmapBits(hBmp,Width*Height*4,ucBits); |
246 |
int Max=0,Val; |
247 |
for(int i=0;i<4*Width*Height;i+=4) |
248 |
{ |
249 |
Val=ucBits[i]+256*ucBits[i+1]; |
250 |
if(Val>Max) |
251 |
Max=Val; |
252 |
} |
253 |
for(int i=0;i<4*Width*Height;i+=4) |
254 |
{ |
255 |
Val=ucBits[i]+256*ucBits[i+1]; |
256 |
ImgDest->ucBits[i]=0; |
257 |
ImgDest->ucBits[i+1]=0; |
258 |
ImgDest->ucBits[i+2]=(UCHAR)((double)(Val/(double)Max)*255); |
259 |
} |
260 |
SetBitmapBits(ImgDest->hBmp,Width*Height*4,ImgDest->ucBits); |
261 |
return 1; |
262 |
} |
lien1 lien2 lien3