基于随机游走的图像分割算法

基于随机游走的图像分割算法是属于图论分割方法中的一种,这个算法比较偏,网上的paper比较少,刚开始学习找个资料都不容易,其实这个算法的原理就是通过求解一个邻接矩阵方程组,跟三维空间三角网格曲面的调和场求解有点类似。

1、算法开始前,先简单描述一下随机游走模型

一维随机游走问题:设一个质点(随机游走者)沿着一条直线运动,单位时间内只能运动一个单位长度,且只能停留在该直线上的整数点,假设在时刻t,该质点位于直线上的点i,那么在时刻t +1,该质点的位置有三种可能:①以p 的概率跳到整数点i-1,②或以q的概率跳到点i+1,③或以r=1-p-q的概率继续停留在点i ,由于每一步的结果都是独立的,且每种情况发生的概率之和都为1,则该过程服从伯努利分布,称为贝努利随机游走过程。当 p=q=0.5时,即质点在下一时刻到达其相邻点的概率是相等的,称为简单的随机游走。

例子1:如下图所示,假设某一时刻一质点位于刻度2的位置,质点左右游走的概率各为0.5,那么下一时刻该质点既有可能往左走,也有可能往右走,当质点运动到位置0、5位置时,质点停止运动,求质点到最后运动到位置5的概率?该问题便是随机游走问题。

对于一维的简单随机游走问题,满足:

   

,

其中,x为当前的位置点,x-1、x+1为位置x的左右邻接顶点。根据该公式,我们可以列出由n个未知数组成的n个方程组,可以发现该方程组的系数矩阵即为拉普拉斯邻接矩阵。拉普拉斯矩阵是非满秩矩阵,需要添加边界约束条件,方程组才有唯一解。

如例子1的问题,设添加边界约束条件:

则最后可以列出如下方程组,求出各点到位置5的概率。

2、基于随机游走的图像分割算法

①参考文献:《Random Walks for Image Segmentation》

②文献概述:随机游走算法是一种基于图论的分割算法,属于一种交互式的图像分割。它的分割思想是,以图像的像素为图的顶点,相邻像素之间的四邻域或八邻域关系为图的边,并根据像素属性及相邻像素之间特征的相似性定义图中各边的权值,以此构建网络图,然后由通过用户手工指定前景和背景标记,即前景物体和背景物体的种子像素,以边上的权重为转移概率,未标记像素节点为初始点,计算每个未标记节点首次到达各种子像素的概率,根据概率大小,划分未标记节点,得到最终分割结果。

例子2:如图下所示,图中的小圆圈代表图像上的每个像素点。L1,L2,L3三个种子点分别由用户交互输入,作为标记的种子点。现要把图像分割成对应的三部分。

③算法流程:

A.计算图中任意一点vi与其各个邻接顶点连接边的权重:

其中,表示个像素点的灰度值、或纹理信息等参数;

B.对于图中任意一点vi的概率,其满足随机游走概率公式:

其中,Ni为vi点的邻接顶点(可为四邻接顶点或八邻接顶点),根据上式,可构建图的拉普拉斯矩阵,然而拉普拉斯是非满秩矩阵,需要添加边界约束条件,才可根据方程组解出个各未知点的概率。也就是将图像分割问题转换为Dirichlet问题进行求解。

C.添加边界约束条件:以已标记的K类顶点作为边界约束条件,求解未知点到各个类的概率。如下图所示:求解各未知点游走到L1的概率,则以,作为约束条件,可求得个未知点的概率,如下图所示:

到达L1的概率

到达L2的概率

到达L3的概率

(5) 每一个未标记点,根据获得的对 K 类标记的隶属度值进行判断,若未标记点到达第k类的概率最大,则将未标记节点vi判别为属于类别k,完成分割。

最后贴一下自己写的部分重要函数代码:

[cpp] view plaincopy
  1. //根据邻接关系,构造拉普拉斯矩阵
  2. void CRandomWalk::ComputeCoff()
  3. {
  4. int height=m_image->Height;
  5. int width=m_image->Width;
  6. m_A.resize(height*width,width*height);
  7. int vn=height*width;
  8. typedef Eigen::Triplet<double> Tri;
  9. std::vector<Tri> tripletList;
  10. for (int i=0;i<height;i++)
  11. {
  12. for (int j=0;j<width;j++)
  13. {
  14. int idex=i*width+j;
  15. Eigen::Vector2i nei[4]={Eigen::Vector2i(i-1,j),Eigen::Vector2i(i,j-1),Eigen::Vector2i(i+1,j),Eigen::Vector2i(i,j+1)};
  16. BYTE *data=GetpData(Eigen::Vector2i(i,j),m_image);
  17. float sumw=0;
  18. for (int k=0;k<4;k++)
  19. {
  20. if (nei[k][0]>=0&&nei[k][0]<height&&nei[k][1]>=0&&nei[k][1]<width)
  21. {
  22. int idexnei=nei[k][0]*width+nei[k][1];
  23. BYTE *neidata=GetpData(nei[k],m_image);
  24. float w=-GetGrad(data,neidata);
  25. w=exp(w/(2*50*50));
  26. sumw+=w;
  27. tripletList.push_back(Tri(idex,idexnei,w));
  28. }
  29. }
  30. //计算A
  31. tripletList.push_back(Tri(idex,idex,-sumw));
  32. }
  33. }
  34. m_A.setFromTriplets(tripletList.begin(),tripletList.end());
  35. m_B.resize(height*width);
  36. m_B.setZero();
  37. }
  38. void CRandomWalk::AddConstrain()
  39. {
  40. for (int i=0;i<m_front.size();i++)
  41. {
  42. int indexf=m_image->Width*m_front[i].y+m_front[i].x;
  43. float a=m_A.coeff(indexf,indexf) +1;
  44. m_A.coeffRef(indexf,indexf)=a;
  45. }
  46. for (int j=0;j<m_back.size();j++)
  47. {
  48. int indexb=m_image->Width*m_back[j].y+m_back[j].x;
  49. float b=m_A.coeff(indexb,indexb) +1;
  50. m_A.coeffRef(indexb,indexb)=b;
  51. }
  52. m_MatricesCholesky=new Eigen::SparseLU<Eigen::SparseMatrix<double>>(m_A);
  53. }
  54. void CRandomWalk::Solver()
  55. {
  56. ComputeCoff();
  57. AddConstrain();
  58. Eigen::VectorXd b=m_B;
  59. for (int i=0;i<m_front.size();i++)
  60. {
  61. int indexf=m_image->Width*m_front[i].y+m_front[i].x;
  62. b(indexf)+=1;
  63. }
  64. Eigen::VectorXd x=m_MatricesCholesky->solve(b);
  65. Eigen::VectorXd bb=m_B;
  66. for (int j=0;j<m_back.size();j++)
  67. {
  68. int indexfb=m_image->Width*m_back[j].y+m_back[j].x;
  69. bb(indexfb)+=1;
  70. }
  71. Eigen::VectorXd y=m_MatricesCholesky->solve(bb);
  72. //比较概率大小
  73. for (int i=0;i<m_image->Height*m_image->Width;i++)
  74. {
  75. if (x(i)>y(i))
  76. {
  77. BYTE *data=(BYTE*)m_image->Scan0+i*4;
  78. for (int k=0;k<3;k++)
  79. {
  80. data[k]=255;
  81. }
  82. }
  83. }
  84. //int indexb=m_image->Width*m_front.y+m_front.x;
  85. }
  86. BYTE* CRandomWalk::GetpData(Eigen::Vector2i pt,BitmapData*image)
  87. {
  88. return (BYTE*)image->Scan0+image->Width*4*pt[0]+4*pt[1];
  89. }
  90. float CRandomWalk::GetGrad(BYTE*data1,BYTE*data2)
  91. {
  92. float sum0=0;
  93. for (int i=0;i<3;i++)
  94. {
  95. sum0+=(data1[i]-data2[i])*(data1[i]-data2[i]);
  96. }
  97. return sum0;
  98. }

本文地址:http://blog.csdn.net/hjimce/article/details/45201263     作者:hjimce     联系qq:1393852684

更多资源请关注我的博客:http://blog.csdn.net/hjimce                  原创文章,版权所有,转载请注明出处 。

图像处理(三)图像分割(1)Random Walks分割相关推荐

  1. 第10章 Python 数字图像处理(DIP) - 图像分割 基础知识 标准差分割法

    This Chapter is all about image segmentation. I still not finished whole chapter, but here try to pu ...

  2. 网格分割算法(Random Walks)

    网格分割算法(Random Walks) 首先以一维随机游走(1D Random Walks)为例来介绍下随机游走(Random Walks)算法,如下图所示,从某点出发,随机向左右移动,向左和向右的 ...

  3. 7.2 Python图像处理之图像分割-单阈值分割

    7.2 Python图像处理之图像分割-单阈值分割 文章目录 7.2 Python图像处理之图像分割-单阈值分割 1 算法原理 2 代码 3 效果 1 算法原理 单阈值分割算法原理: 单阈值分割是指将 ...

  4. Random Walks: A Review of Algorithms and Applications2020翻译

    Random Walks: A Review of Algorithms and Applications2020翻译 在翻译的时候公式太多,公式部分有些乱码.如果需要可以看看本文的文字,感兴趣的话直 ...

  5. 7.1 Python图像处理之图像分割-自适应阈值

    7.1 Python图像处理之图像分割-自适应阈值 文章目录 7.1 Python图像处理之图像分割-自适应阈值 1 算法原理 2 代码 3 效果 1 算法原理 在不均匀照明或者灰度值分布不均的情况下 ...

  6. [Python图像处理] 三十三.图像各种特效处理及原理万字详解(毛玻璃、浮雕、素描、怀旧、流年、滤镜等)...

    此文转载自:https://blog.csdn.net/Eastmount/article/details/111568397#commentBox 该系列文章是讲解Python OpenCV图像处理 ...

  7. 【图像分割模型】全景分割是什么?

    这是专栏<图像分割模型>的第12篇文章.在这里,我们将共同探索解决分割问题的主流网络结构和设计思想. 本文是专栏的最后一篇文章,见识过了分割任务中的大量模型,也了解了语义分割与实例分割,这 ...

  8. 【图像分割模型】实例分割模型—DeepMask

    这是专栏<图像分割模型>的第11篇文章.在这里,我们将共同探索解决分割问题的主流网络结构和设计思想. 本文介绍了用于实例分割任务的模型结构--DeepMask. 作者 | 孙叔桥 编辑 | ...

  9. [Python图像处理] 三十三.图像各种特效处理及原理万字详解(毛玻璃、浮雕、素描、怀旧、流年、滤镜等)

    该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门.OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子.图像增强技术.图像分割等,后期结合深度学习研究图像识别 ...

最新文章

  1. 数据结构与算法(7-2)图的遍历(深度优先遍历DFS、广度优先遍历BFS)(分别用邻接矩阵和邻接表实现)
  2. 禁掉人脸识别!一群音乐人正在号召,禁止在音乐节上动用人脸识别
  3. arm指令中mov和ldr及ldr伪指令的区别
  4. 在springboot中使用easyexcel导出数据excel表格
  5. 你不会真的以为自己懂得计算机网络吧?
  6. Effective C++阅读笔记
  7. 小米电视2+android,真实体验小米电视2方便安装第三方软件
  8. Linux服务之DNS服务篇
  9. CAD图纸、影像地形、倾斜摄影、矢量数据统统搬入图新地球,一键浏览分析
  10. C#之CAD二次开发: Ribbon界面初探
  11. C++-dllmain介绍
  12. 计算机装系统找不到硬盘,电脑小白装系统找不到硬盘
  13. html图片自动适应屏幕代码,css让图片宽度自适应屏幕的例子
  14. linux ccid驱动下载,ccid驱动支持
  15. win8.1 终于删除可恶的微软拼音
  16. HBuilder教程
  17. 服务器重启之后 宝塔面板打不开
  18. 群晖 NAS + frp 最新端口
  19. inprivate浏览是什么意思_打开浏览器无痕是什么意思
  20. 牛客网-排序题目分享(2)

热门文章

  1. 机器学习是如何运作的?谷歌来告诉你
  2. Ubuntu迁移/boot卷
  3. jvm性能调优实战 - 40 百万级数据误处理导致的频繁Full GC问题优化
  4. Elasticsearch-02CentOS7安装elasticsearch-head插件
  5. C++五子棋(四)——走棋原理及权值计算
  6. python列表每行查找字符串,python - 用python查找子字符串列表成字符串列表 - SO中文参考 - www.soinside.com...
  7. 腾讯面试题 linux下free命令详解
  8. (三) LtRecyclerView v2.x (自定义上拉和下拉刷新View)
  9. python伪造浏览器请求头_Python3 伪装浏览器的方法示例
  10. 使用【python语言】和【typescript】进行冒泡排序