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