日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【主动轮廓模型(二)】《GVF Snake》算法原理与OpenCV实现

發布時間:2023/12/14 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【主动轮廓模型(二)】《GVF Snake》算法原理与OpenCV实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 1 問題引入
    • 1.1 傳統Snake模型的缺陷
    • 1.2 亥姆霍茲定理(Helmholtz theorem)
  • 2 GVF Snake
    • 2.1 邊緣圖(Edge Map)
    • 2.2 梯度矢量流(Gradient Vector Flow,GVF)
    • 2.3 數值求解方法
  • 3 OpenCV實現


1 問題引入

1.1 傳統Snake模型的缺陷

傳統的Snake算法(參考博客)存在以下兩個主要缺陷,在《Snakes, Shapes, and Gradient Vector Flow》這篇文章中提出的GVF Snake模型解決了這兩個問題:

  • 初始輪廓必須在真實輪廓附近,或對初始位置敏感;
  • 很難進入凹陷的邊界。
  • 如圖1所示,文章中作者用一個U形輪廓作為示例來直觀解釋傳統Snake的缺陷。在圖(c)中可以看到,U形輪廓凹陷處的力達到了左右平衡即方向相反大小相同,無法使輪廓再繼續向凹陷處移動。

    我們知道,Snake算法的解就是將輪廓點移動到某個確定位置,使得以下等式成立:

    Fint+Fext(g)=0(1)F_{int} + F_{ext}^{(g)} = 0 \tag{1} Fint?+Fext(g)?=0(1)

    其中外部力Fext(g)F_{ext}^{(g)}Fext(g)?的選取對于Snake模型的表現有巨大影響,外部力又可以被分為兩種:靜態(static)和動態(dynamic)。其中靜態力從圖像數據計算并且不隨模型的更新改變,動態力是隨著模型更新而改變的力。傳統的Snake模型外部力就是一種靜態力,GVF Snake中所描述的外部力也是一種靜態力,它不會隨時間變化或依賴于Snake模型輪廓的位置

    1.2 亥姆霍茲定理(Helmholtz theorem)

    GVF Snake中所描述外部力的數學原理來自于亥姆霍茲定理,即最一般的靜態向量場可以被分解為兩個分量:無旋(無旋度)分量和無散(無散度)分量

    由于傳統Snake模型的變分公式長生的外力是勢函數的梯度,因此它必須作為靜態無旋場加入力平衡方程(公式(1))。因此,可以通過允許包括無旋分量和無散分量來獲得更一般的靜態場。文章中,設計了一個外力場,使其具有大的捕獲范圍的同時又具有指向邊界凹陷的力。

    2 GVF Snake

    GVF Snake中定義Fext(g)=v(x,y)F_{ext}^{(g)}=\mathbf{v}(x,y)Fext(g)?=v(x,y),僅這里與傳統的Snake不同,稱為梯度矢量流(Gradient Vector Flow,GVF)

    xt(s,t)=αx′′(s,t)?βx′′′′(s,t)+v(2)x_t(s,t)=\alpha x^{''}(s,t)-\beta x^{''''}(s,t)+\mathbf{v} \tag{2} xt?(s,t)=αx′′(s,t)?βx′′′′(s,t)+v(2)

    求解上述方程的參數曲線即為GVF Snake,求解方式與傳統的Snake相同。由于v(x,y)\mathbf{v}(x,y)v(x,y)通常不是一個無旋場,因此該方程通常不表示(1)中的能量最小化問題的歐拉方程。

    2.1 邊緣圖(Edge Map)

    方法很多,比如可以用:

    f(x,y)=?Eext(i)(x,y)(3)f(x,y)=-E_{ext}^{(i)}(x,y) \tag{3} f(x,y)=?Eext(i)?(x,y)(3)

    2.2 梯度矢量流(Gradient Vector Flow,GVF)

    定義GVF為使以下能量函數最小化的矢量場v(x,y)=[u(x,y),v(x,y)]\mathbf{v}(x,y)=[u(x,y),v(x,y)]v(x,y)=[u(x,y),v(x,y)]

    ε=∫∫μ(ux2+uy2+vx2+vy2)+∣?f∣2∣v??f∣2dxdy(4)\varepsilon = \int \int \mu (u_x^2+u_y^2+v_x^2+v_y^2)+| \nabla f |^2| \mathbf{v} - \nabla f |^2 dxdy \tag{4} ε=∫∫μ(ux2?+uy2?+vx2?+vy2?)+∣?f2v??f2dxdy(4)

    其中,?f=[fx,fy]\nabla f=[f_x,f_y]?f=[fx?,fy?],表示邊緣圖像(edge map)的梯度,任何圖像梯度算子都可以被用來計算這個變量。ux/uyu_x/u_yux?/uy?、vx/vyv_x/v_yvx?/vy?為GVF得到的梯度場在(x,y)(x,y)(x,y)位置上xxxyyy方向上的梯度值,由拉普拉斯方程計算得到,且其初始值定義為?f\nabla f?f,即原圖像的二階導??梢钥吹?#xff1a;

    • ?f\nabla f?f很小時,能量由矢量場偏導數的平方和決定,從而產生一個緩慢變化的場;
    • ?f\nabla f?f很大時,第二項占被積函數的主導地位,通過設置v=?f\mathbf{v}=\nabla fv=?f可將其最小化,這可以再邊緣圖較大時保持幾乎等于邊緣圖的梯度,而在均勻區域中緩慢變化。

    參數μ\muμ是控制被積函數中第一項和第二項之間權衡的正則化參數,應根據圖像中存在的噪聲量來設置(噪聲越大μ\muμ應越大)。可以預期由此最小化產生的矢量場既不是完全無旋場也不是完全無散場??梢酝ㄟ^求解以下歐拉方程來求解GVF場(公式(4)):

    {μ?2u?(u?fx)(fx2+fy2)=0μ?2v?(v?fy)(fx2+fy2)=0(5)\begin{cases} \mu \nabla ^2 u - (u-f_x)(f_x^2+f_y^2) = 0 \\ \mu \nabla ^2 v - (v-f_y)(f_x^2+f_y^2) = 0 \end{cases} \tag{5} {μ?2u?(u?fx?)(fx2?+fy2?)=0μ?2v?(v?fy?)(fx2?+fy2?)=0?(5)

    其中?2\nabla ^2?2為拉普拉斯算子。

    2.3 數值求解方法

    uuuvvv看作時間的函數,可以將公示(5)(對應原文中公式(13a)、(13b))轉化為:

    {ut(x,y,t)=μ?2u(x,y,t)?[u(x,y,t)?fx(x,y)]?[fx(x,y)2+fy(x,y)2]vt(x,y,t)=μ?2v(x,y,t)?[v(x,y,t)?fy(x,y)]?[fx(x,y)2+fy(x,y)2](6)\begin{cases} u_t(x,y,t)=\mu \nabla^2 u(x,y,t)-[u(x,y,t)-f_x(x,y)]\cdot[f_x(x,y)^2+f_y(x,y)^2] \\ v_t(x,y,t)=\mu \nabla^2 v(x,y,t)-[v(x,y,t)-f_y(x,y)]\cdot[f_x(x,y)^2+f_y(x,y)^2] \end{cases} \tag{6} {ut?(x,y,t)=μ?2u(x,y,t)?[u(x,y,t)?fx?(x,y)]?[fx?(x,y)2+fy?(x,y)2]vt?(x,y,t)=μ?2v(x,y,t)?[v(x,y,t)?fy?(x,y)]?[fx?(x,y)2+fy?(x,y)2]?(6)

    上式進一步簡化:

    {ut(x,y,t)=μ?2u(x,y,t)?b(x,y)u(x,y,t)+c1(x,y)vt(x,y,t)=μ?2v(x,y,t)?b(x,y)v(x,y,t)+c2(x,y)(7)\begin{cases} u_t(x,y,t)=\mu \nabla^2 u(x,y,t)-b(x,y)u(x,y,t)+c^1(x,y) \\ v_t(x,y,t)=\mu \nabla^2 v(x,y,t)-b(x,y)v(x,y,t)+c^2(x,y) \end{cases} \tag{7} {ut?(x,y,t)=μ?2u(x,y,t)?b(x,y)u(x,y,t)+c1(x,y)vt?(x,y,t)=μ?2v(x,y,t)?b(x,y)v(x,y,t)+c2(x,y)?(7)

    其中,

    {b(x,y)=fx(x,y)2+fy(x,y)2c1(x,y)=b(x,y)fx(x,y)c2(x,y)=b(x,y)fy(x,y)(8)\begin{cases} b(x,y)=f_x(x,y)^2+f_y(x,y)^2 \\ c^1(x,y)=b(x,y)f_x(x,y) \\ c^2(x,y)=b(x,y)f_y(x,y) \end{cases} \tag{8} ????b(x,y)=fx?(x,y)2+fy?(x,y)2c1(x,y)=b(x,y)fx?(x,y)c2(x,y)=b(x,y)fy?(x,y)?(8)

    公式(7)中的系數b(x,y)b(x,y)b(x,y)、c1(x,y)c^1(x,y)c1(x,y)c2(x,y)c^2(x,y)c2(x,y)在整個迭代過程中是固定的,只需要計算一次。為方便計算,作以下假設:

    {i,j,n:對應x、y、tΔx、Δy:像素間隔spacingΔt:每次迭代的時間間隔\begin{cases} i,j,n: 對應x、y、t \\ \Delta x、\Delta y: 像素間隔spacing \\ \Delta t: 每次迭代的時間間隔 \end{cases} ????i,j,n:對應x、y、tΔx、Δy:像素間隔spacingΔt:每次迭代的時間間隔?

    則每次迭代的偏微分方程可以寫為:

    {ut=1Δt(ui,jn+1?ui,jn)vt=1Δt(vi,jn+1?vi,jn)?2u=1ΔxΔy(ui+1,j+ui,j+1+ui?1,j+ui,j?1?4ui,j)?2v=1ΔxΔy(vi+1,j+vi,j+1+vi?1,j+vi,j?1?4vi,j)(9)\begin{cases} u_t=\frac{1}{\Delta t} (u_{i,j}^{n+1} - u_{i,j}^n) \\ v_t=\frac{1}{\Delta t} (v_{i,j}^{n+1} - v_{i,j}^n) \\ \nabla^2u = \frac{1}{\Delta x \Delta y}(u_{i+1,j}+u_{i,j+1}+u_{i-1,j}+u_{i,j-1}-4u_{i,j}) \\ \nabla^2v = \frac{1}{\Delta x \Delta y}(v_{i+1,j}+v_{i,j+1}+v_{i-1,j}+v_{i,j-1}-4v_{i,j}) \end{cases} \tag{9} ????ut?=Δt1?(ui,jn+1??ui,jn?)vt?=Δt1?(vi,jn+1??vi,jn?)?2u=ΔxΔy1?(ui+1,j?+ui,j+1?+ui?1,j?+ui,j?1??4ui,j?)?2v=ΔxΔy1?(vi+1,j?+vi,j+1?+vi?1,j?+vi,j?1??4vi,j?)?(9)

    將這些近似值帶入公式(7)可以得出GVF的迭代解:

    {ui,jn+1=(1?bi,jΔt)ui,jn+r(ui+1n+ui,j+1n+ui?1,jn+ui,j?1n?4ui,jn)+ci,j1Δtvi,jn+1=(1?bi,jΔt)vi,jn+r(vi+1n+vi,j+1n+vi?1,jn+vi,j?1n?4vi,jn)+ci,j2Δt(10)\begin{cases} u_{i,j}^{n+1}=(1-b_{i,j}\Delta t)u_{i,j}^n+r(u_{i+1}^n+u_{i,j+1}^n+u_{i-1,j}^n+u_{i,j-1}^n-4u_{i,j}^n)+c_{i,j}^1 \Delta t \\ v_{i,j}^{n+1}=(1-b_{i,j}\Delta t)v_{i,j}^n+r(v_{i+1}^n+v_{i,j+1}^n+v_{i-1,j}^n+v_{i,j-1}^n-4v_{i,j}^n)+c_{i,j}^2 \Delta t \end{cases} \tag{10} {ui,jn+1?=(1?bi,j?Δt)ui,jn?+r(ui+1n?+ui,j+1n?+ui?1,jn?+ui,j?1n??4ui,jn?)+ci,j1?Δtvi,jn+1?=(1?bi,j?Δt)vi,jn?+r(vi+1n?+vi,j+1n?+vi?1,jn?+vi,j?1n??4vi,jn?)+ci,j2?Δt?(10)

    其中:

    r=μΔtΔxΔy(11)r=\frac{\mu \Delta t}{\Delta x \Delta y} \tag{11} r=ΔxΔyμΔt?(11)

    為了保證收斂,必須確保Δt≤ΔxΔy4μ\Delta t \leq \frac{\Delta x \Delta y}{4\mu}Δt4μΔxΔy?。

    3 OpenCV實現

    這里給出作為外力的梯度矢量流(GVF)的OpenCV實現。

    std::vector<cv::Mat> GVFSnake::GVF(cv::Mat edgeImg, double mu, int iterNum) {cv::Mat fImg = edgeImg.clone();fImg.convertTo(fImg, CV_32FC1);// a.Calculate the gradient of the edge mapqDebug() << "Calculate the gradient of the edge map";cv::Mat fx, fy;cv::Sobel(fImg, fx, fImg.depth(), 1, 0, 1, 0.5, 0, cv::BORDER_CONSTANT); // fImg must be CV_32FC1 formatcv::Sobel(fImg, fy, fImg.depth(), 0, 1, 1, 0.5, 0, cv::BORDER_CONSTANT);// b.Squared magnitude of the gradient fieldqDebug() << "Squared magnitude of the gradient field";cv::Mat SqrMagf = fx.mul(fx) + fy.mul(fy);// c.Initialize GVF to the gradientqDebug() << "Initialize GVF to the gradient";cv::Mat u = fx.clone();cv::Mat v = fy.clone();// d.Iteratively solve for the GVF u,vqDebug() << "Iteratively solve for the GVF u,v";for (int i = 0; i < iterNum; i++){// equal to del2 in matlabcv::Mat mKernal = (cv::Mat_<float>(3, 3) << 0, 1 / 4, 0,1 / 4, -1, 1 / 4,0, 1 / 4, 0);cv::Mat uLap, vLap;cv::filter2D(u, uLap, u.depth(), mKernal);cv::filter2D(v, vLap, v.depth(), mKernal);// why *4 ? ref: https://blog.csdn.net/qq_41634276/article/details/80659218u += mu * 4 * uLap - SqrMagf.mul(u - fx);v += mu * 4 * vLap - SqrMagf.mul(v - fy);}std::vector<cv::Mat> uvMatVector;uvMatVector.push_back(u);uvMatVector.push_back(v);return uvMatVector; }

    總結

    以上是生活随笔為你收集整理的【主动轮廓模型(二)】《GVF Snake》算法原理与OpenCV实现的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。