一、level set相关理论

基于水平集的图像分割算法是一种进化版的Snake算法,也是需要给定初始的轮廓曲线,然后根据泛函能量最小化,进行曲线演化。水平集的方法,用的是一种隐式函数的方法,这个算法比较难理解,我一年前开始搞这个算法的时候,虽然知道代码怎么写,但是它的原理推导完全不懂,因为这个算法比较难理解,所以我这边将讲的稍微详细一点。

跟传统的snake算法相比,思想完全不一样,snake算法曲线演化的时候,是曲线上离散点显示坐标的位置更新移动,只要懂得能量最小化的曲线演化规则,就可以很快理解算法,并写出代码。然而水平集的方法,更新的不是曲线离散点的坐标,而是更新整张图片像素点到曲线的有向距离场。因此算法最关键的是理解这个距离场的更新规则,当然这个更新规则跟能量最小化相关。

开始这个算法之前,我们需要非常熟悉,显式二维的曲线与隐式曲线(水平集函数)的相互转换公式。给定初始的轮廓曲线C,我们怎么把它转换成水平集函数,这个是实现算法的第一步。水平集函数的定义:

公式1:       

也就是说,如果给你一条初始封闭轮廓曲线C,进行水平集图像分割,我们需要写的第一个函数就是计算图像的每个像素点p(x,y)到曲线的最短距离d,如果该像素点p位于曲线C的内部,那么有向距离为-d;反之为d。这样遍历图像每个像素点,每个像素点都可以求得对应的有向距离u(x,y)。反过来,如果我已经知道了图像上每个像素点的有向距离u(x,y),那么我要怎么把这个隐式函数转换成显示函数呢?

其实很简单,只要求出满足u(x,y)=0 的像素点,就是曲线上的点,因为如果该像素点到曲线C的最短距离为0,那么这个像素点肯定在这条曲线上,据此我们就可以把所有满足u(x,y)=0的像素点全部提取出来,获得这些像素点的坐标p(x,y),而这些点便是曲线C的离散点,这样就完成了从隐式距离场到显式离散曲线的转换。

据此我们可以得到算法的大体流程:

输入:给定离散的初始轮廓曲线C,待分割图像T

输出:分割结果曲线C’

Algorithm:

Begin:

1、根据公式1,计算每个像素点到离散曲线C的最短有向距离u(x,y)

2、根据图像梯度等信息,对u(x,y)进行演化,使得其沿着能量最小化的方向演化,这个过程说的简单一点,就是更新每个像素点的u(x,y)值。

3、根据第2步的演化结果,遍历每个像素点(x,y),判断其水平集函数值是否为零。

If  u(x,y)==0:

保存像素点坐标(x,y)(因为这个点就是曲线C’上的点)

得到所有u(x,y)==0的点,就是最后我们想要的图像分割结果曲线C’

End

二、算法实现:

这里我选择Mean Separation (MS) Energy能量最小化为例,讲解局部活动轮廓图像分割,具体的参考文献为:《Localizing Region-Based Active Contours》。这里为直接把文中最后算法实现需要使用的公式,截出来,以便学习。

水平集总演化公式为:

其中:

dt是一个较小的数,选择范围为0.1~40都可以,当然迭代步长还是选择的越小效果越好,就是需要的迭代次数越多。然后下面的公式为公式(17)对应的参数求解公式:

其中:

公式3是一个卷积核,上面的大部分过程的计算都涉及到用B(x,y)进行卷积,卷积半径在我的项目使用的时候,我是选择R=8,而且B(x,y)是一个均值滤波的卷积核,因此如果要对算法用快速均值滤波,算法可提高五六倍的速度。具体算法代码实现如下:

function seg = local_AC_MS(Img,mask_init,rad,alpha,num_it,epsilon) %参数Img为灰度图像 %mask_init为初始曲线的一个mask,曲线上的点坐标在mask中的值为1 %rad 为卷积半径 %alpha为公式6中的λ %num_it为迭代次数 %epsilon为公式1中的ε phi0 = mask2phi(mask_init);%从显式曲线转换成水平集函数 phi = phi0;%计算距离场,即计算所有的像素点位置(x,y)到曲线的最短距离,这就是所谓的水平集函数 B0 = ones(2*rad+1,2*rad+1); %mask,卷积核 KI=conv2(Img,B0,'same'); %对图像Img用卷积核B0进行卷积 KONE=conv2(ones(size(Img)),B0,'same'); %下面计算的是文献的公式17,即使用公式17对曲线进行演化,所有的计算都是为了计算公式17 for ii = 1:num_it%开始迭代 mask = Heaviside2(phi,epsilon);%计算文献公式1 I=Img.*mask; temp1=conv2(mask,B0,'same'); %文献的公式18 temp2=conv2(I,B0,'same'); c1=temp2./(temp1); c2=(KI-temp2)./(KONE-temp1); A1 = temp1;%文献的公式18 A2 = conv2(1-mask,B0,'same');%文献公式19 D = (A1.*A2+eps); term1 = (A2-A1)./D; term2 = (A2.*c1.^2-A1.*c2.^2)./D; term3 = (A2.*c1-A1.*c2)./D; %计算总公式的前半部分 dataForce = conv2(term1.*Dirac2(phi,epsilon),B0,'same').*Img.*Img + conv2(term2.*Dirac2(phi,epsilon),B0,'same')-2.*Img.*conv2(term3.*Dirac2(phi,epsilon),B0,'same'); %%% During the implementation, Img should be separated out of the filtering operation!!! dataForce = dataForce/max(abs(dataForce(:))); %计算总公式的后半部分,即水平集的散度 curvature = curvature_central(phi); %总公式 dphi = Dirac2(phi,epsilon).*(-dataForce + alpha*curvature); dt = 1/(max(abs(dphi(:)))+eps);%时间步长,该参数可人为设置为恒定参数 %曲线演化公式,即完成曲线的迭代 phi = phi + dt.*dphi; %绘制曲线,(x,y)的值为0的点即为曲线上的点 if(mod(ii,10) == 0) showCurveAndPhi(Img,phi,ii); %绘制值为0的等值线 end end seg = (phi>=0); %为了保证水平集的光滑性,需要对水平集进行重新计算,保证水平集的梯度模为1 %具体计算公式见 function D = sussman(D, dt) %前后差分 a = D - shiftR(D); % 后差分 b = shiftL(D) - D; % 前差分 c = D - shiftD(D); d = shiftU(D) - D; a_p = a; a_n = a; % a+ and a- b_p = b; b_n = b; c_p = c; c_n = c; d_p = d; d_n = d; a_p(a < 0) = 0; a_n(a > 0) = 0; b_p(b < 0) = 0; b_n(b > 0) = 0; c_p(c < 0) = 0; c_n(c > 0) = 0; d_p(d < 0) = 0; d_n(d > 0) = 0; dD = zeros(size(D)); D_neg_ind = find(D < 0); D_pos_ind = find(D > 0); dD(D_pos_ind) = sqrt(max(a_p(D_pos_ind).^2, b_n(D_pos_ind).^2) ... + max(c_p(D_pos_ind).^2, d_n(D_pos_ind).^2)) - 1; dD(D_neg_ind) = sqrt(max(a_n(D_neg_ind).^2, b_p(D_neg_ind).^2) ... + max(c_n(D_neg_ind).^2, d_p(D_neg_ind).^2)) - 1; D = D - dt .* sussman_sign(D) .* dD; function shift = shiftD(M) shift = shiftR(M')'; function shift = shiftL(M) shift = [ M(:,2:size(M,2)) M(:,size(M,2)) ]; function shift = shiftR(M) shift = [ M(:,1) M(:,1:size(M,2)-1) ]; function shift = shiftU(M) shift = shiftL(M')'; function S = sussman_sign(D) S = D ./ sqrt(D.^2 + 1); %计算有向距离场函数 function phi = mask2phi(init_a) phi=bwdist(init_a)-bwdist(1-init_a)+im2double(init_a); phi = -double(phi); %水平集提取函数,也就是把隐式函数转换成显式函数,所得简单一点,就是提取值为0的等高线 function showCurveAndPhi(I, phi, i) imshow(I,'initialmagnification',200,'displayrange',[ ]); hold on; contour(phi, [0 0], 'y','LineWidth',2); hold off; title([num2str(i) ' Iterations']); drawnow; %文献公式2 function f = Dirac2(x, sigma) f = (sigma/pi)./(sigma^2+x.^2); %计算文献公式1 function f = Heaviside2(x, epsilon) f = 0.5*(1+2/pi*atan(x./epsilon)); %散度计算 function k = curvature_central(u) [ux,uy] = gradient(u); normDu = sqrt(ux.^2+uy.^2+1e-10); Nx = ux./normDu; Ny = uy./normDu; [nxx,junk] = gradient(Nx); [junk,nyy] = gradient(Ny); k = nxx+nyy;

个人观点:我觉得传统的snake算法,只能用烂来解释,基本上以遇到一点噪声,就不行了,分割精度真不是一般的差。而水平集的分割只能用高大上来形容,可以进行自动分裂合并等,就是速度有点慢,因为每次都要对水平集函数进行更新,更新一次就相当于遍历一张图片,因此速度可想而知,当然还有很多加速版的水平集方法,有待测试学习。本文地址:http://blog.csdn.net/hjimce/article/details/45586727    作者:hjimce     联系qq:1393852684   更多资源请关注我的博客:http://blog.csdn.net/hjimce                 原创文章,版权所有,转载请保留本行信息

图像处理(十一)图像分割(3)泛函能量LevelSet、snake分割相关推荐

  1. 【图像处理】图像分割之(一~四)GraphCut,GrabCut函数使用和源码解读(OpenCV)

    图像分割之(一)概述 http://blog.csdn.net/zouxy09 所谓图像分割指的是根据灰度.颜色.纹理和形状等特征把图像划分成若干互不交迭的区域,并使这些特征在同一区域内呈现出相似性, ...

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

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

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

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

  4. 【图像分割模型】用BRNN做分割—ReSeg

    这是专栏<图像分割模型>的第9篇文章.在这里,我们将共同探索解决分割问题的主流网络结构和设计思想. 尽管许多人都知道RNN在处理上下文上多优于CNN,但如何将RNN用于分割任务还是值得讨论 ...

  5. OpenCV Using Python——应用统计肤色模型和相对于块原点能量的肤色分割

    应用统计肤色模型和相对于块原点能量的肤色分割 1. 肤色分割简介 (1)统计肤色模型简介 在前面的文章中,我们利用训练数据已经成功计算出训练数据的后验概率P(Cs|v),即已知像素值判断属于肤色类的概 ...

  6. 图像分割之主动轮廓线模型Snake

    基本概念 1987年由 Kass 等人提出的主动轮廓模型即蛇模型(snake 模型).活动轮廓模型可以用在图像分割和理解中,也适用于分析动态图像或三维图像.Snake定义为最小的能量样条曲线.下面重点 ...

  7. 数字图像处理——形态学图像处理及图像分割

    文章目录 形态学图像处理 1 膨胀和腐蚀 1.1 膨胀 1.2 腐蚀 2 开操作和闭操作 3 击中或击不中变换 4 一些基本的形态学算法 4.1 边界提取 4.2 区域填充 4.3 连通分量的提取 图 ...

  8. [Python图像处理] 十一.灰度直方图概念及OpenCV绘制直方图

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

  9. 计算机视觉基础-图像处理(图像分割/二值化)cpp+python

    5.1 简介 该部分的学习内容是对经典的阈值分割算法进行回顾,图像阈值化分割是一种传统的最常用的图像分割方法,因其实现简单.计算量小.性能较稳定而成为图像分割中最基本和应用最广泛的分割技术.它特别适用 ...

最新文章

  1. ubuntu8.10家庭使用(一)
  2. linux 内核中基于netfilter的编译选项
  3. 呼叫中心如何规划好工作习惯
  4. php - 冒泡排序
  5. idea 类注释,方法注释设置
  6. [C++STL]map容器用法介绍
  7. [转载]ext4的noatime
  8. IP子网编址和无类域路由CIDR
  9. Go一个协程实现加法demo
  10. 拓端tecdat|r语言中对LASSO回归,Ridge岭回归和弹性网络Elastic Net模型实现|视频
  11. 2019一注结构成绩_2019年福建地区计算机考研汇总分析
  12. webstorm使用指南
  13. HTML5+CSS——个人在线简历
  14. C语言读bin文件内容
  15. windows安装yarn和tyarn
  16. 如何通过XRD计算晶格常数
  17. HHL论文第一弹(总结算法基本思想、QRAM制备量子态)
  18. 全球及中国熔融碳酸盐燃料电池行业前景展望及市场全景调研报告2022-2028年版
  19. python tcl 外部_python为什么有tcl|python教程|python入门|python教程
  20. 压缩解压zip文件包

热门文章

  1. Java个人网页设计实验报告_web实验报告.doc
  2. B端和C端的产品有何差异
  3. STEM 教育课程如何设计?
  4. 分辨率,码率,帧率,ppi,像素,帧大小的计算
  5. .NET Framework和.NET Core/.NET5/.NET6
  6. python 处理csv文件 一个简单的数据处理任务
  7. html页面证书过期,网页上的完全证书过期过失效怎么处理
  8. 图书管理开题报告php,基于PHP+SqlServer的图书管理系统,毕业论文设计,答辩ppt,开题报告,外文翻译,苹果,硕士研究生,iphone...
  9. shell卸载 simatic_Siemens Simatic WinCC v7.5 SP1 (x64)ISO 授权安装教程
  10. 企业级Memcached服务应用实践