声振论坛

 找回密码
 我要加入

QQ登录

只需一步,快速开始

查看: 3018|回复: 3

[C/C++] 分水岭算法对输入算法尽行分割

[复制链接]
发表于 2006-6-3 11:23 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?我要加入

x
分水岭算法对输入算法尽行分割

  1. //Image Watershed Segmentation
  2. //This is the implementation of the algorithm based on immersion model.
  3. // ===========================================================================
  4. // =====      Module: Watershed.cpp
  5. // ===== -------------------------------------------------------------- ======
  6. // =====      Version 01   Date: 04/21/2003
  7. // ===== -------------------------------------------------------------- ======
  8. // ===========================================================================
  9. // =====      Written by Foxhole@smth.org
  10. // =====      e-mail:  gong200@china.com
  11. // ===========================================================================
  12. // Permission to use, copy, or modify this software and its documentation
  13. // for educational and research purposes only is hereby granted without
  14. // fee, provided that this copyright notice appear on all copies and
  15. // related documentation.  For any other uses of this software, in original
  16. // or modified form, including but not limited to distribution in whole
  17. // or in part, specific prior permission must be obtained from
  18. // the author(s).
  19. //
  20. // THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
  21. // EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
  22. // WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  23. //
  24. // IN NO EVENT SHALL RUTGERS UNIVERSITY BE LIABLE FOR ANY SPECIAL,
  25. // INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY
  26. // DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  27. // WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY
  28. // THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE
  29. // OR PERFORMANCE OF THIS SOFTWARE.
  30. // ===========================================================================

  31. #include <queue>
  32. #include <vector>
  33. #include <windows.h>


  34. /*====================================================================
  35. 函数名                        :        Watershed
  36. 功能                        :        用标记-分水岭算法对输入图像进行分割
  37. 算法实现                :        无
  38. 输入参数说明        :        OriginalImage --输入图像(灰度图,0~255)
  39.                                           SeedImage     --标记图像(二值图,0-非标记,1-标记)
  40.                                           LabelImage    --输出图像(1-第一个分割区域,2-第二个分割区域,...)
  41.                                           row           --图像行数
  42.                                           col           --图像列数
  43. 返回值说明                :         无       
  44. ====================================================================*/
  45. void Watershed(const int **OriginalImage, char** SeedImage, int **LabelImage, int row, int col)
  46. {
  47.         using namespace std;

  48.         //标记区域标识号,从1开始
  49.         int Num=0;
  50.         int i,j;

  51.         //保存每个队列种子个数的数组
  52.         vector<int*> SeedCounts;
  53.         //临时种子队列
  54.         queue<POINT> que;
  55.         //保存所有标记区域种子队列的数组
  56.         vector<queue<POINT>* > qu;
  57.        
  58.         int* array;
  59.         queue<POINT> *uu;
  60.         POINT temp;

  61.         for(i=0;i<row;i++)
  62.                 for(j=0;j<col;j++)
  63.                         LabelImage[i][j]=0;
  64.        

  65.         int m,n,k=0;
  66.         int up,down,right,left,upleft,upright,downleft,downright;

  67.         //预处理,提取区分每个标记区域,并初始化每个标记的种子队列
  68.         //种子是指标记区域边缘的点,他们可以在水位上升时向外淹没(或者说生长)
  69.         for(i=0;i<row;i++)
  70.         {
  71.                 for(j=0;j<col;j++)
  72.                 {
  73.                         //如果找到一个标记区域
  74.                         if(SeedImage[i][j]==1)
  75.                         {
  76.                                 //区域的标识号加一
  77.                                 Num++;
  78.                                 //分配数组并初始化为零
  79.                                 array=new int[256];
  80.                                 ZeroMemory(array,256*sizeof(int));
  81.                                 //
  82.                                 SeedCounts.push_back(array);
  83.                                 //分配本标记的优先队列
  84.                                 uu=new queue<POINT>[256];
  85.                                 //加入到队列数组中
  86.                                 qu.push_back(uu);
  87.                                 //当前点放入本标记区域的临时种子队列中
  88.                                 temp.x=i;
  89.                                 temp.y=j;
  90.                                 que.push(temp);
  91.                                 //当前点标记为已处理
  92.                                 LabelImage[i][j]=Num;
  93.                                 SeedImage[i][j]=127;
  94.                                
  95.                                 //让种子队列中的种子进行生长直到所有的种子都生长完毕
  96.                                 while(!que.empty())
  97.                                 {
  98.                                         up=down=right=left=0;
  99.                                         upleft=upright=downleft=downright=0;
  100.                                         //队列中取出一个种子
  101.                                         temp=que.front();
  102.                                         m=temp.x;
  103.                                         n=temp.y;
  104.                                         que.pop();

  105.                                         if(m>0)
  106.                                         {
  107.                                                 //上方若为可生长点则加为新种子
  108.                                                 if(SeedImage[m-1][n]==1)
  109.                                                 {
  110.                                                         temp.x=m-1;
  111.                                                         temp.y=n;
  112.                                                         que.push(temp);
  113.                                                         //新种子点标记为已淹没区域
  114.                                                         LabelImage[m-1][n]=Num;
  115.                                                         SeedImage[m-1][n]=127;
  116.                                                 }else//否则上方为不可生长
  117.                                                 {
  118.                                                         up=1;
  119.                                                 }
  120.                                         }
  121.                                         if(m>0&&n>0)
  122.                                         {
  123.                                                 if(SeedImage[m-1][n-1]==1)//左上方若为可生长点则加为新种子
  124.                                                 {
  125.                                                         temp.x=m-1;
  126.                                                         temp.y=n-1;
  127.                                                         que.push(temp);
  128.                                                         //新种子点标记为已淹没区域
  129.                                                         LabelImage[m-1][n-1]=Num;
  130.                                                         SeedImage[m-1][n-1]=127;
  131.                                                 }else//否则左上方为不可生长
  132.                                                 {
  133.                                                         upleft=1;
  134.                                                 }
  135.                                         }

  136.                                         if(m<row-1)
  137.                                         {
  138.                                                 if(SeedImage[m+1][n]==1)//下方若为可生长点则加为新种子
  139.                                                 {
  140.                                                         temp.x=m+1;
  141.                                                         temp.y=n;
  142.                                                         que.push(temp);
  143.                                                         //新种子点标记为已淹没区域
  144.                                                         LabelImage[m+1][n]=Num;
  145.                                                         SeedImage[m+1][n]=127;
  146.                                                 }else//否则下方为不可生长
  147.                                                 {
  148.                                                         down=1;
  149.                                                 }
  150.                                         }
  151.                                         if(m<(row-1)&&n<(col-1))
  152.                                         {
  153.                                                 if(SeedImage[m+1][n+1]==1)//下方若为可生长点则加为新种子
  154.                                                 {
  155.                                                         temp.x=m+1;
  156.                                                         temp.y=n+1;
  157.                                                         que.push(temp);
  158.                                                         //新种子点标记为已淹没区域
  159.                                                         LabelImage[m+1][n+1]=Num;
  160.                                                         SeedImage[m+1][n+1]=127;
  161.                                                 }else//否则下方为不可生长
  162.                                                 {
  163.                                                         downright=1;
  164.                                                 }
  165.                                         }
  166.                                
  167.                                         if(n<col-1)
  168.                                         {
  169.                                                 if(SeedImage[m][n+1]==1)//右方若为可生长点则加为新种子
  170.                                                 {
  171.                                                         temp.x=m;
  172.                                                         temp.y=n+1;
  173.                                                         que.push(temp);
  174.                                                         //新种子点标记为已淹没区域
  175.                                                         LabelImage[m][n+1]=Num;
  176.                                                         SeedImage[m][n+1]=127;
  177.                                                 }else//否则右方为不可生长
  178.                                                 {
  179.                                                         right=1;
  180.                                                 }
  181.                                         }
  182.                                         if(m>0&&n<(col-1))
  183.                                         {
  184.                                                 if(SeedImage[m-1][n+1]==1)//右上方若为可生长点则加为新种子
  185.                                                 {
  186.                                                         temp.x=m-1;
  187.                                                         temp.y=n+1;
  188.                                                         que.push(temp);
  189.                                                         //新种子点标记为已淹没区域
  190.                                                         LabelImage[m-1][n+1]=Num;
  191.                                                         SeedImage[m-1][n+1]=127;
  192.                                                 }else//否则右上方为不可生长
  193.                                                 {
  194.                                                         upright=1;
  195.                                                 }
  196.                                         }

  197.                                         if(n>0)
  198.                                         {
  199.                                                 if(SeedImage[m][n-1]==1)//左方若为可生长点则加为新种子
  200.                                                 {
  201.                                                         temp.x=m;
  202.                                                         temp.y=n-1;
  203.                                                         que.push(temp);
  204.                                                         //新种子点标记为已淹没区域
  205.                                                         LabelImage[m][n-1]=Num;
  206.                                                         SeedImage[m][n-1]=127;
  207.                                                 }else//否则左方为不可生长
  208.                                                 {
  209.                                                         left=1;
  210.                                                 }
  211.                                         }
  212.                                         if(m<(row-1)&&n>0)
  213.                                         {
  214.                                                 if(SeedImage[m+1][n-1]==1)//左下方若为可生长点则加为新种子
  215.                                                 {
  216.                                                         temp.x=m+1;
  217.                                                         temp.y=n-1;
  218.                                                         que.push(temp);
  219.                                                         //新种子点标记为已淹没区域
  220.                                                         LabelImage[m+1][n-1]=Num;
  221.                                                         SeedImage[m+1][n-1]=127;
  222.                                                 }else//否则左方为不可生长
  223.                                                 {
  224.                                                         downleft=1;
  225.                                                 }
  226.                                         }

  227.                                         //上下左右只要有一点不可生长,那么本点为初始种子队列中的一个
  228.                                         if(up||down||right||left||
  229.                                                 upleft||downleft||upright||downright)
  230.                                         {
  231.                                                 temp.x=m;
  232.                                                 temp.y=n;
  233.                                                 qu[Num-1][OriginalImage[m][n]].push(temp);
  234.                                                 SeedCounts[Num-1][OriginalImage[m][n]]++;
  235.                                         }

  236.                                 }//while结束
  237.                         }
  238.                 }
  239.         }

  240.         bool actives;//在某一水位处,所有标记的种子生长完的标志
  241.         int WaterLevel;

  242.         //淹没过程开始,水位从零开始上升
  243.         for(WaterLevel=0;WaterLevel<256;WaterLevel++)
  244.         {
  245.                 actives=true;
  246.                 while(actives)
  247.                 {
  248.                         actives=false;
  249.                         //依次处理每个标记区域
  250.                         for(i=0;i<Num;i++)
  251.                         {
  252.                         if(!qu[i][WaterLevel].empty())
  253.                         {
  254.                                 actives=true;
  255.                                 while(SeedCounts[i][WaterLevel]>0)
  256.                                 {
  257.                                         SeedCounts[i][WaterLevel]--;
  258.                                         temp=qu[i][WaterLevel].front();
  259.                                         qu[i][WaterLevel].pop();
  260.                                         m = temp.x;
  261.                                         n = temp.y;//当前种子的坐标
  262.                                         if(m>0)
  263.                                         {
  264.                                                 if(!LabelImage[m-1][n])//上方若未处理
  265.                                                 {
  266.                                                         temp.x=m-1;
  267.                                                         temp.y=n;
  268.                                                         LabelImage[m-1][n]=i+1;//上方点标记为已淹没区域

  269.                                                         if(OriginalImage[m-1][n]<=WaterLevel)//上方若为可生长点则加入当前队列
  270.                                                         {
  271.                                                                 qu[i][WaterLevel].push(temp);
  272.                                                         }
  273.                                                         else//否则加入OriginalImage[m-1][n]级队列
  274.                                                         {
  275.                                                                 qu[i][OriginalImage[m-1][n]].push(temp);
  276.                                                                 SeedCounts[i][OriginalImage[m-1][n]]++;
  277.                                                         }
  278.                                                 }
  279.                                         }

  280.                                         if(m<row-1)
  281.                                         {
  282.                                                 if(!LabelImage[m+1][n])//下方若未处理
  283.                                                 {
  284.                                                         temp.x=m+1;
  285.                                                         temp.y=n;
  286.                                                         LabelImage[m+1][n]=i+1;//下方点标记为已淹没区域

  287.                                                         if(OriginalImage[m+1][n]<=WaterLevel)//下方若为可生长点则加入当前队列
  288.                                                         {
  289.                                                                 qu[i][WaterLevel].push(temp);
  290.                                                         }
  291.                                                         else//否则加入OriginalImage[m+1][n]级队列
  292.                                                         {
  293.                                                                 qu[i][OriginalImage[m+1][n]].push(temp);
  294.                                                                 SeedCounts[i][OriginalImage[m+1][n]]++;
  295.                                                         }
  296.                                                 }
  297.                                         }
  298.                        
  299.                                         if(n<col-1)
  300.                                         {
  301.                                                 if(!LabelImage[m][n+1])//右边若未处理
  302.                                                 {
  303.                                                         temp.x=m;
  304.                                                         temp.y=n+1;
  305.                                                         LabelImage[m][n+1]=i+1;//右边点标记为已淹没区域

  306.                                                         if(OriginalImage[m][n+1]<=WaterLevel)//右边若为可生长点则加入当前队列
  307.                                                         {
  308.                                                                 qu[i][WaterLevel].push(temp);
  309.                                                         }
  310.                                                         else//否则加入OriginalImage[m][n+1]级队列
  311.                                                         {
  312.                                                                 qu[i][OriginalImage[m][n+1]].push(temp);
  313.                                                                 SeedCounts[i][OriginalImage[m][n+1]]++;
  314.                                                         }
  315.                                                 }
  316.                                         }

  317.                                         if(n>0)
  318.                                         {
  319.                                                 if(!LabelImage[m][n-1])//左边若未处理
  320.                                                 {
  321.                                                         temp.x=m;
  322.                                                         temp.y=n-1;
  323.                                                         LabelImage[m][n-1]=i+1;//左边点标记为已淹没区域

  324.                                                         if(OriginalImage[m][n-1]<=WaterLevel)//左边若为可生长点则加入当前队列
  325.                                                         {
  326.                                                                 qu[i][WaterLevel].push(temp);
  327.                                                         }
  328.                                                         else//否则加入OriginalImage[m][n-1]级队列
  329.                                                         {
  330.                                                                 qu[i][OriginalImage[m][n-1]].push(temp);
  331.                                                                 SeedCounts[i][OriginalImage[m][n-1]]++;
  332.                                                         }
  333.                                                 }
  334.                                         }
  335.                                 }//while循环结束
  336.                                 SeedCounts[i][WaterLevel]=qu[i][WaterLevel].size();
  337.                         }//if结束
  338.                         }//for循环结束
  339.                 }//while循环结束
  340.         }//for循环结束
  341.         while(!qu.empty())
  342.         {
  343.                 uu=qu.back();
  344.                 delete[] uu;
  345.                 qu.pop_back();
  346.         }
  347.         while(!SeedCounts.empty())
  348.         {
  349.                 array=SeedCounts.back();
  350.                 delete[] array;
  351.                 SeedCounts.pop_back();
  352.         }
复制代码

[ 本帖最后由 风花雪月 于 2006-11-12 07:48 编辑 ]
回复
分享到:

使用道具 举报

发表于 2006-8-11 13:22 | 显示全部楼层
:)最近看文章时碰到了
下来研究看看
谢谢!
发表于 2006-8-15 22:56 | 显示全部楼层
谢谢
发表于 2006-8-15 23:37 | 显示全部楼层
下了,谢谢分享
您需要登录后才可以回帖 登录 | 我要加入

本版积分规则

QQ|小黑屋|Archiver|手机版|联系我们|声振论坛

GMT+8, 2024-11-25 21:41 , Processed in 0.063954 second(s), 17 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表