1. 程式人生 > >數字影象處理中結構元素、腐蝕、膨脹的基本概念。(轉+源)

數字影象處理中結構元素、腐蝕、膨脹的基本概念。(轉+源)

重建操作

       重建操作分為很多種,包括重建開操作、重建頂帽操作等。其根本原理是通過腐蝕找到SE的模式,然後迭代膨脹或者迭代頂帽操作直到影象收斂。

程式碼

  1. #include <cv.h>
  2. #include <highgui.h>
  3. #include <stdio.h>
  4. #define TOFINDMAX 0
  5. #define TOFINDMIN 1
  6. #define isSIZEEQU(x,y) (((x)->width)==((y)->width)&&((x)->height)==((y)->height))
  7. struct
     position{  
  8.     int x;  
  9.     int y;  
  10. };  
  11. typedefstruct position Position;  
  12. //判斷結構元是否平滑
  13. int isSmooth(IplImage *src){  
  14.     int width=src->width;  
  15.     int height=src->height;  
  16.     for(int i=0;i<width;i++)  
  17.         for(int j=0;j<height;j++){  
  18.             int v=cvGetReal2D(src,j,i);  
  19.             if
    (v!=255.0&&v!=0.0)  
  20.                 return 0;  
  21.         }  
  22.     return 1;  
  23. }  
  24. //判斷兩幅影象是否相等
  25. int isEqu(IplImage *src1,IplImage *src2){  
  26.     if(!isSIZEEQU(src1, src2))  
  27.         return 0;  
  28.     for(int i=0;i<src1->width;i++)  
  29.         for(int j=0;j<src1->height;j++){  
  30.             double v1=cvGetReal2D(src1, j, i);  
  31.             double v2=cvGetReal2D(src2, j, i);  
  32.             if(v1!=v2)  
  33.                 return 0;  
  34.         }  
  35.     return 1;  
  36. }  
  37. //將影象全部設定為1
  38. void One(IplImage *src){  
  39.     int width=src->width;  
  40.     int height=src->height;  
  41.     for(int i=0;i<width;i++)  
  42.         for(int j=0;j<height;j++)  
  43.             cvSetReal2D(src, j, i, 255.0);  
  44. }  
  45. //位移,如果非平滑SE將加上sevalue,即對應的灰度值
  46. void Translation(IplImage *src ,IplImage *dst,double SEvalue,Position *d,int istoFindMin){  
  47.     IplImage *temp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  48.     int srcwidth=src->width;  
  49.     int srcheight=src->height;  
  50.     int dstwidth=dst->width;  
  51.     int dstheight=dst->height;  
  52.     if(istoFindMin)  
  53.         One(temp);  
  54.     else
  55.         cvZero(temp);  
  56.     for(int i=0;i<srcwidth;i++){  
  57.         for(int j=0;j<srcheight;j++){  
  58.             int target_x=i+d->x;  
  59.             int target_y=j+d->y;  
  60.             if(target_x>=0&&target_y>=0&&  
  61.                target_x<dstwidth&&target_y<dstheight){  
  62.                 double value=cvGetReal2D(src, j, i)+SEvalue;  
  63.                 value=(value>=255.0?255.0:value);  
  64.                 cvSetReal2D(temp, target_y, target_x, value);  
  65.             }  
  66.         }  
  67.     }  
  68.     cvCopy(temp, dst, NULL);  
  69.     cvReleaseImage(&temp);  
  70. }  
  71. //找出兩幅等大影象中同一位置中相對較大的畫素值
  72. void MaxPix(IplImage *src1 ,IplImage *src2,IplImage *dst){  
  73.     if(!isSIZEEQU(src1, src2)||!isSIZEEQU(src1, dst)){  
  74.         printf("MaxPix wrong: src size not equ!\n");  
  75.         exit(1);  
  76.     }  
  77.     int width=src1->width;  
  78.     int height=src1->height;  
  79.     for(int i=0;i<width;i++)  
  80.         for(int j=0;j<height;j++){  
  81.             double value1=cvGetReal2D(src1, j,i);  
  82.             double value2=cvGetReal2D(src2, j,i);  
  83.             value1>value2?cvSetReal2D(dst, j,i,value1):cvSetReal2D(dst, j, i, value2);  
  84.         }  
  85. }  
  86. //找出兩幅等大影象中同一位置中相對較小的畫素值
  87. void MinPix(IplImage *src1 ,IplImage *src2,IplImage *dst){  
  88.     if(!isSIZEEQU(src1, src2)||!isSIZEEQU(src1, dst)){  
  89.         printf("MaxPix wrong: src size not equ!\n");  
  90.         exit(1);  
  91.     }  
  92.     int width=src1->width;  
  93.     int height=src1->height;  
  94.     for(int i=0;i<width;i++)  
  95.         for(int j=0;j<height;j++){  
  96.             double value1=cvGetReal2D(src1, j,i);  
  97.             double value2=cvGetReal2D(src2, j,i);  
  98.             value1<value2?cvSetReal2D(dst, j, i, value1):cvSetReal2D(dst, j, i, value2);  
  99.         }  
  100. }  
  101. //灰度影象膨脹
  102. void Dilate_Gray(IplImage *src,IplImage *dst,IplImage *se,Position *center){  
  103.     int SEissmooth=isSmooth(se);  
  104.     IplImage *temp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  105.     IplImage *temp_last=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  106.     Position centerde;  
  107.     centerde.x=se->width/2;  
  108.     centerde.y=se->height/2;  
  109.     if(center==NULL){  
  110.         center=¢erde;  
  111.     }  
  112.     int sewidth=se->width;  
  113.     int seheight=se->height;  
  114.     cvCopy(src,temp_last,NULL);  
  115.     for(int i=0;i<sewidth;i++)  
  116.         for(int j=0;j<seheight;j++){  
  117.             cvCopy(src,temp,NULL);  
  118.             double value=cvGetReal2D(se, j, i);  
  119.             if(value!=0.0){  
  120.                 Position d;  
  121.                 d.x=center->x-i;  
  122.                 d.y=center->y-j;  
  123.                 if(SEissmooth)  
  124.                     Translation(temp, temp, 0.0, &d,TOFINDMAX);  
  125.                 else
  126.                     Translation(temp, temp, value, &d,TOFINDMAX);  
  127.                 MaxPix(temp, temp_last, temp_last);  
  128.             }  
  129.         }  
  130.     cvCopy(temp_last, dst, NULL);  
  131.     cvReleaseImage(&temp);  
  132.     cvReleaseImage(&temp_last);  
  133. }  
  134. //灰度影象腐蝕
  135. void Erode_Gray(IplImage *src,IplImage *dst,IplImage *se,Position *center){  
  136.     int SEissmooth=isSmooth(se);  
  137.     IplImage *temp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  138.     IplImage *temp_last=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  139.     Position centerde;  
  140.     centerde.x=se->width/2;  
  141.     centerde.y=se->height/2;  
  142.     if(center==NULL){  
  143.         center=¢erde;  
  144.     }  
  145.     int sewidth=se->width;  
  146.     int seheight=se->height;  
  147.     cvCopy(src,temp_last,NULL);  
  148.     for(int i=0;i<sewidth;i++)  
  149.         for(int j=0;j<seheight;j++){  
  150.             cvCopy(src,temp,NULL);  
  151.             double value=cvGetReal2D(se, j, i);  
  152.             if(value!=0.0){  
  153.                 Position d;  
  154.                 d.x=i-center->x;  
  155.                 d.y=j-center->y;  
  156.                 if(SEissmooth)  
  157.                     Translation(temp, temp, 0.0, &d,TOFINDMIN);  
  158.                 else
  159.                     Translation(temp, temp, -1.0*value, &d,TOFINDMIN);  
  160.                 MinPix(temp, temp_last, temp_last);  
  161.             }  
  162.         }  
  163.     cvCopy(temp_last, dst, NULL);  
  164.     cvReleaseImage(&temp);  
  165.     cvReleaseImage(&temp_last);  
  166. }  
  167. //開操作
  168. void Open_Gray(IplImage *src,IplImage *dst,IplImage *se,Position *center){  
  169.     IplImage *temp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  170.     Erode_Gray(src, temp, se, center);  
  171.     Dilate_Gray(temp, temp, se, center);  
  172.     cvCopy(temp, dst, NULL);  
  173.     cvReleaseImage(&temp);  
  174. }  
  175. //閉操作
  176. void Close_Gray(IplImage *src,IplImage *dst,IplImage *se,Position *center){  
  177.     IplImage *temp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  178.     Dilate_Gray(src, temp, se, center);  
  179.     Erode_Gray(temp, temp, se, center);  
  180.     cvCopy(temp, dst, NULL);  
  181.     cvReleaseImage(&temp);  
  182. }  
  183. //灰度梯度形態學提取
  184. void Gard_Gray(IplImage *src,IplImage *dst,IplImage *se,Position *center){  
  185.     IplImage *temp_dilate=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  186.     IplImage *temp_erode=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  187.     Dilate_Gray(src, temp_dilate, se, center);  
  188.     Erode_Gray(src, temp_erode, se, center);  
  189.     cvSub(temp_dilate, temp_erode, dst, NULL);  
  190.     cvReleaseImage(&temp_erode);  
  191.     cvReleaseImage(&temp_dilate);  
  192. }  
  193. //頂帽操作
  194. void TopHat(IplImage *src,IplImage *dst,IplImage *se,Position *center){  
  195.     IplImage *temp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  196.     Open_Gray(src, temp, se, center);  
  197.     cvSub( src,temp, dst, NULL);  
  198.     cvReleaseImage(&temp);  
  199. }  
  200. //底帽操作
  201. void BottomHat(IplImage *src,IplImage *dst,IplImage *se,Position *center){  
  202.     IplImage *temp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  203.     Close_Gray(src, temp, se, center);  
  204.     cvSub(temp,src, dst, NULL);  
  205.     cvReleaseImage(&temp);  
  206. }  
  207. //測地腐蝕
  208. void Erode_Gray_g(IplImage *src,IplImage *ground,IplImage *dst,IplImage *se,Position *center){  
  209.     int SEissmooth=isSmooth(se);  
  210.     IplImage *temp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  211.     IplImage *temp_last=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  212.     Position centerde;  
  213.     centerde.x=se->width/2;  
  214.     centerde.y=se->height/2;  
  215.     if(center==NULL){  
  216.         center=¢erde;  
  217.     }  
  218.     int sewidth=se->width;  
  219.     int seheight=se->height;  
  220.     cvCopy(src,temp_last,NULL);  
  221.     for(int i=0;i<sewidth;i++)  
  222.         for(int j=0;j<seheight;j++){  
  223.             cvCopy(src,temp,NULL);  
  224.             double value=cvGetReal2D(se, j, i);  
  225.             if(value!=0.0){  
  226.                 Position d;  
  227.                 d.x=i-center->x;  
  228.                 d.y=j-center->y;  
  229.                 if(SEissmooth)  
  230.                     Translation(temp, temp, 0.0, &d,TOFINDMIN);  
  231.                 else
  232.                     Translation(temp, temp, -1.0*value, &d,TOFINDMIN);  
  233.                 MinPix(temp, temp_last, temp_last);  
  234.             }  
  235.         }  
  236.     MaxPix(temp_last,ground,temp_last);  
  237.     cvCopy(temp_last, dst, NULL);  
  238.     cvReleaseImage(&temp);  
  239.     cvReleaseImage(&temp_last);  
  240. }  
  241. //測地膨脹
  242. void Dilate_Gray_g(IplImage *src,IplImage *ground,IplImage *dst,IplImage *se,Position *center){  
  243.     int SEissmooth=isSmooth(se);  
  244.     IplImage *temp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  245.     IplImage *temp_last=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  246.     Position centerde;  
  247.     centerde.x=se->width/2;  
  248.     centerde.y=se->height/2;  
  249.     if(center==NULL){  
  250.         center=¢erde;  
  251.     }  
  252.     int sewidth=se->width;  
  253.     int seheight=se->height;  
  254.     cvCopy(src,temp_last,NULL);  
  255.     for(int i=0;i<sewidth;i++)  
  256.         for(int j=0;j<seheight;j++){  
  257.             cvCopy(src,temp,NULL);  
  258.             double value=cvGetReal2D(se, j, i);  
  259.             if(value!=0.0){  
  260.                 Position d;  
  261.                 d.x=center->x-i;  
  262.                 d.y=center->y-j;  
  263.                 if(SEissmooth)  
  264.                     Translation(temp, temp, 0.0, &d,TOFINDMAX);  
  265.                 else
  266.                     Translation(temp, temp, value, &d,TOFINDMAX);  
  267.                 MaxPix(temp, temp_last, temp_last);  
  268.             }  
  269.         }  
  270.     MinPix(temp_last, ground, temp_last);  
  271.     cvCopy(temp_last, dst, NULL);  
  272.     cvReleaseImage(&temp);  
  273.     cvReleaseImage(&temp_last);  
  274. }  
  275. //重建開操作
  276. void Rebuild_Open(IplImage *src,IplImage *dst,IplImage *ground,IplImage *erodeSE,IplImage *dilateSE,int eroden){  
  277.     IplImage *temp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  278.     IplImage *temp_last=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  279.     cvCopy(src, temp, NULL);  
  280.     for(int i=0;i<eroden;i++){  
  281.         Erode_Gray(temp, temp, erodeSE, NULL);  
  282.     }  
  283.     while(!isEqu(temp, temp_last)){  
  284.         cvCopy(temp, temp_last, NULL);  
  285.         Dilate_Gray_g(temp, ground, temp, dilateSE, NULL);  
  286.     }  
  287.     cvCopy(temp, dst, NULL);  
  288.     cvReleaseImage(&temp);  
  289.     cvReleaseImage(&temp_last);  
  290. }  
  291. //重建閉操作,這段沒測試
  292. void Rebuild_Close(IplImage *src,IplImage *dst,IplImage *ground,IplImage *dilateSE,IplImage *erodeSE,int dilaten){  
  293.     IplImage *temp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  294.     IplImage *temp_last=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  295.     cvCopy(src, temp, NULL);  
  296.     for(int i=0;i<dilaten;i++){  
  297.         Dilate_Gray(temp, temp, dilateSE, NULL);  
  298.     }  
  299.     while(!isEqu(temp, temp_last)){  
  300.         cvCopy(temp, temp_last, NULL);  
  301.         Erode_Gray(temp, temp, erodeSE, NULL);  
  302.         MinPix(temp, ground, temp);  
  303.     }  
  304.     cvCopy(temp, dst, NULL);  
  305.     cvReleaseImage(&temp);  
  306.     cvReleaseImage(&temp_last);  
  307. }  
  308. //重建頂帽操作
  309. void Rebuild_Tophat(IplImage *src,IplImage *dst,IplImage *ground,IplImage *dilateSE,IplImage *erodeSE,int eroden){  
  310.     Rebuild_Open(src,dst,ground,erodeSE,dilateSE,eroden);  
  311.     cvSub(src, dst, dst, NULL);  
  312. }  
  313. //重建底帽操作
  314. void Rebuild_Bottomhat(IplImage *src,IplImage *dst,IplImage *ground,IplImage *dilateSE,IplImage *erodeSE,int dilaten){  
  315.     Rebuild_Close(src,dst,ground,dilateSE,erodeSE,dilaten);  
  316.     cvSub(src, dst, dst, NULL);  
  317. }  
  318. int main(){  
  319.     return 1;  
  320. }  

結果圖片:

       以下結果原圖為lena 512x512的影象產生: 腐蝕:
膨脹:
開操作:
閉操作:
頂帽操作:
底帽操作:
重建操作示意(岡薩雷斯 中文第三版 P437): 去除橫向亮條:重建頂帽操作
重建開操作,去除縱向亮紋:
上圖橫向膨脹:
膨脹結果與重建頂帽操作的最小操作:
原圖對比:
程式碼
[cpp] view plain copy

    #include <cv.h>  
    #include <highgui.h>  
    #include <stdio.h>  
    #define TOFINDMAX 0  
    #define TOFINDMIN 1  
    #define isSIZEEQU(x,y) (((x)->width)==((y)->width)&&((x)->height)==((y)->height))  
    struct position{  
        int x;  
        int y;  
    };  
    typedef struct position Position;  
    //判斷結構元是否平滑  
    int isSmooth(IplImage *src){  
        int width=src->width;  
        int height=src->height;  
        for(int i=0;i<width;i++)  
            for(int j=0;j<height;j++){  
                int v=cvGetReal2D(src,j,i);  
                if(v!=255.0&&v!=0.0)  
                    return 0;  
            }  
        return 1;  
    }  
    //判斷兩幅影象是否相等  
    int isEqu(IplImage *src1,IplImage *src2){  
        if(!isSIZEEQU(src1, src2))  
            return 0;  
        for(int i=0;i<src1->width;i++)  
            for(int j=0;j<src1->height;j++){  
                double v1=cvGetReal2D(src1, j, i);  
                double v2=cvGetReal2D(src2, j, i);  
                if(v1!=v2)  
                    return 0;  
            }  
        return 1;  
      
    }  
    //將影象全部設定為1  
    void One(IplImage *src){  
        int width=src->width;  
        int height=src->height;  
        for(int i=0;i<width;i++)  
            for(int j=0;j<height;j++)  
                cvSetReal2D(src, j, i, 255.0);  
      
      
    }  
    //位移,如果非平滑SE將加上sevalue,即對應的灰度值  
    void Translation(IplImage *src ,IplImage *dst,double SEvalue,Position *d,int istoFindMin){  
        IplImage *temp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
        int srcwidth=src->width;  
        int srcheight=src->height;  
        int dstwidth=dst->width;  
        int dstheight=dst->height;  
        if(istoFindMin)  
            One(temp);  
        else  
            cvZero(temp);  
        for(int i=0;i<srcwidth;i++){  
            for(int j=0;j<srcheight;j++){  
                int target_x=i+d->x;  
                int target_y=j+d->y;  
                if(target_x>=0&&target_y>=0&&  
                   target_x<dstwidth&&target_y<dstheight){  
                    double value=cvGetReal2D(src, j, i)+SEvalue;  
                    value=(value>=255.0?255.0:value);  
                    cvSetReal2D(temp, target_y, target_x, value);  
                }  
            }  
        }  
        cvCopy(temp, dst, NULL);  
          
        cvReleaseImage(&temp);  
    }  
    //找出兩幅等大影象中同一位置中相對較大的畫素值  
    void MaxPix(IplImage *src1 ,IplImage *src2,IplImage *dst){  
        if(!isSIZEEQU(src1, src2)||!isSIZEEQU(src1, dst)){  
            printf("MaxPix wrong: src size not equ!\n");  
            exit(1);  
        }  
        int width=src1->width;  
        int height=src1->height;  
        for(int i=0;i<width;i++)  
            for(int j=0;j<height;j++){  
                double value1=cvGetReal2D(src1, j,i);  
                double value2=cvGetReal2D(src2, j,i);  
                value1>value2?cvSetReal2D(dst, j,i,value1):cvSetReal2D(dst, j, i, value2);  
            }  
      
    }  
    //找出兩幅等大影象中同一位置中相對較小的畫素值  
    void MinPix(IplImage *src1 ,IplImage *src2,IplImage *dst){  
        if(!isSIZEEQU(src1, src2)||!isSIZEEQU(src1, dst)){  
            printf("MaxPix wrong: src size not equ!\n");  
            exit(1);  
        }  
        int width=src1->width;  
        int height=src1->height;  
        for(int i=0;i<width;i++)  
            for(int j=0;j<height;j++){  
                double value1=cvGetReal2D(src1, j,i);  
                double value2=cvGetReal2D(src2, j,i);  
                value1<value2?cvSetReal2D(dst, j, i, value1):cvSetReal2D(dst, j, i, value2);  
            }  
          
    }  
    //灰度影象膨脹  
    void Dilate_Gray(IplImage *src,IplImage *dst,IplImage *se,Position *center){  
        int SEissmooth=isSmooth(se);  
        IplImage *temp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
        IplImage *temp_last=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
        Position centerde;  
        centerde.x=se->width/2;  
        centerde.y=se->height/2;  
        if(center==NULL){  
            center=¢erde;  
        }  
        int sewidth=se->width;  
        int seheight=se->height;  
        cvCopy(src,temp_last,NULL);  
        for(int i=0;i<sewidth;i++)  
            for(int j=0;j<seheight;j++){  
                cvCopy(src,temp,NULL);  
                double value=cvGetReal2D(se, j, i);  
                if(value!=0.0){  
                    Position d;  
                    d.x=center->x-i;  
                    d.y=center->y-j;  
                    if(SEissmooth)  
                        Translation(temp, temp, 0.0, &d,TOFINDMAX);  
                    else  
                        Translation(temp, temp, value, &d,TOFINDMAX);  
                    MaxPix(temp, temp_last, temp_last);  
                }  
            }  
        cvCopy(temp_last, dst, NULL);  
        cvReleaseImage(&temp);  
        cvReleaseImage(&temp_last);  
      
    }  
    //灰度影象腐蝕  
    void Erode_Gray(IplImage *src,IplImage *dst,IplImage *se,Position *center){  
        int SEissmooth=isSmooth(se);  
        IplImage *temp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
        IplImage *temp_last=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
        Position centerde;  
        centerde.x=se->width/2;  
        centerde.y=se->height/2;  
        if(center==NULL){  
            center=¢erde;  
        }  
        int sewidth=se->width;  
        int seheight=se->height;  
        cvCopy(src,temp_last,NULL);  
        for(int i=0;i<sewidth;i++)  
            for(int j=0;j<seheight;j++){  
                cvCopy(src,temp,NULL);  
                double value=cvGetReal2D(se, j, i);  
                if(value!=0.0){  
                    Position d;  
                      
                    d.x=i-center->x;  
                    d.y=j-center->y;  
                    if(SEissmooth)  
                        Translation(temp, temp, 0.0, &d,TOFINDMIN);  
                    else  
                        Translation(temp, temp, -1.0*value, &d,TOFINDMIN);  
                    MinPix(temp, temp_last, temp_last);  
                      
                }  
            }  
        cvCopy(temp_last, dst, NULL);  
        cvReleaseImage(&temp);  
        cvReleaseImage(&temp_last);  
          
    }  
    //開操作  
    void Open_Gray(IplImage *src,IplImage *dst,IplImage *se,Position *center){  
        IplImage *temp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
        Erode_Gray(src, temp, se, center);  
        Dilate_Gray(temp, temp, se, center);  
        cvCopy(temp, dst, NULL);  
        cvReleaseImage(&temp);  
      
    }  
    //閉操作  
    void Close_Gray(IplImage *src,IplImage *dst,IplImage *se,Position *center){  
        IplImage *temp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
        Dilate_Gray(src, temp, se, center);  
        Erode_Gray(temp, temp, se, center);  
        cvCopy(temp, dst, NULL);  
        cvReleaseImage(&temp);  
          
    }  
    //灰度梯度形態學提取  
    void Gard_Gray(IplImage *src,IplImage *dst,IplImage *se,Position *center){  
        IplImage *temp_dilate=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
        IplImage *temp_erode=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
        Dilate_Gray(src, temp_dilate, se, center);  
        Erode_Gray(src, temp_erode, se, center);  
        cvSub(temp_dilate, temp_erode, dst, NULL);  
        cvReleaseImage(&temp_erode);  
        cvReleaseImage(&temp_dilate);  
      
      
    }  
    //頂帽操作  
    void TopHat(IplImage *src,IplImage *dst,IplImage *se,Position *center){  
        IplImage *temp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
        Open_Gray(src, temp, se, center);  
        cvSub( src,temp, dst, NULL);  
        cvReleaseImage(&temp);  
      
    }  
    //底帽操作  
    void BottomHat(IplImage *src,IplImage *dst,IplImage *se,Position *center){  
        IplImage *temp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
        Close_Gray(src, temp, se, center);  
        cvSub(temp,src, dst, NULL);  
        cvReleaseImage(&temp);  
          
    }  
    //測地腐蝕  
    void Erode_Gray_g(IplImage *src,IplImage *ground,IplImage *dst,IplImage *se,Position *center){  
        int SEissmooth=isSmooth(se);  
        IplImage *temp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
        IplImage *temp_last=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
        Position centerde;  
        centerde.x=se->width/2;  
        centerde.y=se->height/2;  
        if(center==NULL){  
            center=¢erde;  
        }  
        int sewidth=se->width;  
        int seheight=se->height;  
        cvCopy(src,temp_last,NULL);  
        for(int i=0;i<sewidth;i++)  
            for(int j=0;j<seheight;j++){  
                cvCopy(src,temp,NULL);  
                double value=cvGetReal2D(se, j, i);  
                if(value!=0.0){  
                    Position d;  
                      
                    d.x=i-center->x;  
                    d.y=j-center->y;  
                    if(SEissmooth)  
                        Translation(temp, temp, 0.0, &d,TOFINDMIN);  
                    else  
                        Translation(temp, temp, -1.0*value, &d,TOFINDMIN);  
                    MinPix(temp, temp_last, temp_last);  
                      
                }  
            }  
        MaxPix(temp_last,ground,temp_last);  
        cvCopy(temp_last, dst, NULL);  
        cvReleaseImage(&temp);  
        cvReleaseImage(&temp_last);  
      
      
    }  
    //測地膨脹  
    void Dilate_Gray_g(IplImage *src,IplImage *ground,IplImage *dst,IplImage *se,Position *center){  
        int SEissmooth=isSmooth(se);  
        IplImage *temp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
        IplImage *temp_last=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
        Position centerde;  
        centerde.x=se->width/2;  
        centerde.y=se->height/2;  
        if(center==NULL){  
            center=¢erde;  
        }  
        int sewidth=se->width;  
        int seheight=se->height;  
        cvCopy(src,temp_last,NULL);  
        for(int i=0;i<sewidth;i++)  
            for(int j=0;j<seheight;j++){  
                cvCopy(src,temp,NULL);  
                double value=cvGetReal2D(se, j, i);  
                if(value!=0.0){  
                    Position d;  
                    d.x=center->x-i;  
                    d.y=center->y-j;  
                    if(SEissmooth)  
                        Translation(temp, temp, 0.0, &d,TOFINDMAX);  
                    else  
                        Translation(temp, temp, value, &d,TOFINDMAX);  
                    MaxPix(temp, temp_last, temp_last);  
                }  
            }  
        MinPix(temp_last, ground, temp_last);  
        cvCopy(temp_last, dst, NULL);  
        cvReleaseImage(&temp);  
        cvReleaseImage(&temp_last);  
    }  
    //重建開操作  
    void Rebuild_Open(IplImage *src,IplImage *dst,IplImage *ground,IplImage *erodeSE,IplImage *dilateSE,int eroden){  
        IplImage *temp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
        IplImage *temp_last=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
        cvCopy(src, temp, NULL);  
        for(int i=0;i<eroden;i++){  
            Erode_Gray(temp, temp, erodeSE, NULL);  
        }  
          
        while(!isEqu(temp, temp_last)){  
            cvCopy(temp, temp_last, NULL);  
            Dilate_Gray_g(temp, ground, temp, dilateSE, NULL);  
              
        }  
        cvCopy(temp, dst, NULL);  
        cvReleaseImage(&temp);  
        cvReleaseImage(&temp_last);  
          
    }  
    //重建閉操作,這段沒測試  
    void Rebuild_Close(IplImage *src,IplImage *dst,IplImage *ground,IplImage *dilateSE,IplImage *erodeSE,int dilaten){  
        IplImage *temp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
        IplImage *temp_last=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
        cvCopy(src, temp, NULL);  
        for(int i=0;i<dilaten;i++){  
            Dilate_Gray(temp, temp, dilateSE, NULL);  
        }  
          
        while(!isEqu(temp, temp_last)){  
            cvCopy(temp, temp_last, NULL);  
            Erode_Gray(temp, temp, erodeSE, NULL);  
            MinPix(temp, ground, temp);  
              
        }  
        cvCopy(temp, dst, NULL);  
        cvReleaseImage(&temp);  
        cvReleaseImage(&temp_last);  
          
    }  
    //重建頂帽操作  
    void Rebuild_Tophat(IplImage *src,IplImage *dst,IplImage *ground,IplImage *dilateSE,IplImage *erodeSE,int eroden){  
        Rebuild_Open(src,dst,ground,erodeSE,dilateSE,eroden);  
        cvSub(src, dst, dst, NULL);  
      
    }  
    //重建底帽操作  
    void Rebuild_Bottomhat(IplImage *src,IplImage *dst,IplImage *ground,IplImage *dilateSE,IplImage *erodeSE,int dilaten){  
        Rebuild_Close(src,dst,ground,dilateSE,erodeSE,dilaten);  
        cvSub(src, dst, dst, NULL);  
          
    }  
    int main(){  
          
        return 1;  
      
    }  


結果圖片:
       以下結果原圖為lena 512x512的影象產生:
腐蝕:

膨脹:

開操作:

閉操作:

頂帽操作:

底帽操作:



重建操作示意(岡薩雷斯 中文第三版 P437):
去除橫向亮條:重建頂帽操作

重建開操作,去除縱向亮紋:

上圖橫向膨脹:

膨脹結果與重建頂帽操作的最小操作:

原圖對比:


程式碼
  1. #include <cv.h>
  2. #include <highgui.h>
  3. #include <stdio.h>
  4. #define TOFINDMAX 0
  5. #define TOFINDMIN 1
  6. #define isSIZEEQU(x,y) (((x)->width)==((y)->width)&&((x)->height)==((y)->height))
  7. struct position{  
  8.     int x;  
  9.     int y;  
  10. };  
  11. typedefstruct position Position;  
  12. //判斷結構元是否平滑
  13. int isSmooth(IplImage *src){  
  14.     int width=src->width;  
  15.     int height=src->height;  
  16.     for(int i=0;i<width;i++)  
  17.         for(int j=0;j<height;j++){  
  18.             int v=cvGetReal2D(src,j,i);  
  19.             if(v!=255.0&&v!=0.0)  
  20.                 return 0;  
  21.         }  
  22.     return 1;  
  23. }  
  24. //判斷兩幅影象是否相等
  25. int isEqu(IplImage *src1,IplImage *src2){  
  26.     if(!isSIZEEQU(src1, src2))  
  27.         return 0;  
  28.     for(int i=0;i<src1->width;i++)  
  29.         for(int j=0;j<src1->height;j++){  
  30.             double v1=cvGetReal2D(src1, j, i);  
  31.             double v2=cvGetReal2D(src2, j, i);  
  32.             if(v1!=v2)  
  33.                 return 0;  
  34.         }  
  35.     return 1;  
  36. }  
  37. //將影象全部設定為1
  38. void One(IplImage *src){  
  39.     int width=src->width;  
  40.     int height=src->height;  
  41.     for(int i=0;i<width;i++)  
  42.         for(int j=0;j<height;j++)  
  43.             cvSetReal2D(src, j, i, 255.0);  
  44. }  
  45. //位移,如果非平滑SE將加上sevalue,即對應的灰度值
  46. void Translation(IplImage *src ,IplImage *dst,double SEvalue,Position *d,int istoFindMin){  
  47.     IplImage *temp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  48.     int srcwidth=src->width;  
  49.     int srcheight=src->height;  
  50.     int dstwidth=dst->width;  
  51.     int dstheight=dst->height;  
  52.     if(istoFindMin)  
  53.         One(temp);  
  54.     else
  55.         cvZero(temp);  
  56.     for(int i=0;i<srcwidth;i++){  
  57.         for(int j=0;j<srcheight;j++){  
  58.             int target_x=i+d->x;  
  59.             int target_y=j+d->y;  
  60.             if(target_x>=0&&target_y>=0&&  
  61.                target_x<dstwidth&&target_y<dstheight){  
  62.                 double value=cvGetReal2D(src, j, i)+SEvalue;  
  63.                 value=(value>=255.0?255.0:value);  
  64.                 cvSetReal2D(temp, target_y, target_x, value);  
  65.             }  
  66.         }  
  67.     }  
  68.     cvCopy(temp, dst, NULL);  
  69.     cvReleaseImage(&temp);  
  70. }  
  71. //找出兩幅等大影象中同一位置中相對較大的畫素值
  72. void MaxPix(IplImage *src1 ,IplImage *src2,IplImage *dst){  
  73.     if(!isSIZEEQU(src1, src2)||!isSIZEEQU(src1, dst)){  
  74.         printf("MaxPix wrong: src size not equ!\n");  
  75.         exit(1);  
  76.     }  
  77.     int width=src1->width;  
  78.     int height=src1->height;  
  79.     for(int i=0;i<width;i++)  
  80.         for(int j=0;j<height;j++){  
  81.             double value1=cvGetReal2D(src1, j,i);  
  82.             double value2=cvGetReal2D(src2, j,i);  
  83.             value1>value2?cvSetReal2D(dst, j,i,value1):cvSetReal2D(dst, j, i, value2);  
  84.         }  
  85. }  
  86. //找出兩幅等大影象中同一位置中相對較小的畫素值
  87. void MinPix(IplImage *src1 ,IplImage *src2,IplImage *dst){  
  88.     if(!isSIZEEQU(src1, src2)||!isSIZEEQU(src1, dst)){  
  89.         printf("MaxPix wrong: src size not equ!\n");  
  90.         exit(1);  
  91.     }  
  92.     int width=src1->width;  
  93.     int height=src1->height;  
  94.     for(int i=0;i<width;i++)  
  95.         for(int j=0;j<height;j++){  
  96.             double value1=cvGetReal2D(src1, j,i);  
  97.             double value2=cvGetReal2D(src2, j,i);  
  98.             value1<value2?cvSetReal2D(dst, j, i, value1):cvSetReal2D(dst, j, i, value2);  
  99.         }  
  100. }  
  101. //灰度影象膨脹
  102. void Dilate_Gray(IplImage *src,IplImage *dst,IplImage *se,Position *center){  
  103.     int SEissmooth=isSmooth(se);  
  104.     IplImage *temp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  105.     IplImage *temp_last=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  106.     Position centerde;  
  107.     centerde.x=se->width/2;  
  108.     centerde.y=se->height/2;  
  109.     if(center==NULL){  
  110.         center=¢erde;  
  111.     }  
  112.     int sewidth=se->width;  
  113.     int seheight=se->height;  
  114.     cvCopy(src,temp_last,NULL);  
  115.     for(int i=0;i<sewidth;i++)  
  116.         for(int j=0;j<seheight;j++){  
  117.             cvCopy(src,temp,NULL);  
  118.             double value=cvGetReal2D(se, j, i);  
  119.             if(value!=0.0){  
  120.                 Position d;  
  121.                 d.x=center->x-i;  
  122.                 d.y=center->y-j;  
  123.                 if(SEissmooth)  
  124.                     Translation(temp, temp, 0.0, &d,TOFINDMAX);  
  125.                 else
  126.                     Translation(temp, temp, value, &d,TOFINDMAX);  
  127.                 MaxPix(temp, temp_last, temp_last);  
  128.             }  
  129.         }  
  130.     cvCopy(temp_last, dst, NULL);  
  131.     cvReleaseImage(&temp);  
  132.     cvReleaseImage(&temp_last);  
  133. }  
  134. //灰度影象腐蝕
  135. void Erode_Gray(IplImage *src,IplImage *dst,IplImage *se,Position *center){  
  136.     int SEissmooth=isSmooth(se);  
  137.     IplImage *temp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  138.     IplImage *temp_last=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  139.     Position centerde;  
  140.     centerde.x=se->width/2;  
  141.     centerde.y=se->height/2;  
  142.     if(center==NULL){  
  143.         center=¢erde;  
  144.     }  
  145.     int sewidth=se->width;  
  146.