Morphologie.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   
23  #include "../CImage.h" 
24   
25   
26  int StructLenght=3; 
27  bool Struct[225]; 
28  bool BordClair=0; 
29  bool first=1; 
30   
31   
32  bool CImage::Erosion(bool *Noyau,int KernelLenght,bool BordureColor,CImage *ImgDest) 
33  { 
34    if(hBmp==0){ 
35      MessageBox(NULL,"Erosion : L'image source est vide", 
36            NULL,MB_OK|MB_ICONWARNING); 
37      return 0; 
38    } 
39   
40    if(ImgType!=BIN){ 
41      MessageBox(NULL,"Erosion : L'image source doit etre binaire", 
42            NULL,MB_OK|MB_ICONWARNING); 
43      return 0; 
44    } 
45   
46    if(ImgDest!=0 && ImgDest!=this) 
47      ImgDest->Copy(this); 
48    if(ImgDest==0) 
49      ImgDest=this; 
50   
51    int i,j,k,l,n,Pos; 
52    bool Skip; 
53    bool *Tab=new bool[Width*Height]; 
54    n=(int)sqrt((double)KernelLenght); 
55   
56    //recupération des pixels 
57    GetBitmapBits(hBmp,Width*Height*4,ucBits); 
58   
59    for(i=n/2;i<Width-n/2;i++) 
60      for(j=n/2;j<Height-n/2;j++) 
61      { 
62        Pos=(i+j*Width); 
63        Tab[Pos]=0; 
64        Skip=false; 
65        for(l=-n/2;l<=n/2 && Skip==0 ;l++) 
66          for(k=-n/2; k<=n/2 && Skip==0 ;k++) 
67            if(Noyau[(k+n/2)+(l+n/2)*n] && GetPixel(i+k,j+l,BLUE)==0) 
68              Skip=true; 
69        if(!Skip) 
70          Tab[Pos]=1; 
71      } 
72   
73      /* 
74    for(i=0;i<Width;i++){ 
75      for(j=0;j<n/2;j++) 
76        Tab[i+j*Width]=BordureColor; 
77      for(j=Height-1;j>Height-1-n/2;j--) 
78        Tab[i+j*Width]=BordureColor; 
79    } 
80    for(j=0;j<Height;j++){ 
81      for(i=0;i<n/2;i++) 
82        Tab[i+j*Width]=BordureColor; 
83      for(i=Width-1;i>Width-1-n/2;i--) 
84        Tab[i+j*Width]=BordureColor; 
85    } 
86    */ 
87   
88    ImgDest->ImgType=BIN; 
89    for(i=0,j=0;i<Width*Height*4;i+=4,j++) 
90    { 
91      ImgDest->ucBits[i]=(Tab[j]== 1 ? 255 : 0); 
92      ImgDest->ucBits[i+1]=ImgDest->ucBits[i]; 
93      ImgDest->ucBits[i+2]=ImgDest->ucBits[i]; 
94    } 
95   
96   
97    delete []Tab; 
98    SetBitmapBits (ImgDest->hBmp,(Width*Height)*4,ImgDest->ucBits); 
99    return 1; 
100  } 
101   
102  bool CImage::Dilatation(bool *Noyau,int KernelLenght,bool BordureColor,CImage *ImgDest) 
103  { 
104    if(hBmp==0){ 
105      MessageBox(NULL,"Dilatation : L'image source est vide", 
106            NULL,MB_OK|MB_ICONWARNING); 
107      return 0; 
108    } 
109   
110    if(ImgType!=BIN){ 
111      MessageBox(NULL,"Dilatation : L'image source doit être binaire", 
112            NULL,MB_OK|MB_ICONWARNING); 
113      return 0; 
114    } 
115   
116    if(ImgDest==0) 
117      ImgDest=this; 
118   
119    CImage ImgTmp; 
120    ImgTmp.Copy(this); 
121    ImgTmp.NOT(); 
122    ImgTmp.Erosion(Noyau,KernelLenght,BordureColor); 
123    ImgTmp.NOT(); 
124    ImgDest->Copy(&ImgTmp); 
125    return true; 
126   
127  } 
128   
129  bool CImage::Ouverture(bool *Noyau,int KernelLenght,bool BordureColor,CImage *ImgDest) 
130  { 
131    if(hBmp==0){ 
132      MessageBox(NULL,"Ouverture : L'image source est vide", 
133            NULL,MB_OK|MB_ICONWARNING); 
134      return 0; 
135    } 
136   
137    if(ImgType!=BIN){ 
138      MessageBox(NULL,"Ouverture : L'image source doit être binaire", 
139            NULL,MB_OK|MB_ICONWARNING); 
140      return 0; 
141    } 
142   
143    if(ImgDest==0) 
144      ImgDest=this; 
145   
146    CImage ImgTmp; 
147    ImgTmp.Copy(this); 
148    ImgTmp.Erosion(Noyau,KernelLenght,BordureColor); 
149    ImgTmp.Dilatation(Noyau,KernelLenght,BordureColor); 
150    ImgDest->Copy(&ImgTmp); 
151    return true; 
152  } 
153   
154  bool CImage::Fermeture(bool *Noyau,int KernelLenght,bool BordureColor,CImage *ImgDest) 
155  { 
156    if(hBmp==0){ 
157      MessageBox(NULL,"Fermeture : L'image source est vide", 
158            NULL,MB_OK|MB_ICONWARNING); 
159      return 0; 
160    } 
161   
162    if(ImgType!=BIN){ 
163      MessageBox(NULL,"Fermeture : L'image source doit être binaire", 
164            NULL,MB_OK|MB_ICONWARNING); 
165      return 0; 
166    } 
167   
168    if(ImgDest==0) 
169      ImgDest=this; 
170   
171    CImage ImgTmp; 
172    ImgTmp.Copy(this); 
173    ImgTmp.Dilatation(Noyau,KernelLenght,BordureColor); 
174    ImgTmp.Erosion(Noyau,KernelLenght,BordureColor); 
175    ImgDest->Copy(&ImgTmp); 
176    return true; 
177  } 
178   
179   
180   
181   
182  bool CImage::ErosionNG(bool *Noyau,int KernelLenght,bool BordureColor,CImage *ImgDest) 
183  { 
184    if(hBmp==0){ 
185      MessageBox(NULL,"Erosion Niveau de gris: L'image source est vide", 
186            NULL,MB_OK|MB_ICONWARNING); 
187      return 0; 
188    } 
189   
190    if(ImgDest!=0 && ImgDest!=this) 
191      ImgDest->Copy(this); 
192    if(ImgDest==0) 
193      ImgDest=this; 
194   
195    int i,j,k,l,n,Min,tmp,*Tab; 
196    n=(int)sqrt((double)KernelLenght); 
197    Tab=new int[Width*Height]; 
198   
199    GetBitmapBits(hBmp,Width*Height*4,ucBits); 
200   
201    for(i=0;i<Width;i++) 
202      for(j=0;j<Height;j++) 
203      { 
204        Min=255; 
205   
206        for(k=-n/2;k<=n/2;k++) 
207          for(l=-n/2;l<=n/2;l++) 
208          { 
209            if(!Noyau[(k+n/2)+(l+n/2)*n] || i+k<0 || i+k >=Width || j+l<0 || j+l>=Height) 
210              continue; 
211   
212            if((tmp=(int)GetPixel(i+k,j+l,GRAY))<Min) 
213              Min=tmp; 
214          } 
215        Tab[i+j*Width]=Min; 
216      } 
217   
218    ImgDest->ImgType=GRAY; 
219    for(i=0,j=0;i<Width*Height*4;i+=4,j++) 
220    { 
221      ImgDest->ucBits[i]=Tab[j]; 
222      ImgDest->ucBits[i+1]=ImgDest->ucBits[i]; 
223      ImgDest->ucBits[i+2]=ImgDest->ucBits[i]; 
224    } 
225   
226    SetBitmapBits (ImgDest->hBmp,(Width*Height)*4,ImgDest->ucBits); 
227    delete []Tab; 
228    return 1; 
229   
230   
231  } 
232  bool CImage::DilatationNG(bool *Noyau,int KernelLenght,bool BordureColor,CImage *ImgDest) 
233  { 
234    if(hBmp==0){ 
235      MessageBox(NULL,"Dilatation Niveau de gris: L'image source est vide", 
236            NULL,MB_OK|MB_ICONWARNING); 
237      return 0; 
238    } 
239   
240    if(ImgDest!=0 && ImgDest!=this) 
241      ImgDest->Copy(this); 
242    if(ImgDest==0) 
243      ImgDest=this; 
244   
245    int i,j,k,l,n,Max,tmp,*Tab; 
246    n=(int)sqrt((double)KernelLenght); 
247    Tab=new int[Width*Height]; 
248   
249    GetBitmapBits(hBmp,Width*Height*4,ucBits); 
250   
251    for(i=0;i<Width;i++) 
252      for(j=0;j<Height;j++) 
253      { 
254        Max=0; 
255        for(k=-n/2;k<=n/2;k++) 
256          for(l=-n/2;l<=n/2;l++) 
257          { 
258            if(i+k<0 || i+k >=Width || j+l<0 || j+l>=Height) 
259              continue; 
260            if((tmp=(int)GetPixel(i+k,j+l,GRAY))>Max) 
261              Max=tmp; 
262          } 
263        Tab[i+j*Width]=Max; 
264      } 
265   
266    ImgDest->ImgType=GRAY; 
267    for(i=0,j=0;i<Width*Height*4;i+=4,j++) 
268    { 
269      ImgDest->ucBits[i]=Tab[j]; 
270      ImgDest->ucBits[i+1]=ImgDest->ucBits[i]; 
271      ImgDest->ucBits[i+2]=ImgDest->ucBits[i]; 
272    } 
273   
274    SetBitmapBits (ImgDest->hBmp,(Width*Height)*4,ImgDest->ucBits); 
275    delete []Tab; 
276    return 1; 
277  } 
278   
279   
280  bool CImage::BlackTopHat(bool *Noyau,int KernelLenght,bool BordureColor,CImage *ImgDest) 
281  { 
282    if(hBmp==0){ 
283      MessageBox(NULL,"BlackTopHat : L'image source est vide", 
284            NULL,MB_OK|MB_ICONWARNING); 
285      return 0; 
286    } 
287    if(ImgDest==0) 
288      ImgDest=this; 
289   
290    CImage ImgTmp; 
291    ImgTmp.Copy(this); 
292    ImgTmp.ErosionNG(Noyau,KernelLenght,BordureColor); 
293    ImgTmp.DilatationNG(Noyau,KernelLenght,BordureColor); 
294    Soustraction(&ImgTmp,ImgDest); 
295    ImgDest->ImgType=GRAY; 
296    return true; 
297  } 
298   
299  bool CImage::WhiteTopHat(bool *Noyau,int KernelLenght,bool BordureColor,CImage *ImgDest) 
300  { 
301    if(hBmp==0){ 
302      MessageBox(NULL,"WhiteTopHat : L'image source est vide", 
303            NULL,MB_OK|MB_ICONWARNING); 
304      return 0; 
305    } 
306    if(ImgDest==0) 
307      ImgDest=this; 
308   
309    CImage ImgTmp; 
310    ImgTmp.Copy(this); 
311    ImgTmp.DilatationNG(Noyau,KernelLenght,BordureColor); 
312    ImgTmp.ErosionNG(Noyau,KernelLenght,BordureColor); 
313    Soustraction(&ImgTmp,ImgDest); 
314    ImgDest->ImgType=GRAY; 
315   
316    return true; 
317  } 
318   
319  bool CImage::GradientMor(bool *Noyau,int KernelLenght,bool BordureColor,CImage *ImgDest) 
320  { 
321    if(hBmp==0){ 
322      MessageBox(NULL,"Gradient Morphologique : L'image source est vide", 
323            NULL,MB_OK|MB_ICONWARNING); 
324      return 0; 
325    } 
326    if(ImgDest==0) 
327      ImgDest=this; 
328   
329    CImage ImgTmp; 
330    ImgTmp.Copy(this); 
331    ImgTmp.ErosionNG(Noyau,KernelLenght,BordureColor); 
332    Soustraction(&ImgTmp,ImgDest); 
333    ImgDest->ImgType=GRAY; 
334    return true; 
335  } 
336   
337   
338   
339  bool APIENTRY DialogMORProc(HWND hDlg,UINT uMsg,WPARAM wParam,LPARAM lParam) 
340  { 
341   
342    HBRUSH hBrush ; 
343    HPEN hPen,hPenSelect; 
344    HDC    hdc ; 
345    RECT   rect ; 
346    PAINTSTRUCT ps ; 
347    static HWND hSpin; 
348    char szBuf[5]; 
349    //static int Src; 
350    static int Taille=3; 
351    static bool Tab[225]; 
352   
353   
354    int i; 
355    switch (uMsg) 
356    { 
357    case WM_SETFOCUS: 
358      if(wParam==IDC_EDIT_MOR_TAILLE) 
359        Taille=(Taille > 15 ? 15 : max(3,Taille)); 
360          Taille=(Taille%2==0 ? Taille+1 : Taille); 
361        SetDlgItemInt(hDlg, IDC_EDIT_MOR_TAILLE, Taille, FALSE); 
362    break; 
363    case WM_INITDIALOG: 
364   
365       CheckRadioButton(hDlg,IDC_RADIO_MOR_SOMBRE,IDC_RADIO_MOR_CLAIR,IDC_RADIO_MOR_SOMBRE+BordClair); 
366       SetDlgItemInt(hDlg, IDC_EDIT_MOR_SRC, (int)lParam,FALSE); 
367       SetDlgItemInt(hDlg, IDC_EDIT_MOR_DEST, (int)lParam+1,FALSE); 
368       SetDlgItemInt(hDlg, IDC_EDIT_MOR_TAILLE, StructLenght,FALSE); 
369       SendDlgItemMessage(hDlg, IDC_COMBO_MOR, CB_ADDSTRING, 0, (LPARAM)"Erosion"); 
370       SendDlgItemMessage(hDlg, IDC_COMBO_MOR, CB_ADDSTRING, 0, (LPARAM)"Dilatation"); 
371       SendDlgItemMessage(hDlg, IDC_COMBO_MOR, CB_ADDSTRING, 0, (LPARAM)"Ouverture"); 
372       SendDlgItemMessage(hDlg, IDC_COMBO_MOR, CB_ADDSTRING, 0, (LPARAM)"Fermeture"); 
373       SendDlgItemMessage(hDlg, IDC_COMBO_MOR, CB_ADDSTRING, 0, (LPARAM)"Top Hat foncée"); 
374       SendDlgItemMessage(hDlg, IDC_COMBO_MOR, CB_ADDSTRING, 0, (LPARAM)"Top Hat clair"); 
375       SendDlgItemMessage(hDlg, IDC_COMBO_MOR, CB_ADDSTRING, 0, (LPARAM)"Gradient Morphologique"); 
376       SendDlgItemMessage(hDlg, IDC_COMBO_MOR, CB_SETCURSEL, 0, 0); 
377   
378       for(i=0;i<225;i++) 
379         Tab[i]=Struct[i]; 
380   
381       if(first) 
382         SendMessage(hDlg,WM_COMMAND,IDC_BUTTON_MOR_REMPLIR,0); 
383       first=0; 
384      return TRUE; 
385   
386   
387    case WM_VSCROLL: 
388        int Old; 
389        Old=Taille; 
390            switch (LOWORD (wParam)) 
391            { 
392            case SB_LINEUP: 
393                 Taille =Taille+2 ; 
394           Taille=(Taille > 15 ? 15 : max(3,Taille)); 
395             Taille=(Taille%2==0 ? Taille+1 : Taille); 
396           SetDlgItemInt(hDlg, IDC_EDIT_MOR_TAILLE, Taille,FALSE); 
397           if(Old!=Taille)InvalidateRect(hDlg,0,TRUE); 
398                 break ; 
399   
400            case SB_LINEDOWN: 
401                 Taille =Taille-2 ; 
402           Taille=(Taille > 15 ? 15 : max(3,Taille)); 
403             Taille=(Taille%2==0 ? Taille+1 : Taille); 
404           SetDlgItemInt(hDlg, IDC_EDIT_MOR_TAILLE, Taille,FALSE); 
405           if(Old!=Taille)InvalidateRect(hDlg,0,TRUE); 
406                 break ; 
407   
408        } 
409   
410   
411      break; 
412   
413    case WM_PAINT: 
414      int i,j,n; 
415      GetDlgItemText(hDlg, IDC_EDIT_MOR_TAILLE, szBuf, 5); 
416      Taille=atoi(szBuf); 
417      n=(Taille > 15 ? 15 : max(3,Taille)); 
418      n=(n%2==0 ? n+1 : n); 
419   
420      hdc=BeginPaint(hDlg,&ps); 
421   
422      hBrush = CreateSolidBrush (RGB (236,233,216)) ; 
423      hPen = CreatePen (PS_SOLID, 2, RGB(50,50,50)); 
424      hPenSelect= CreatePen(PS_SOLID, 2, RGB(180,0,0)); 
425      SelectObject(hdc,hBrush); 
426      SelectObject(hdc,hPen); 
427      for(i=-n/2;i<=n/2;i++) 
428        for(j=-n/2;j<=n/2;j++) 
429        { 
430          if(i==0 && j==0)SelectObject(hdc,hPenSelect); 
431          if(i==0 && j==1)SelectObject(hdc,hPen); 
432          Ellipse(hdc, (148+i*18 - 9), (148+j*18- 9), (148+i*18 + 9), (148+j*18 + 9)); 
433          if(Tab[i+7+(j+7)*15]) 
434          { 
435            MoveToEx (hdc,148+i*18+6,148+j*18+6, NULL) ; 
436            LineTo (hdc,148+i*18-6,148+j*18-6); 
437            MoveToEx (hdc,148+i*18+6,148+j*18-6, NULL) ; 
438            LineTo (hdc,148+i*18-6,148+j*18+6); 
439          } 
440   
441        } 
442      EndPaint(hDlg,&ps); 
443      break; 
444   
445    case WM_LBUTTONDOWN: 
446   
447      int x,y; 
448   
449      x = LOWORD (lParam) ; 
450      y = HIWORD (lParam) ; 
451      n=(Taille > 15 ? 15 : max(3,Taille)); 
452      n=(n%2==0 ? n+1 : n); 
453   
454      if(x<7 || y<3 || x>=277 || y>273) 
455        break; 
456      for(i=-n/2;i<=n/2;i++) 
457        for(j=-n/2;j<=n/2;j++) 
458          if(x>137+18*i && x<155+18*i && y>137+18*j && y<155+18*j) 
459          { 
460            Tab[i+7+(j+7)*15]=!Tab[i+7+(j+7)*15]; 
461            SetRect(&rect,137+18*i,137+18*j,155+18*i,155+18*j); 
462            InvalidateRect(hDlg,&rect,TRUE); 
463          } 
464      break; 
465   
466    case WM_COMMAND: 
467      if (LOWORD(wParam) == IDOK){ 
468        bool Noyau[225]; 
469        int ind,Src,Dest; 
470   
471        for(i=0;i<225;i++) 
472          Struct[i]=Tab[i]; 
473   
474        GetDlgItemText(hDlg, IDC_EDIT_MOR_TAILLE, szBuf, 5); 
475        Taille=atoi(szBuf); 
476        n=(Taille > 15 ? 15 : max(3,Taille)); 
477        n=(n%2==0 ? n+1 : n); 
478        StructLenght=n; 
479        GetDlgItemText(hDlg, IDC_EDIT_MOR_DEST,szBuf,5); 
480        Dest=atoi(szBuf)-1; 
481        GetDlgItemText(hDlg, IDC_EDIT_MOR_SRC,szBuf,5); 
482        Src=atoi(szBuf)-1; 
483   
484   
485        ind=0; 
486   
487        for(i=0;i<15;i++) 
488          for(j=0;j<15;j++) 
489          { 
490   
491            if(i>=7-n/2 && i<=7+n/2 && j>=7-n/2 && j<=7+n/2) 
492              Noyau[ind++]=Tab[i+j*15]; 
493          } 
494   
495        if(IsDlgButtonChecked(hDlg, IDC_RADIO_MOR_SOMBRE) == BST_CHECKED) 
496          BordClair=0; 
497        else BordClair=1; 
498        switch(SendDlgItemMessage(hDlg,IDC_COMBO_MOR,CB_GETCURSEL,0,0)) 
499        { 
500        case 0:Img[Src].Erosion(Noyau,StructLenght*StructLenght,BordClair,&Img[Dest]);break; 
501        case 1:Img[Src].Dilatation(Noyau,StructLenght*StructLenght,BordClair,&Img[Dest]);break; 
502        case 2:Img[Src].Ouverture(Noyau,StructLenght*StructLenght,BordClair,&Img[Dest]);break; 
503        case 3:Img[Src].Fermeture(Noyau,StructLenght*StructLenght,BordClair,&Img[Dest]);break; 
504        case 4:Img[Src].BlackTopHat(Noyau,StructLenght*StructLenght,BordClair,&Img[Dest]);break; 
505        case 5:Img[Src].WhiteTopHat(Noyau,StructLenght*StructLenght,BordClair,&Img[Dest]);break; 
506        case 6:Img[Src].GradientMor(Noyau,StructLenght*StructLenght,BordClair,&Img[Dest]);break; 
507        } 
508   
509        EndDialog (hDlg, Dest); 
510      } 
511   
512      if (LOWORD(wParam) == IDCANCEL){ 
513        EndDialog (hDlg, -1); 
514   
515      } 
516      if(LOWORD(wParam)==IDC_BUTTON_MOR_VIDER){ 
517        for(i=0;i<225;i++) 
518          Tab[i]=0; 
519        SetRect(&rect,7,3,285,280); 
520        InvalidateRect(hDlg,&rect,TRUE); 
521      } 
522      if(LOWORD(wParam)==IDC_BUTTON_MOR_REMPLIR){ 
523        for(i=0;i<225;i++) 
524          Tab[i]=1; 
525        SetRect(&rect,7,3,285,280); 
526        InvalidateRect(hDlg,&rect,TRUE); 
527        } 
528      return FALSE; 
529   
530    default: 
531   
532      GetDlgItemText(hDlg, IDC_EDIT_MOR_TAILLE, szBuf, 5); 
533      if(Taille!=atoi(szBuf)){ 
534        Taille=atoi(szBuf); 
535        InvalidateRect(hDlg,NULL,TRUE); 
536        //SetDlgItemInt(hDlg, IDC_EDIT_MOR_TAILLE, Taille, FALSE); 
537   
538      } 
539      return FALSE; 
540    } 
541   
542    return 0; 
543  } 

lien1 lien2 lien3