首页 > 代码库 > 形态学处理函数

形态学处理函数

  1. #include <cv.h>  
  2. #include <highgui.h>  
  3. #include <stdio.h>  
  4. #define isSIZEEQU(x,y) (((x)->width)==((y)->width)&&((x)->height)==((y)->height))  
  5. typedef int DataType;  
  6. struct Position_{  
  7.     int x;  
  8.     int y;  
  9. };  
  10. typedef struct Position_ Position;  
  11. typedef struct Position_ MoveDirection;  
  12. //位移操作,将图像整体移动,如果超出边界舍去  
  13. int isEqual(IplImage *src1,IplImage *src2){  
  14.     if(!isSIZEEQU(src1, src2))  
  15.         return 0;  
  16.     int width=src1->width;  
  17.     int height=src1->height;  
  18.     for(int i=0;i<width;i++)  
  19.         for(int j=0;j<height;j++){  
  20.             int v0=cvGetReal2D(src1, j, i);  
  21.             int v1=cvGetReal2D(src2, j, i);  
  22.             if(v0!=v1)  
  23.                 return 0;  
  24.         }  
  25.     return 1;  
  26. }  
  27. //检测图像是否为空  
  28. int isEmpty(IplImage *src){  
  29.     int width=src->width;  
  30.     int height=src->height;  
  31.     for(int i=0;i<width;i++)  
  32.         for(int j=0;j<height;j++){  
  33.             int v=cvGetReal2D(src, j, i);  
  34.             if(v!=0.0)  
  35.                 return 0;  
  36.         }  
  37.     return 1;  
  38. }  
  39.   
  40. void Translation(IplImage *src,IplImage *dst,MoveDirection *direction){  
  41.     int width=src->width;  
  42.     int height=src->height;  
  43.     //printf("%d,%d\n",direction->x,direction->y);  
  44.     IplImage *temp=cvCreateImage(cvSize(width, height), src->depth, src->nChannels);  
  45.     cvZero(temp);  
  46.     for(int i=0;i<width;i++)  
  47.         for(int j=0;j<height;j++){  
  48.                 if(j+direction->y<height &&  
  49.                    i+direction->x<width  &&  
  50.                    j+direction->y>=0      &&  
  51.                    i+direction->x>=0        )  
  52.                 cvSetReal2D(temp, j+direction->y, i+direction->x, cvGetReal2D(src, j, i));  
  53.               
  54.         }  
  55.     cvCopy(temp, dst, NULL);  
  56.     cvReleaseImage(&temp);  
  57. }  
  58. //将小的图像弄到大的黑色图像中间,或者说是给图像加黑色边框  
  59. void Zoom(IplImage *src,IplImage *dst){  
  60.     if(dst->width<src->width         ||  
  61.        dst->height<src->height       ||  
  62.        (dst->height-src->height)%2==1||  
  63.        (dst->width-src->width)%2==1){  
  64.         if(dst->width<src->width )  
  65.             printf("Zoom wrong:dst‘s width too small!\n");  
  66.         if(dst->height<src->height )  
  67.             printf("Zoom wrong:dst‘s height too small!\n");  
  68.         if((dst->height-src->height)%2==1||(dst->width-src->width)%2==1)  
  69.             printf("Zoom wrong:dst-src not a oushu!\n");  
  70.         exit(0);  
  71.     }  
  72.     MoveDirection m;  
  73.     m.x=(dst->width-src->width)/2;  
  74.     m.y=(dst->height-src->height)/2;  
  75.     cvZero(dst);  
  76.     for(int i=m.x,j=0;j<src->width;i++,j++){  
  77.         for(int k=m.y,n=0;n<src->height;k++,n++){  
  78.             cvSetReal2D(dst, k, i, cvGetReal2D(src, n, j));  
  79.           
  80.         }  
  81.     }  
  82.   
  83. }  
  84. //逻辑与操作  
  85. int And(IplImage *src0,IplImage *src1,IplImage *dst){  
  86.     int isChanged=0;  
  87.     if(!isSIZEEQU(src0,src1)){  
  88.         printf("And wrong !\n");  
  89.         exit(0);  
  90.     }  
  91.     if(!isSIZEEQU(src0,dst)){  
  92.         printf("And wrong !\n");  
  93.         exit(0);  
  94.     }  
  95.     int width=src0->width;  
  96.     int height=src0->height;  
  97.     for(int i=0;i<width;i++){  
  98.         for(int j=0;j<height;j++){  
  99.             if(cvGetReal2D(src0, j, i)>100.0&&  
  100.                cvGetReal2D(src1, j, i)>100.0)  
  101.                 cvSetReal2D(dst, j, i, 255.0);  
  102.             else  
  103.                 cvSetReal2D(dst, j, i, 0.0);  
  104.         }  
  105.     }  
  106.     return isChanged;  
  107. }  
  108. //逻辑或操作  
  109. void Or(IplImage *src0,IplImage *src1,IplImage *dst){  
  110.     if(!isSIZEEQU(src0,src1)){  
  111.         printf("And wrong !\n");  
  112.         exit(0);  
  113.     }  
  114.     if(!isSIZEEQU(src0,dst)){  
  115.         printf("And wrong !\n");  
  116.         exit(0);  
  117.     }  
  118.     int width=src0->width;  
  119.     int height=src0->height;  
  120.     for(int i=0;i<width;i++){  
  121.         for(int j=0;j<height;j++){  
  122.             if(cvGetReal2D(src0, j, i)>100.0||  
  123.                cvGetReal2D(src1, j, i)>100.0)  
  124.                 cvSetReal2D(dst, j, i, 255);  
  125.              
  126.         }  
  127.     }  
  128. }  
  129. //取反  
  130. void Not(IplImage *src,IplImage *dst){  
  131.      
  132.     if(!isSIZEEQU(src,dst)){  
  133.         printf("Not wrong !\n");  
  134.         exit(0);  
  135.     }  
  136.     int width=src->width;  
  137.     int height=src->height;  
  138.     for(int i=0;i<width;i++){  
  139.         for(int j=0;j<height;j++){  
  140.             cvSetReal2D(dst, j, i, 255.0-cvGetReal2D(src, j, i));  
  141.         }  
  142.     }  
  143. }  
  144. //将所有元素设为1  
  145. void One(IplImage *src){  
  146.     for(int i=0;i<src->width;i++)  
  147.         for(int j=0;j<src->height;j++)  
  148.             cvSetReal2D(src, j, i, 255.0);  
  149.   
  150.   
  151. }  
  152.   
  153. //膨胀  
  154. void Dilate(IplImage *src,IplImage *dst,IplImage *se,Position *center){  
  155.   
  156.     if(center==NULL){  
  157.         Position temp;  
  158.         temp.x=se->width/2;  
  159.         temp.y=se->height/2;  
  160.         center=&temp;  
  161.     }  
  162.     //printf("%d,%d",center->x,center->y);  
  163.     MoveDirection m;  
  164.     IplImage *temp=cvCreateImage(cvGetSize(dst), dst->depth,dst->nChannels);  
  165.     IplImage *tempdst=cvCreateImage(cvGetSize(dst), dst->depth,dst->nChannels);  
  166.     IplImage *realdst=cvCreateImage(cvGetSize(dst), dst->depth,dst->nChannels);  
  167.     cvZero(realdst);  
  168.     Zoom(src,temp);  
  169.     int width=se->width;  
  170.     int height=se->height;  
  171.     for(int i=0;i<width;i++){  
  172.         for(int j=0;j<height;j++){  
  173.             if(cvGetReal2D(se, j, i)>100.0){  
  174.                 m.x=i-center->x;  
  175.                 m.y=j-center->y;  
  176.                 Translation(temp,tempdst, &m);  
  177.                 Or(tempdst, realdst, realdst);  
  178.             }  
  179.         }  
  180.     }  
  181.       
  182.     cvCopy(realdst, dst, NULL);  
  183.     cvReleaseImage(&temp);  
  184.     cvReleaseImage(&realdst);  
  185.     cvReleaseImage(&tempdst);  
  186. }  
  187.   
  188. //腐蚀  
  189. void Erode(IplImage *src,IplImage *dst,IplImage *se,Position *center){  
  190.       
  191.      
  192.     if(center==NULL){  
  193.         Position temp;  
  194.         temp.x=se->width/2;  
  195.         temp.y=se->height/2;  
  196.         center=&temp;  
  197.     }  
  198.     MoveDirection m;  
  199.     IplImage *temp=cvCreateImage(cvGetSize(dst), dst->depth,dst->nChannels);  
  200.     IplImage *tempdst=cvCreateImage(cvGetSize(dst), dst->depth,dst->nChannels);  
  201.     IplImage *realdst=cvCreateImage(cvGetSize(dst), dst->depth,dst->nChannels);  
  202.     One(realdst);  
  203.     Zoom(src,temp);  
  204.     int width=se->width;  
  205.     int height=se->height;  
  206.     for(int i=0;i<width;i++){  
  207.         for(int j=0;j<height;j++){  
  208.             if(cvGetReal2D(se, j, i)>100.0){  
  209.                 m.x=center->x-i;  
  210.                 m.y=center->y-j;  
  211.                 Translation(temp,tempdst, &m);  
  212.                 And(tempdst, realdst, realdst);  
  213.             }  
  214.         }  
  215.     }  
  216.     cvCopy(realdst, dst, NULL);  
  217.     cvReleaseImage(&tempdst);  
  218.     cvReleaseImage(&temp);  
  219.     cvReleaseImage(&realdst);  
  220. }  
  221.   
  222. //开操作  
  223. void Open(IplImage *src,IplImage *dst,IplImage *se,Position *center){  
  224.     Erode(src, dst, se, center);  
  225.     Dilate(dst, dst, se, center);  
  226.   
  227. }  
  228. //关操作  
  229. void Close(IplImage *src,IplImage *dst,IplImage *se,Position *center){  
  230.     Dilate(src, dst, se, center);  
  231.     Erode(dst, dst, se, center);  
  232.       
  233. }  
  234. //击中与击不中  
  235. void HitorMiss(IplImage *src,IplImage *se1,IplImage *se2,IplImage *dst,Position *se1center,Position *se2center){  
  236.     IplImage *temp1=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  237.     IplImage *temp2=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  238.     Erode(src, temp1, se1, se1center);  
  239.     Not(src, temp2);  
  240.     Erode(temp2, temp2, se2, se2center);  
  241.     And(temp1, temp2, dst);  
  242.     cvReleaseImage(&temp1);  
  243.     cvReleaseImage(&temp2);  
  244. }  
  245. //二值图像,边缘检测  
  246. void BinaryEdge(IplImage *src,IplImage* dst){  
  247.     IplImage *temp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  248.     Erode(src, temp, NULL, NULL);  
  249.     cvSub(src, temp, dst, NULL);  
  250.     cvReleaseImage(&temp);  
  251. }  
  252. //孔洞填充  
  253. void FillHole(IplImage *src,IplImage *dst,IplImage *se,Position *seed){  
  254.     IplImage * temp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  255.     cvZero(temp);  
  256.     IplImage * lasttemp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  257.     IplImage * nsrc=http://www.mamicode.com/cvCreateImage(cvGetSize(src), src->depth, src->nChannels);
  258.     Not(src, nsrc);  
  259.     cvSetReal2D(temp, seed->y, seed->x, 255.0);  
  260.     while(!isEqual(lasttemp, temp)){  
  261.         cvCopy(temp, lasttemp, NULL);  
  262.         Dilate(temp, temp, se, NULL);  
  263.         And(temp, nsrc, temp);  
  264.           
  265.   
  266.           
  267.     }  
  268.     Or(temp, src, dst);  
  269.     cvReleaseImage(&temp);  
  270.     cvReleaseImage(&lasttemp);  
  271.     cvReleaseImage(&nsrc);  
  272. }  
  273. //连通分量获取  
  274. void GetConComponent(IplImage *src,IplImage *dst,IplImage *se,Position *seed){  
  275.     IplImage * temp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  276.     cvZero(temp);  
  277.     IplImage * lasttemp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  278.       
  279.     cvSetReal2D(temp, seed->y, seed->x, 255.0);  
  280.     while(!isEqual(lasttemp, temp)){  
  281.         cvCopy(temp, lasttemp, NULL);  
  282.         Dilate(temp, temp, se, NULL);  
  283.         And(temp, src, temp);  
  284.           
  285.     }  
  286.     cvCopy(temp, dst, NULL);  
  287.     cvReleaseImage(&temp);  
  288.     cvReleaseImage(&lasttemp);  
  289. }  
  290. //骨架  
  291. void FrameWork(IplImage *src,IplImage *dst,IplImage *se){  
  292.     cvZero(dst);  
  293.     IplImage *temp=cvCreateImage(cvGetSize(src), src->depth,src->nChannels);  
  294.     IplImage *temp_open=cvCreateImage(cvGetSize(src), src->depth,src->nChannels);  
  295.     cvCopy(src, temp, NULL);  
  296.     while(!isEmpty(temp)){  
  297.         Erode(temp, temp, se, NULL);  
  298.         cvCopy(temp, temp_open, NULL);  
  299.         Open(temp_open, temp_open, se, NULL);  
  300.         cvSub(temp, temp_open, temp_open,NULL);  
  301.         Or(temp_open, dst, dst);  
  302.           
  303.     }  
  304.     cvReleaseImage(&temp);  
  305.     cvReleaseImage(&temp_open);  
  306. }  
  307. //凸壳生成结构元  
  308. IplImage* CreateConvexhullSE(int num){  
  309.     IplImage *se=cvCreateImage(cvSize(3, 3), 8, 1);  
  310.     cvZero(se);  
  311.     switch (num) {  
  312.         case 0:  
  313.         {  
  314.             cvSetReal2D(se, 0, 0, 255.0);  
  315.             cvSetReal2D(se, 1, 0, 255.0);  
  316.             cvSetReal2D(se, 2, 0, 255.0);  
  317.         }  
  318.             break;  
  319.         case 1:  
  320.         {  
  321.             cvSetReal2D(se, 0, 0, 255.0);  
  322.             cvSetReal2D(se, 0, 1, 255.0);  
  323.             cvSetReal2D(se, 0, 2, 255.0);  
  324.           
  325.         }  
  326.             break;  
  327.         case 2:  
  328.         {  
  329.             cvSetReal2D(se, 0, 2, 255.0);  
  330.             cvSetReal2D(se, 1, 2, 255.0);  
  331.             cvSetReal2D(se, 2, 2, 255.0);  
  332.         }  
  333.             break;  
  334.         case 3:  
  335.         {  
  336.             cvSetReal2D(se, 2, 0, 255.0);  
  337.             cvSetReal2D(se, 2, 1, 255.0);  
  338.             cvSetReal2D(se, 2, 2, 255.0);  
  339.         }  
  340.             break;  
  341.         default:  
  342.             break;  
  343.     }  
  344.     return se;  
  345. }  
  346. //凸壳  
  347. void Convexhull(IplImage *src,IplImage *dst){  
  348.     cvCopy(src, dst, NULL);  
  349.     IplImage * se[4];  
  350.     IplImage *temp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  351.     IplImage *temp_last=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  352.     //cvCopy(src, temp, NULL);  
  353.     for(int i=0;i<4;i++){  
  354.         cvCopy(src, temp, NULL);  
  355.         se[i]=CreateConvexhullSE(i);  
  356.         while (!isEqual(temp, temp_last)) {  
  357.             cvCopy(temp, temp_last, NULL);  
  358.             Erode(temp, temp, se[i],NULL);  
  359.             Or(temp, dst, temp);  
  360.               
  361.             
  362.         }  
  363.         cvCopy(temp, dst, NULL);  
  364.         cvReleaseImage(&se[i]);  
  365.     }  
  366.     cvReleaseImage(&temp);  
  367.     cvReleaseImage(&temp_last);  
  368.   
  369. }  
  370. //生成细化结构元  
  371. IplImage* CreateThinningSE(int num){  
  372.     IplImage *se=cvCreateImage(cvSize(3, 3), 8, 1);  
  373.     cvZero(se);  
  374.     switch (num) {  
  375.         case 0:  
  376.         {  
  377.             cvSetReal2D(se, 2, 0, 255.0);  
  378.             cvSetReal2D(se, 2, 1, 255.0);  
  379.             cvSetReal2D(se, 2, 2, 255.0);  
  380.             cvSetReal2D(se, 1, 1, 255.0);  
  381.         }  
  382.             break;  
  383.         case 1:  
  384.         {  
  385.             cvSetReal2D(se, 1, 1, 255.0);  
  386.             cvSetReal2D(se, 1, 0, 255.0);  
  387.             cvSetReal2D(se, 2, 0, 255.0);  
  388.             cvSetReal2D(se, 2, 1, 255.0);  
  389.               
  390.         }  
  391.             break;  
  392.         case 2:  
  393.         {  
  394.             cvSetReal2D(se, 1, 1, 255.0);  
  395.             cvSetReal2D(se, 1, 0, 255.0);  
  396.             cvSetReal2D(se, 2, 0, 255.0);  
  397.             cvSetReal2D(se, 0, 0, 255.0);  
  398.         }  
  399.             break;  
  400.         case 3:  
  401.         {  
  402.             cvSetReal2D(se, 1, 1, 255.0);  
  403.             cvSetReal2D(se, 0, 0, 255.0);  
  404.             cvSetReal2D(se, 0, 1, 255.0);  
  405.             cvSetReal2D(se, 1, 0, 255.0);  
  406.         }  
  407.             break;  
  408.         case 4:  
  409.         {  
  410.             cvSetReal2D(se, 1, 1, 255.0);  
  411.             cvSetReal2D(se, 0, 0, 255.0);  
  412.             cvSetReal2D(se, 0, 1, 255.0);  
  413.             cvSetReal2D(se, 0, 2, 255.0);  
  414.         }  
  415.             break;  
  416.         case 5:  
  417.         {  
  418.             cvSetReal2D(se, 0, 1, 255.0);  
  419.             cvSetReal2D(se, 0, 2, 255.0);  
  420.             cvSetReal2D(se, 1, 1, 255.0);  
  421.             cvSetReal2D(se, 1, 2, 255.0);  
  422.               
  423.         }  
  424.             break;  
  425.         case 6:  
  426.         {  
  427.             cvSetReal2D(se, 1, 1, 255.0);  
  428.             cvSetReal2D(se, 0, 2, 255.0);  
  429.             cvSetReal2D(se, 1, 2, 255.0);  
  430.             cvSetReal2D(se, 2, 2, 255.0);  
  431.         }  
  432.             break;  
  433.         case 7:  
  434.         {  
  435.             cvSetReal2D(se, 1, 1, 255.0);  
  436.             cvSetReal2D(se, 1, 2, 255.0);  
  437.             cvSetReal2D(se, 2, 1, 255.0);  
  438.             cvSetReal2D(se, 2, 2, 255.0);  
  439.         }  
  440.             break;  
  441.         default:  
  442.             break;  
  443.     }  
  444.     return se;  
  445. }  
  446. IplImage* CreateThinningUSE(int num){  
  447.     IplImage *se=cvCreateImage(cvSize(3, 3), 8, 1);  
  448.     cvZero(se);  
  449.     switch (num) {  
  450.         case 0:  
  451.         {  
  452.               
  453.             cvSetReal2D(se, 0, 1, 255.0);  
  454.             cvSetReal2D(se, 0, 2, 255.0);  
  455.             cvSetReal2D(se, 0, 0, 255.0);  
  456.         }  
  457.             break;  
  458.         case 1:  
  459.         {  
  460.             cvSetReal2D(se, 0, 1, 255.0);  
  461.             cvSetReal2D(se, 0, 2, 255.0);  
  462.             cvSetReal2D(se, 1, 2, 255.0);  
  463.               
  464.         }  
  465.             break;  
  466.         case 2:  
  467.         {  
  468.               
  469.             cvSetReal2D(se, 0, 2, 255.0);  
  470.             cvSetReal2D(se, 1, 2, 255.0);  
  471.             cvSetReal2D(se, 2, 2, 255.0);  
  472.         }  
  473.             break;  
  474.         case 3:  
  475.         {  
  476.             cvSetReal2D(se, 1, 2, 255.0);  
  477.             cvSetReal2D(se, 2, 1, 255.0);  
  478.             cvSetReal2D(se, 2, 2, 255.0);  
  479.         }  
  480.             break;  
  481.         case 4:  
  482.         {  
  483.               
  484.             cvSetReal2D(se, 2, 0, 255.0);  
  485.             cvSetReal2D(se, 2, 1, 255.0);  
  486.             cvSetReal2D(se, 2, 2, 255.0);  
  487.         }  
  488.             break;  
  489.         case 5:  
  490.         {  
  491.               
  492.             cvSetReal2D(se, 1, 0, 255.0);  
  493.             cvSetReal2D(se, 2, 0, 255.0);  
  494.             cvSetReal2D(se, 2, 1, 255.0);  
  495.               
  496.         }  
  497.             break;  
  498.         case 6:  
  499.         {  
  500.              
  501.             cvSetReal2D(se, 0, 0, 255.0);  
  502.             cvSetReal2D(se, 1, 0, 255.0);  
  503.             cvSetReal2D(se, 2, 0, 255.0);  
  504.         }  
  505.             break;  
  506.         case 7:  
  507.         {  
  508.             cvSetReal2D(se, 0, 0, 255.0);  
  509.             cvSetReal2D(se, 0, 1, 255.0);  
  510.             cvSetReal2D(se, 1, 0, 255.0);  
  511.         }  
  512.             break;  
  513.         default:  
  514.             break;  
  515.     }  
  516.     return se;  
  517. }  
  518.   
  519. //细化操作  
  520. void Thinning(IplImage *src,IplImage *dst){  
  521.     IplImage *temp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  522.     IplImage *temp_last=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  523.     IplImage *temp_com=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  524.     cvZero(temp_last);  
  525.     cvCopy(src, temp, NULL);  
  526.   
  527.     while(!isEqual(temp, temp_com)){  
  528.         cvCopy(temp, temp_com, NULL);  
  529.         for(int i=0;i<8;i++){  
  530.             cvCopy(temp, temp_last, NULL);  
  531.             IplImage *se1=CreateThinningSE(i);  
  532.             IplImage *se2=CreateThinningUSE(i);  
  533.             HitorMiss(temp, se1, se2, temp, NULL, NULL);  
  534.             cvSub(temp_last, temp, temp, NULL);  
  535.             cvReleaseImage(&se1);  
  536.             cvReleaseImage(&se2);  
  537.         }  
  538.           
  539.     }  
  540.     cvCopy(temp, dst, NULL);  
  541.     cvReleaseImage(&temp);  
  542.     cvReleaseImage(&temp_com);  
  543.     cvReleaseImage(&temp_last);  
  544. }  
  545. //重建开操作  
  546. void reBuildOpen(IplImage *src,IplImage *dst,IplImage *ground,IplImage *dilateSE,IplImage *erodeSE,int eroden){  
  547.     IplImage *temp=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  548.     IplImage *temp_last=cvCreateImage(cvGetSize(src), src->depth, src->nChannels);  
  549.     cvCopy(src, temp, NULL);  
  550.     for(int i=0;i<eroden;i++){  
  551.         Erode(temp, temp, erodeSE, NULL);  
  552.     }  
  553.      
  554.     while(!isEqual(temp, temp_last)){  
  555.         cvCopy(temp, temp_last, NULL);  
  556.         Dilate(temp, temp, dilateSE, NULL);  
  557.         And(temp, ground, temp);  
  558.           
  559.     }  
  560.     cvCopy(temp, dst, NULL);  
  561.     cvReleaseImage(&temp);  
  562.     cvReleaseImage(&temp_last);  
  563.   
  564. }  
  565.   
  566. int main(){  
  567.       
  568.     return 0;  

形态学处理函数