这四个步骤基本上贯穿了整个从思路构建到具体实现的大致流程,早期的snake模型本质上是用一种曲线演化的思想来实现分割,这种方法具有很大的局限性(以后我会在单讲水平集方法的时候进行分析),对比之下,水平集方法则具备较强的优势,而根据水平集方法在上述流程图中引入步骤的不同,我们把水平集方法在主动轮廓模型中的应用分为如下两类:传统的基于主动轮廓模型和水平集理论的方法和变分水平集方法。
其中传统的方法则是在获得步骤二中的用于演化的偏微分方程后再引入水平集方法,如下图所示
1 构建能量泛函 2 获得用于演化的偏微分方程,引入水平集方法 3 离散化偏微分方程 4 代码实现与调试比如针对某一几何活动轮廓模型,我们有如下PDF驱动曲线演化: ∂ c ∂ t = g ( u ) N (1) \frac{\partial c}{\partial t}=g(u) N \tag{1} ∂t∂c=g(u)N(1) 其中 c c c代表演化曲线, g ( u ) g(u) g(u)用于控制曲线的演化速度(u可以理解为目标曲线所在图像), N N N则表示内单位法向量。 将曲线 c ( t ) c(t) c(t)引入三位水平集函数 ϕ ( x , y , t ) \phi(x,y,t) ϕ(x,y,t)的零水平集(ZLS)则可得: ϕ ( c ( t ) , t ) = 0 (2) \phi(c(t), t)=0 \tag{2} ϕ(c(t),t)=0(2)对公式(2)中 t t t求导可得 ∇ ϕ ⋅ ∂ c ∂ t + ∂ ϕ ∂ t = 0 (3) \nabla \phi \cdot \frac{\partial c}{\partial t}+\frac{\partial \phi}{\partial t}=0 \tag{3} ∇ϕ⋅∂t∂c+∂t∂ϕ=0(3)这样我们就找到了曲线演化和水平集函数演化之间的对应关系: ∂ ϕ α t = − ∇ ϕ ⋅ ∂ c ∂ t = − ∇ ϕ ⋅ g ( u ) ⋅ N (4) \frac{\partial \phi}{\alpha t}=-\nabla \phi \cdot \frac{\partial c}{\partial t}=-\nabla \phi \cdot g(u) \cdot N \tag {4} αt∂ϕ=−∇ϕ⋅∂t∂c=−∇ϕ⋅g(u)⋅N(4)而对于三维水平集函数,其梯度方向则必然与零等势面即零水平集切线方向垂直,所以在假定水平集函数内负外正的情况下,我们可以切线方向可表示为: N = − ∇ ϕ ∣ ∇ ϕ ∣ (5) N=-\frac{\nabla \phi}{|\nabla \phi|} \tag {5} N=−∣∇ϕ∣∇ϕ(5)将式(5)进一步引入式(4)中,即可得 : ∂ ϕ α t = − ∇ ϕ ⋅ ∂ c ∂ t = − ∇ ϕ ⋅ g ( u ) ⋅ ( − ∇ ϕ ∣ ∇ ϕ ∣ ) = g ( u ) ∣ ∇ ϕ ∣ (6) \frac{\partial \phi}{\alpha t}=-\nabla \phi \cdot \frac{\partial c}{\partial t}=-\nabla \phi \cdot g(u) \cdot (-\frac{\nabla \phi}{|\nabla \phi|}) = g(u)|\nabla \phi| \tag {6} αt∂ϕ=−∇ϕ⋅∂t∂c=−∇ϕ⋅g(u)⋅(−∣∇ϕ∣∇ϕ)=g(u)∣∇ϕ∣(6)至此,基于曲线演化得偏微分方程已经被新的基于水平集函数的偏微分方程完全取代。
而第二种在引入水平集的方法则是直接在步骤1构建能量泛函中引入水平集函数,然后利用变分法求解能量泛函极值,这种方法则称之为变分水平集方法。
1 构建能量泛函,引入水平集方法 2 获得用于演化的偏微分方程 3 离散化偏微分方程 4 代码实现与调试比如对于经典的基于区域的Chan-Vese模型,其核心思想是构造一个包含目标曲线的能量泛函 E = E 1 ( C ) + E 2 ( C ) = ∫ i n s i d e ( C ) ∣ I 0 ( x , y ) − C 1 ∣ 2 d x d y + ∫ o u t s i d e ( C ) ∣ I 0 ( x , y ) − C 2 ∣ 2 d x d y E = E_1(C) + E_2(C) = \int_{inside(C)}{|I_0(x,y)-C_1|^2}\,{\rm d}x{\rm d}y + \int_{outside(C)}{|I_0(x,y)-C_2|^2}\,{\rm d}x{\rm d}y E=E1(C)+E2(C)=∫inside(C)∣I0(x,y)−C1∣2dxdy+∫outside(C)∣I0(x,y)−C2∣2dxdy其中 E 1 ( C ) E_1(C) E1(C)和 E 2 ( C ) E_2(C) E2(C)则分别代表曲线内和曲线外能量, E 1 ( C ) E_1(C) E1(C)和 E 2 ( C ) E_2(C) E2(C)分别对应图中 F 1 ( C ) 和 F 2 ( C ) F_1(C)和F_2(C) F1(C)和F2(C),根据下图可以很容易判断,当曲线达到目标边缘时,能量函数取得极小值, 因此,其演化本质就是利用演化曲线内像素和跟曲线外像素和的差作为动力驱动曲线向目标边缘演化。 和第一节引入水平集函数的方法不同,其在构造能量函数这一步就引入了水平集函数,引入水平集函数后,并加上 λ 1 \lambda 1 λ1和 λ 2 \lambda 2 λ2所代表的正则项后的能量函数则如下: F ( ϕ ( x , y ) ) = μ ∫ Ω ∣ ∇ H ( ϕ ( x , y ) ) ∣ d x d y + ν ∫ Ω H ( ϕ ( x , y ) d x d y + λ 1 ∫ Ω ∣ I 0 ( x , y ) − C 1 ∣ 2 H ( ϕ ( x , y ) d x d y + λ 2 ∫ o u t s i d e ( C ) ∣ I 0 ( x , y ) − C 2 ∣ 2 ( 1 − H ( ϕ ( x , y ) ) d x d y F(\phi(x,y)) =\mu \int_\Omega{|\nabla H(\phi(x,y))|}dxdy + \nu \int_\Omega{H( \phi(x,y)}dxdy \\ + \lambda_1 \int_{\Omega}{|I_0(x,y)-C_1|^2 H( \phi(x,y)}\,{\rm d}x{\rm d}y + \\ \lambda_2 \int_{outside(C)}{|I_0(x,y)-C_2|^2 (1-H( \phi(x,y))}\,{\rm d}x{\rm d}y F(ϕ(x,y))=μ∫Ω∣∇H(ϕ(x,y))∣dxdy+ν∫ΩH(ϕ(x,y)dxdy+λ1∫Ω∣I0(x,y)−C1∣2H(ϕ(x,y)dxdy+λ2∫outside(C)∣I0(x,y)−C2∣2(1−H(ϕ(x,y))dxdy,然后进行第二步,根据变分法和梯度下降流来求解泛函极值就可以获得如下的演化方程 ∂ ϕ ∂ t = δ ϵ ( ϕ ) [ μ d i v ( ∇ ϕ ∣ ∇ ϕ ∣ ) − ν − λ 1 ( I − C 1 ) 2 + λ 2 ( I − C 2 ) 2 ] \frac{\partial \phi}{\partial t} = \delta_{\epsilon}(\phi)[\mu div(\frac{\nabla\phi}{|\nabla\phi|})-\nu - \lambda_1(I-C_1)^2+\lambda_2(I-C_2)^2] ∂t∂ϕ=δϵ(ϕ)[μdiv(∣∇ϕ∣∇ϕ)−ν−λ1(I−C1)2+λ2(I−C2)2],最后将上述演化方程离散化后,就可以进行编写代码啦! 具体有关利用Chan-Vese模型进行曲线演化的方法可以参见我的另一篇博客基于区域的主动轮廓模型_从零到一用python实现Chan-Vese(CV)算法。