Sobel.cpp

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  #include "../CImage.h" 
24   
25   
26   
27   
28  //Worker Threads 
29  //Chacun des threads a une partie de l'image a traiter et se termine lorsqu'il a fini sa zone 
30  DWORD WINAPI SOBEL(LPVOID lParam) 
31  { 
32    MULTITHREAD *MT=(MULTITHREAD*)lParam; 
33    MT->Error=0; 
34    if(MT->ImgDest==0 || MT->ImgDest->GetHBmp()==0){ 
35      MT->Error=1; 
36      return 0; 
37    } 
38    int i,j,Pos; 
39    double Gx,Gy; 
40    Dimension Dim=MT->ImgDest->GetDimension(); 
41   
42    if(MT->Param1!=RGBi) 
43      MT->ImgDest->SetType(GRAY); 
44   
45    for(i=MT->X0 ; i<MT->X1 ; i++) 
46      for(j=MT->Y0 ; j<MT->Y1 ; j++) 
47      { 
48   
49        Pos=( i+ j * Dim.cx)*4; 
50   
51        if(i==0 || i==Dim.cx-1 ||j==0 || j==Dim.cy-1) 
52        { 
53   
54          MT->ImgDest->ucBits[Pos+2]=0; 
55          MT->ImgDest->ucBits[Pos+1]=0; 
56          MT->ImgDest->ucBits[Pos+2]=0; 
57          continue; 
58        } 
59        switch(MT->Param1) 
60        { 
61        case RGBi : 
62   
63            Gx=  MT->ucBits[(i-1+(j-1)*Dim.cx)*4] + 2*MT->ucBits[(i+(j-1)*Dim.cx)*4] + MT->ucBits[(i+1+(j-1)*Dim.cx)*4] 
64               -MT->ucBits[(i-1+(j+1)*Dim.cx)*4] - 2*MT->ucBits[(i+(j+1)*Dim.cx)*4] - MT->ucBits[(i+1+(j+1)*Dim.cx)*4]; 
65            Gy=  MT->ucBits[(i-1+(j-1)*Dim.cx)*4] + 2*MT->ucBits[(i-1+j*Dim.cx)*4] + MT->ucBits[(i-1+(j+1)*Dim.cx)*4] 
66               -MT->ucBits[(i+1+(j+1)*Dim.cx)*4] - 2*MT->ucBits[(i+1+j*Dim.cx)*4] - MT->ucBits[(i+1+(j+1)*Dim.cx)*4]; 
67            MT->ImgDest->ucBits[Pos]=(int)Limit(sqrt(Gx*Gx+Gy*Gy)); 
68   
69            Gx=  MT->ucBits[(i-1+(j-1)*Dim.cx)*4+1] + 2*MT->ucBits[(i+(j-1)*Dim.cx)*4+1] + MT->ucBits[(i+1+(j-1)*Dim.cx)*4+1] 
70               -MT->ucBits[(i-1+(j+1)*Dim.cx)*4+1] - 2*MT->ucBits[(i+(j+1)*Dim.cx)*4+1] - MT->ucBits[(i+1+(j+1)*Dim.cx)*4+1]; 
71            Gy=  MT->ucBits[(i-1+(j-1)*Dim.cx)*4+1] + 2*MT->ucBits[(i-1+j*Dim.cx)*4+1] + MT->ucBits[(i-1+(j+1)*Dim.cx)*4+1] 
72               -MT->ucBits[(i+1+(j+1)*Dim.cx)*4+1] - 2*MT->ucBits[(i+1+j*Dim.cx)*4+1] - MT->ucBits[(i+1+(j+1)*Dim.cx)*4+1]; 
73            MT->ImgDest->ucBits[Pos+1]=(int)Limit(sqrt(Gx*Gx+Gy*Gy)); 
74   
75            Gx=  MT->ucBits[(i-1+(j-1)*Dim.cx)*4+2] + 2*MT->ucBits[(i+(j-1)*Dim.cx)*4+2] + MT->ucBits[(i+1+(j-1)*Dim.cx)*4+2] 
76               -MT->ucBits[(i-1+(j+1)*Dim.cx)*4+2] - 2*MT->ucBits[(i+(j+1)*Dim.cx)*4+2] - MT->ucBits[(i+1+(j+1)*Dim.cx)*4+2]; 
77            Gy=  MT->ucBits[(i-1+(j-1)*Dim.cx)*4+2] + 2*MT->ucBits[(i-1+j*Dim.cx)*4+2] + MT->ucBits[(i-1+(j+1)*Dim.cx)*4+2] 
78               -MT->ucBits[(i+1+(j+1)*Dim.cx)*4+2] - 2*MT->ucBits[(i+1+j*Dim.cx)*4+2] - MT->ucBits[(i+1+(j+1)*Dim.cx)*4+2]; 
79            MT->ImgDest->ucBits[Pos+2]=(int)Limit(sqrt(Gx*Gx+Gy*Gy)); 
80            break; 
81   
82          case GRAY : 
83            double D[8]; 
84   
85            D[0]=(MT->ucBits[(i-1+(j-1)*Dim.cx)*4]+MT->ucBits[(i-1+(j-1)*Dim.cx)*4+1]+MT->ucBits[(i-1+(j-1)*Dim.cx)*4+2])/3; 
86            D[1]=(MT->ucBits[(i+(j-1)*Dim.cx)*4]+MT->ucBits[(i+(j-1)*Dim.cx)*4+1]+MT->ucBits[(i+(j-1)*Dim.cx)*4+2])/3; 
87            D[2]=(MT->ucBits[(i+1+(j-1)*Dim.cx)*4]+MT->ucBits[(i+1+(j-1)*Dim.cx)*4+1]+MT->ucBits[(i+1+(j-1)*Dim.cx)*4+2])/3; 
88   
89            D[3]=(MT->ucBits[(i-1+j*Dim.cx)*4]+MT->ucBits[(i-1+j*Dim.cx)*4+1]+MT->ucBits[(i-1+j*Dim.cx)*4+2])/3; 
90            D[4]=(MT->ucBits[(i+1+j*Dim.cx)*4]+MT->ucBits[(i+1+j*Dim.cx)*4+1]+MT->ucBits[(i+1+j*Dim.cx)*4+2])/3; 
91   
92            D[5]=(MT->ucBits[(i-1+(j+1)*Dim.cx)*4]+MT->ucBits[(i-1+(j+1)*Dim.cx)*4+1]+MT->ucBits[(i-1+(j+1)*Dim.cx)*4+2])/3; 
93            D[6]=(MT->ucBits[(i+(j+1)*Dim.cx)*4]+MT->ucBits[(i+(j+1)*Dim.cx)*4+1]+MT->ucBits[(i+(j+1)*Dim.cx)*4+2])/3; 
94            D[7]=(MT->ucBits[(i+1+(j+1)*Dim.cx)*4]+MT->ucBits[(i+1+(j+1)*Dim.cx)*4+1]+MT->ucBits[(i+1+(j+1)*Dim.cx)*4+2])/3; 
95   
96            Gx=D[0]+2*D[1]+D[2]-D[5]-2*D[6]-D[7]; 
97            Gy=D[0]+2*D[3]+D[5]-D[2]-2*D[4]-D[7]; 
98   
99            MT->ImgDest->ucBits[Pos]=  (int)Limit(sqrt(Gx*Gx+Gy*Gy)); 
100            MT->ImgDest->ucBits[Pos+1]=MT->ImgDest->ucBits[Pos]; 
101            MT->ImgDest->ucBits[Pos+2]=MT->ImgDest->ucBits[Pos]; 
102   
103            break; 
104   
105          case RED  : 
106            Gx=  MT->ucBits[(i-1+(j-1)*Dim.cx)*4+2] + 2*MT->ucBits[(i+(j-1)*Dim.cx)*4+2] + MT->ucBits[(i+1+(j-1)*Dim.cx)*4+2] 
107               -MT->ucBits[(i-1+(j+1)*Dim.cx)*4+2] - 2*MT->ucBits[(i+(j+1)*Dim.cx)*4+2] - MT->ucBits[(i+1+(j+1)*Dim.cx)*4+2]; 
108            Gy=  MT->ucBits[(i-1+(j-1)*Dim.cx)*4+2] + 2*MT->ucBits[(i-1+j*Dim.cx)*4+2] + MT->ucBits[(i-1+(j+1)*Dim.cx)*4+2] 
109               -MT->ucBits[(i+1+(j+1)*Dim.cx)*4+2] - 2*MT->ucBits[(i+1+j*Dim.cx)*4+2] - MT->ucBits[(i+1+(j+1)*Dim.cx)*4+2]; 
110            MT->ImgDest->ucBits[Pos]=(int)Limit(sqrt(Gx*Gx+Gy*Gy)); 
111            MT->ImgDest->ucBits[Pos+1]=MT->ImgDest->ucBits[Pos]; 
112            MT->ImgDest->ucBits[Pos+2]=MT->ImgDest->ucBits[Pos]; 
113            break; 
114   
115   
116          case GREEN: 
117            Gx=  MT->ucBits[(i-1+(j-1)*Dim.cx)*4+1] + 2*MT->ucBits[(i+(j-1)*Dim.cx)*4+1] + MT->ucBits[(i+1+(j-1)*Dim.cx)*4+1] 
118               -MT->ucBits[(i-1+(j+1)*Dim.cx)*4+1] - 2*MT->ucBits[(i+(j+1)*Dim.cx)*4+1] - MT->ucBits[(i+1+(j+1)*Dim.cx)*4+1]; 
119            Gy=  MT->ucBits[(i-1+(j-1)*Dim.cx)*4+1] + 2*MT->ucBits[(i-1+j*Dim.cx)*4+1] + MT->ucBits[(i-1+(j+1)*Dim.cx)*4+1] 
120               -MT->ucBits[(i+1+(j+1)*Dim.cx)*4+1] - 2*MT->ucBits[(i+1+j*Dim.cx)*4+1] - MT->ucBits[(i+1+(j+1)*Dim.cx)*4+1]; 
121            MT->ImgDest->ucBits[Pos]=(int)Limit(sqrt(Gx*Gx+Gy*Gy)); 
122            MT->ImgDest->ucBits[Pos+1]=MT->ImgDest->ucBits[Pos]; 
123            MT->ImgDest->ucBits[Pos+2]=MT->ImgDest->ucBits[Pos]; 
124            break; 
125   
126          case BLUE : 
127            Gx=  MT->ucBits[(i-1+(j-1)*Dim.cx)*4] + 2*MT->ucBits[(i+(j-1)*Dim.cx)*4] + MT->ucBits[(i+1+(j-1)*Dim.cx)*4] 
128               -MT->ucBits[(i-1+(j+1)*Dim.cx)*4] - 2*MT->ucBits[(i+(j+1)*Dim.cx)*4] - MT->ucBits[(i+1+(j+1)*Dim.cx)*4]; 
129            Gy=  MT->ucBits[(i-1+(j-1)*Dim.cx)*4] + 2*MT->ucBits[(i-1+j*Dim.cx)*4] + MT->ucBits[(i-1+(j+1)*Dim.cx)*4] 
130               -MT->ucBits[(i+1+(j+1)*Dim.cx)*4] - 2*MT->ucBits[(i+1+j*Dim.cx)*4] - MT->ucBits[(i+1+(j+1)*Dim.cx)*4]; 
131            MT->ImgDest->ucBits[Pos]=(int)Limit(sqrt(Gx*Gx+Gy*Gy)); 
132            MT->ImgDest->ucBits[Pos+1]=MT->ImgDest->ucBits[Pos]; 
133            MT->ImgDest->ucBits[Pos+2]=MT->ImgDest->ucBits[Pos]; 
134            break; 
135          } 
136      } 
137   
138   
139    return 1; 
140  } 
141   
142  bool CImage::Sobel(int Type,CImage *ImgDest) 
143  { 
144    if(hBmp==0){ 
145      MessageBox(NULL,"Sobel : L'image source est vide", 
146            NULL,MB_OK|MB_ICONWARNING); 
147      return 0; 
148    } 
149    if(ImgDest==0) 
150      ImgDest=this; 
151   
152    CImage ImgTmp; 
153    int i; 
154   
155      HANDLE  hThread[NB_THREAD]; 
156    MULTITHREAD MT[NB_THREAD]; 
157   
158    ImgTmp.CopyProp(this); 
159   
160    InitThread(MT,Width,Height); 
161   
162   
163    for(i=0;i<NB_THREAD;i++){ 
164      MT[i].Param1=Type; 
165      MT[i].ImgDest=&ImgTmp; 
166      MT[i].ucBits=ucBits; 
167    } 
168   
169    GetBitmapBits (hBmp,(Width*Height)*4,ucBits); 
170   
171    for(i=0;i<NB_THREAD;i++) 
172    { 
173      hThread[i]=CreateThread(NULL,0,SOBEL,&MT[i],0,0); 
174      if (hThread[i] == NULL) 
175      { 
176        MessageBox(NULL,"Sobel : Erreur lors de la creation des threads", 
177            NULL,MB_OK|MB_ICONWARNING); 
178        return 0; 
179      } 
180    } 
181   
182    WaitForMultipleObjects(NB_THREAD, hThread, TRUE, INFINITE); 
183   
184    //Verifie si il y a eu des erreurs dans les threads 
185    for(i=0;i<NB_THREAD;i++){ 
186      CloseHandle(hThread[i]); 
187      if(MT[i].Error==1){ 
188        MessageBox(NULL,"Sobel : Erreur lors de l'execution des threads", 
189            NULL,MB_OK|MB_ICONWARNING); 
190        return 0; 
191   
192      } 
193    } 
194   
195   
196   
197    ImgDest->Copy(&ImgTmp); 
198   
199    SetBitmapBits (ImgDest->hBmp,(Width*Height)*4,ImgDest->ucBits); 
200    return 1; 
201  } 
202   
203  /* 
204  bool CImage::Sobel(int Type,CImage *ImgDest) 
205  { 
206    if(hBmp==0){ 
207      MessageBox(NULL,"Sobel : L'image source est vide", 
208            NULL,MB_OK|MB_ICONWARNING); 
209      return 0; 
210    } 
211     
212    if(ImgDest!=0 && ImgDest!=this) 
213      ImgDest->Copy(this); 
214    if(ImgDest==0) 
215      ImgDest=this; 
216   
217     
218    int i,j; 
219    double *dX=new double[Width*Height],Grad; 
220    double *dY=new double[Width*Height]; 
221     
222    double *dX_Red,*dY_Red,*dX_Green,*dY_Green; 
223    if(Type==RGBi) 
224    { 
225      dX_Red=new double[Width*Height]; 
226      dY_Red=new double[Width*Height]; 
227   
228      dX_Green=new double[Width*Height]; 
229      dY_Green=new double[Width*Height]; 
230    } 
231   
232    //recupération des pixels 
233    GetBitmapBits(hBmp,Width*Height*4,ucBits); 
234     
235    for(i=1;i<Width-1;i++) 
236      for(j=1;j<Height-1;j++) 
237      { 
238        switch(Type) 
239        { 
240        case RGBi: 
241          dX_Red[(i+j*Width)]=GetPixel(i-1,j-1,RED)-GetPixel(i+1,j-1,RED) 
242             +2*GetPixel(i-1,j,RED)-2*GetPixel(i+1,j,RED) 
243             +GetPixel(i-1,j+1,RED)-GetPixel(i+1,j+1,RED);   
244          dY_Red[(i+j*Width)]=GetPixel(i-1,j-1,RED)+2*GetPixel(i,j-1,RED)+GetPixel(i+1,j-1,RED) 
245             -GetPixel(i-1,j+1,RED)-2*GetPixel(i,j+1,RED)-GetPixel(i+1,j+1,RED); 
246           
247          dX_Green[(i+j*Width)]=GetPixel(i-1,j-1,GREEN)-GetPixel(i+1,j-1,GREEN) 
248             +2*GetPixel(i-1,j,GREEN)-2*GetPixel(i+1,j,GREEN) 
249             +GetPixel(i-1,j+1,GREEN)-GetPixel(i+1,j+1,GREEN);   
250          dY_Green[(i+j*Width)]=GetPixel(i-1,j-1,GREEN)+2*GetPixel(i,j-1,GREEN)+GetPixel(i+1,j-1,GREEN) 
251             -GetPixel(i-1,j+1,GREEN)-2*GetPixel(i,j+1,GREEN)-GetPixel(i+1,j+1,GREEN); 
252           
253          dX[(i+j*Width)]=GetPixel(i-1,j-1,BLUE)-GetPixel(i+1,j-1,BLUE) 
254             +2*GetPixel(i-1,j,BLUE)-2*GetPixel(i+1,j,BLUE) 
255             +GetPixel(i-1,j+1,BLUE)-GetPixel(i+1,j+1,BLUE);   
256          dY[(i+j*Width)]=GetPixel(i-1,j-1,BLUE)+2*GetPixel(i,j-1,BLUE)+GetPixel(i+1,j-1,BLUE) 
257             -GetPixel(i-1,j+1,BLUE)-2*GetPixel(i,j+1,BLUE)-GetPixel(i+1,j+1,BLUE); 
258        break; 
259        default: 
260          dX[(i+j*Width)]=GetPixel(i-1,j-1,Type)-GetPixel(i+1,j-1,Type) 
261             +2*GetPixel(i-1,j,Type)-2*GetPixel(i+1,j,Type) 
262             +GetPixel(i-1,j+1,Type)-GetPixel(i+1,j+1,Type); 
263             
264          dY[(i+j*Width)]=GetPixel(i-1,j-1,Type)+2*GetPixel(i,j-1,Type)+GetPixel(i+1,j-1,Type) 
265             -GetPixel(i-1,j+1,Type)-2*GetPixel(i,j+1,Type)-GetPixel(i+1,j+1,Type); 
266          break; 
267        } 
268      } 
269   
270    switch(Type) 
271    { 
272    case RGBi: 
273      ImgDest->ImgType=RGBi; 
274      for(i=0,j=0;i<Width*Height*4;i+=4,j++) 
275      {     
276        Grad=sqrt(dX[j]*dX[j]+dY[j]*dY[j]); 
277        ImgDest->ucBits[i]=Limit((int)Grad); 
278        Grad=sqrt(dX_Green[j]*dX_Green[j]+dY_Green[j]*dY_Green[j]); 
279        ImgDest->ucBits[i+1]=Limit((int)Grad); 
280        Grad=sqrt(dX_Red[j]*dX_Red[j]+dY_Red[j]*dY_Red[j]); 
281        ImgDest->ucBits[i+2]=Limit((int)Grad); 
282      } 
283      delete []dX_Red; 
284      delete []dY_Red; 
285      delete []dX_Green; 
286      delete []dY_Green; 
287   
288      break; 
289     
290    default: 
291      ImgDest->ImgType=GRAY; 
292      for(i=0,j=0;i<Width*Height*4;i+=4,j++) 
293      { 
294        Grad=sqrt(dX[j]*dX[j]+dY[j]*dY[j]); 
295        ImgDest->ucBits[i]=(UCHAR)Limit((int)Grad); 
296        ImgDest->ucBits[i+1]=(UCHAR)Limit((int)Grad); 
297        ImgDest->ucBits[i+2]=(UCHAR)Limit((int)Grad); 
298      } 
299      break; 
300    } 
301    delete []dX; 
302    delete []dY; 
303     
304    SetBitmapBits (ImgDest->hBmp,(Width*Height)*4,ImgDest->ucBits); 
305     
306    return 1; 
307  } 
308   
309   
310   
311   
312  */ 

lien1 lien2 lien3