基于边缘的主动轮廓模型——从零到一用python实现snake
從零到一實(shí)現(xiàn)snake算法
- 1、Snake算法原理
- 2、基于曲線演化的實(shí)現(xiàn)方法
- 2.1演化方程推導(dǎo)
- 2.2離散化過程
- 2.3 代碼實(shí)現(xiàn)
- 3、基于水平集的實(shí)現(xiàn)方法
- 4、討論與分析
- 源碼地址[snake](https://github.com/woshimami/snake)
1、Snake算法原理
Kass等人1最早于1988年提出了主動輪廓模型,該方法通過構(gòu)造能量函數(shù),從而將圖像分割轉(zhuǎn)化為求解能量泛函極值的問題,其核心思想在于,作者認(rèn)為和之前的分割方法相比,在不同的圖像解讀(image interpretation)任務(wù)中,表觀或者淺層次(low level)的圖像判讀任務(wù)應(yīng)該需要一些深層次(high level)的圖像信息,并論文[1]中進(jìn)行了舉例分析,有興趣的同學(xué)可以自行翻閱論文查看,這也和主動輪廓模型的兩大特點(diǎn)不謀而合:全局性和可拓展性。全局性也就是說在圖像處理任務(wù)進(jìn)行中,不僅要關(guān)注局部區(qū)域或者邊緣信息,同樣也要關(guān)注圖像或曲線的整體信息如曲線整體的長度和曲率等。再者針對不同的圖像特點(diǎn),能夠設(shè)計或者添加個性化的分割策略,接下來我將根據(jù)公式對此進(jìn)一步分析。
對于圖像I(x,y),C(s)=C(x(s),y(s))I(x,y),C(s)=C(x(s),y(s))I(x,y),C(s)=C(x(s),y(s))為演化曲線,定義snake模型的能量函數(shù)為:Esnake=Eint+EextE_{snake}= E_{int}+E_{ext}Esnake?=Eint?+Eext? 這里我們區(qū)分內(nèi)部能量和外部能量的依據(jù)就是看它是否和演化曲線本身的特性相關(guān)。比如說下式中,定義內(nèi)部能量項的兩部分內(nèi)容分別代表的就是曲線的長度和曲率: Eint=∫0112?(α(s)∣cs(s)∣2+β(s)∣css(s)∣2)dsE_{int} =\int_0^1 \frac{1}{2}* {(\alpha(s)|c_s(s)|^2+\beta(s)|c_{ss}(s)|^2)} \,{\rm d}s Eint?=∫01?21??(α(s)∣cs?(s)∣2+β(s)∣css?(s)∣2)ds 其中公式中的兩項內(nèi)容分別表示的就是曲線的長度項和曲線的光滑程度, α(s)\alpha(s)α(s)和β(s)\beta(s)β(s)可以根據(jù)曲線上某一點(diǎn)的特征進(jìn)行個性化處理,但是大多數(shù)情況下我們一般定義它們?yōu)槌?shù),用于調(diào)節(jié)曲線長度項和光滑程度占比。
而外部能量項通常由兩部分組成構(gòu)成:Eext=Eimg+EconsE_{ext} = E_{img}+E_{cons}Eext?=Eimg?+Econs? EimgE_{img}Eimg?通常表示和圖像相關(guān)的外部能量項目,主要包含如下三種信息,
(1)
最后還有一個限制項EconE_{con}Econ?,這一項就是對曲線演化添加一定的限制作用,比如限制整體曲線到某一點(diǎn)或者某一區(qū)域RRR的距離:Econ=∫01∣∣C(x(s),y(s))?R∣∣dsE_con = \int_0^1{||C(x(s),y(s))-R||}\,{\rm d}sEc?on=∫01?∣∣C(x(s),y(s))?R∣∣ds具體的情況大家可以根據(jù)圖片特點(diǎn)或者需求靈活定義。
2、基于曲線演化的實(shí)現(xiàn)方法
好了,終于到了激動人心的實(shí)現(xiàn)環(huán)節(jié)了,大家是不是跟我一樣激動的直搓手,哈哈哈哈哈哈哈
開始之前我先說明兩點(diǎn)內(nèi)容:1)本次實(shí)現(xiàn)過程基于較為簡單基礎(chǔ)的能量泛函,大家可以先實(shí)現(xiàn)體驗(yàn)一邊,然后再觸類旁通,舉一反三;2)以方面需要對一些數(shù)學(xué)知識進(jìn)行回顧分析,另一方面希望大家仔細(xì)品一品從連續(xù)到離散的變化過程。
2.1演化方程推導(dǎo)
首先我們定義能量函數(shù):Esnake=∫0112?(α∣cs(s)∣2+β∣css(s)∣2?∣?I(x(s),y(s))∣2)dsE_{snake} =\int_0^1 \frac{1}{2}* {(\alpha|c_s(s)|^2+\beta|c_{ss}(s)|^2 -|\nabla{I(x(s),y(s))}|^2)}\,{\rm d}sEsnake?=∫01?21??(α∣cs?(s)∣2+β∣css?(s)∣2?∣?I(x(s),y(s))∣2)ds,當(dāng)能量函數(shù)最小時,就可以獲得C(x(s),y(s))C(x(s),y(s))C(x(s),y(s))的曲線方程,本質(zhì)上這也是一個求能量泛函極值的問題,直接根據(jù)歐拉-拉格朗日方程(變分原理),當(dāng)能量泛函取極值時,應(yīng)滿足:?αc′′(s)+βc′′′′(ss)+?Eext=0-\alpha c^{''}(s)+\beta c^{''''}(ss)+\nabla E_{ext} = 0?αc′′(s)+βc′′′′(ss)+?Eext?=0 可是就算推到這種程度我們以然沒辦法直接求出曲線c(x(s),y(s))c(x(s),y(s))c(x(s),y(s)),尤其是我們希望公式能夠以偏微分方程的形式出現(xiàn),這樣我們就可以利用計算機(jī)進(jìn)行編程序迭代計算了,于是我們在曲線中引入了一個輔組變量ttt,則解可以表示為c(t,s)c(t,s)c(t,s),隨時間變化的解c(t,s)c(t,s)c(t,s)應(yīng)該使得能量函數(shù)逐漸變小(推導(dǎo)過程后續(xù)會補(bǔ)充),從而可以得出:?c(s)?t=αc′′(s)?βc′′′′(ss)??Eext\frac{\partial c(s)}{\partial t} = \alpha c^{''}(s)-\beta c^{''''}(ss)-\nabla E_{ext} ?t?c(s)?=αc′′(s)?βc′′′′(ss)??Eext?
2.2離散化過程
接下來就是整個離散化過程了,首先,我們先明確一下概念,上式中的sss表示什么意思,因?yàn)槲覀兛吹降膱D片都是離散的點(diǎn),所以我們剛開定義初始化的snake曲線時,實(shí)際上定義的也就是一系列離散的點(diǎn)的集合,而曲線的演化過程實(shí)際上也就是這些固定數(shù)目的點(diǎn)的演化過程,離散化后,我們用iii表示sss,那假設(shè)初始化的snake曲線有NNN個點(diǎn),那i∈[0,N?1]i\in [0,N-1]i∈[0,N?1],且x[N]=x[0],x[N+1]=x[2]....x[N] = x[0],x[N+1]=x[2]....x[N]=x[0],x[N+1]=x[2]....,那么對于曲線上任一點(diǎn)c(x(i),y(i))c(x(i),y(i))c(x(i),y(i)):x′′[i]=x[i?1]?2x[i]+x[i+1]x^{''}[i] = x[i-1]-2x[i]+x[i+1]x′′[i]=x[i?1]?2x[i]+x[i+1] x′′′′[i]=x[i?2]?4x[i?1]+6x[i]?4x[i+1]+x[i+2]x^{''''}[i] = x[i-2]-4x[i-1]+6x[i]-4x[i+1]+x[i+2]x′′′′[i]=x[i?2]?4x[i?1]+6x[i]?4x[i+1]+x[i+2]對y也是同理,假設(shè)圖像xxx方向和yyy方向的梯度為G(x,y)G(x,y)G(x,y)(均為正值),那外部力則分別為Gx[x,y],Gy[x,y]G_{x}[x,y],G_{y}[x,y]Gx?[x,y],Gy?[x,y],假定每次迭代后,曲線變化較小,我們用Gt?1(x,y)G_{t-1}(x,y)Gt?1?(x,y)代替Gt(x,y)G_{t}(x,y)Gt?(x,y),那么對任一點(diǎn)c(x(i),y(i))c(x(i),y(i))c(x(i),y(i))就可以推導(dǎo)出離散后的公式為:
?xt[i]?t=α(xt[i?1]?2xt[i]+xt[i+1])+β(?xt[i?2]+4xt[i?1]?6xt[i]+4xt[i+1]?xt[i+2])+Gx(xt[i],yt[i])\frac{\partial x_t[i] }{\partial t} = α(x_t[i-1]-2xt[i]+x_t[i+1]) + β(-x_t[i-2]+4x_t[i-1]-6xt[i]+4x_t[i+1]-x_t[i+2]) + G_x(x_t[i],y_t[i])?t?xt?[i]?=α(xt?[i?1]?2xt[i]+xt?[i+1])+β(?xt?[i?2]+4xt?[i?1]?6xt[i]+4xt?[i+1]?xt?[i+2])+Gx?(xt?[i],yt?[i])用λ\lambdaλ表示步長,則可以進(jìn)一步表示為:xt[i]?xt?1[i]λ=α(xt[i?1]?2xt[i]+xt[i+1])+β(?xt[i?2]+4xt[i?1]?6xt[i]+4xt[i+1]?xt[i+2])+Gx(xt?1[i],yt?1[i])\frac{x_t[i] - x_{t-1}[i] }{\lambda} = α(x_t[i-1]-2xt[i]+x_t[i+1]) + β(-x_t[i-2]+4x_t[i-1]-6xt[i]+4x_t[i+1]-x_t[i+2]) + G_x(x_{t-1}[i],y_{t-1}[i])λxt?[i]?xt?1?[i]?=α(xt?[i?1]?2xt[i]+xt?[i+1])+β(?xt?[i?2]+4xt?[i?1]?6xt[i]+4xt?[i+1]?xt?[i+2])+Gx?(xt?1?[i],yt?1?[i])同理, yt[i]?yt?1[i]λ=α(yt[i?1]?2yt[i]+yt[i+1])+β(?yt[i?2]+4yt[i?1]?6yt[i]+4yt[i+1]?yt[i+2])+Gy(yt?1[i],yt?1[i])\frac{y_t[i] - y_{t-1}[i] }{\lambda} = α(y_t[i-1]-2yt[i]+y_t[i+1]) + β(-y_t[i-2]+4y_t[i-1]-6yt[i]+4y_t[i+1]-y_t[i+2]) + G_y(y_{t-1}[i],y_{t-1}[i])λyt?[i]?yt?1?[i]?=α(yt?[i?1]?2yt[i]+yt?[i+1])+β(?yt?[i?2]+4yt?[i?1]?6yt[i]+4yt?[i+1]?yt?[i+2])+Gy?(yt?1?[i],yt?1?[i]) ,如果一條曲線上有NNN個點(diǎn),那就對xxx和yyy分別列出NNN個式子,如果用矩陣表示的話,那就是:Xt?Xt?1λ=AXt+Gx(xt?1,yt?1)\frac{X_{t}-X_{t-1}}{\lambda} = AX_t + G_x(x_{t-1},y_{t-1})λXt??Xt?1??=AXt?+Gx?(xt?1?,yt?1?)矩陣A則為:(?2α+6βα+4β?β000??βα+4βα+4β?2α+6βα+4β?β00?0?β?βα+4β?2α+6βα+4β?β0?000?βα+4β?2α+6βα+4β?β?0000?βα+4β?2α+6βα+4β?00??????β00000??2α+6βα+4βα+4β?β0000?α+4β?2α+6β)\begin{pmatrix} -2\alpha+6\beta & \alpha+4\beta & -\beta & 0 & 0& 0 & \cdots & -\beta & \alpha+4\beta & \\ \alpha+4\beta & -2\alpha+6\beta & \alpha+4\beta & -\beta & 0& 0 & \cdots & 0 & -\beta & \\ -\beta & \alpha+4\beta & -2\alpha+6\beta & \alpha+4\beta & -\beta & 0 & \cdots & 0 & 0 & \\ 0 & -\beta & \alpha+4\beta & -2\alpha+6\beta & \alpha+4\beta & -\beta & \cdots & 0 & 0 & \\ 0 & 0 & -\beta & \alpha+4\beta & -2\alpha+6\beta & \alpha+4\beta & \cdots & 0 & 0 & \\ \vdots & \vdots & \vdots & \ddots & \vdots \\ -\beta & 0 &0 & 0 & 0& 0 & \cdots & -2\alpha+6\beta & \alpha+4\beta & \\ \alpha+4\beta & -\beta &0 & 0 & 0& 0 & \cdots & \alpha+4\beta & -2\alpha+6\beta & \\ \end{pmatrix} ???????????????2α+6βα+4β?β00??βα+4β?α+4β?2α+6βα+4β?β0?0?β??βα+4β?2α+6βα+4β?β?00?0?βα+4β?2α+6βα+4β?00?00?βα+4β?2α+6β?00?000?βα+4β00??????????β0000?2α+6βα+4β?α+4β?β000α+4β?2α+6β????????????????,求解矩陣即可得出:Xt=(1?λA)?1Xt?1+λGx(Xt?1,Yt?1)X_t = (1-\lambda A)^{-1}{X_{t-1}+\lambda G_x(X_{t-1},Y_{t-1})}Xt?=(1?λA)?1Xt?1?+λGx?(Xt?1?,Yt?1?) Yt=(1?λA)?1Yt?1+λGy(Xt?1,Yt?1)Y_t = (1-\lambda A)^{-1}{Y_{t-1}+\lambda G_y(X_{t-1},Y_{t-1})}Yt?=(1?λA)?1Yt?1?+λGy?(Xt?1?,Yt?1?)至此,需要的核心演化公式到手。
2.3 代碼實(shí)現(xiàn)
看完上面的離散化過程,是不是大家現(xiàn)在都胸有成竹,躍躍欲試,蠢蠢欲動啦,哈哈,接下來就讓我們一起開始愉快的coding吧。
聲明使用的依賴庫主要有:
代碼實(shí)現(xiàn)總共分為如下幾個步驟:
隨手用windows畫圖工具畫了個圓(簡約派):
然后讀入圖片,注意
計算結(jié)果,撒花,撒花,撒花!
3、基于水平集的實(shí)現(xiàn)方法
本來這一段打算拖一拖的,但是看到評論區(qū)有哥們兒問到了,我就仔細(xì)找了找文獻(xiàn),看看怎么給處理下,結(jié)果發(fā)現(xiàn)自己給自己挖了個大坑,對于原始的snake算法來講,使用level set并不是一個很可行的方案或者說需要對snake算法做一些改變,那么為什么將level set方法直接引用到snake模型上不合適呢?
1)首先,大家需要明白常見的主動輪廓模型的常見處理流程:1、構(gòu)建能量泛函; 2、極小化能量泛函(歐拉-拉格朗日方程+梯度下降法)獲得用于演化的偏微分方程; 3、離散化偏微分方程; 4、代碼實(shí)現(xiàn)與調(diào)試,一般都是從步驟1或者步驟2中引入level set,可以參見我的另一篇博客(水平集方法引入主動輪廓模型算法中的兩種方法);2)但是,對于原始的snake算法來講,只存在從步驟1即從能量函數(shù)中引入水平集函數(shù)的可能性,不過因?yàn)槟菢涌赡芴幚砥饋硖闊?#xff0c;所以后來Caselles 等人就在1993年直接對原始snake算法就行了調(diào)整,提出了改進(jìn)的幾何活動輪廓模型,不僅引入了水平集方法還擺脫了原始snake模型對參數(shù)的依賴問題。
因此,總的來說,將level set方法引入snake是理論上的可行性的,只不過比較麻煩,這個博主最近時間比較緊張,等過一段時間閑了再想辦法給實(shí)現(xiàn)下吧(又立flag…)。
4、討論與分析
接下來就讓我們愉快的討(tu)論(cao)下snake算法吧! 有一說一,不得不承認(rèn),Kass等人1當(dāng)初將圖像分割問題轉(zhuǎn)化為求解能量泛函極值的問題確實(shí)很有想象力,這個控制領(lǐng)域的李雅普諾夫函數(shù)簡直有異曲同工之妙之妙,很好奇當(dāng)時作者哪來的這么大的腦洞哈。
源碼地址snake
[1] (KASS,M. snake Active contour models[J]. Proc.first Intl Conf.computer Vision, 1988, 4.) [2] (Caselles V . Geometric models for active contours[C]// International Conference on Image Processing. IEEE Computer Society, 1995.)總結(jié)
以上是生活随笔為你收集整理的基于边缘的主动轮廓模型——从零到一用python实现snake的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: gvf snake matlab,GVF
- 下一篇: python如何进行人口预测_如何使用m