外文原址:

https://

wiseodd。github。io/techb

log/2016/11/20/levelset-segmentation/

Part 2 :影象分割

上一章我們先感性後理性地認識了LSM,它可以應用在很多方面,如波的模擬、野火模擬、氣體模擬。本章我們將研究水平集方法在計算機視覺中的應用——影象分割。

基於LSM的影象分割

回憶下上一章中推導的曲面演化偏微分方程,式(1):

ϕ′=ϕ+ΔtF∥∇ϕ∥

式(1)中的F速度函式(力函式)是需要特別關注的地方,需要針對不同的應用設計不同的F函式。直觀理解,F就是推動曲線演變的力。換句話說,我們可以將F理解為速度場,F描述了ϕ曲面上 每一個點的運動速度和方向(結合法向量,方向向量為單位向量,也即用1、-1來指示方向,關鍵還是靠F來推動演化)

當要分割一幅影象時,我們需要 從影象中推匯出函式F。假設我們有一張圖:

水平集_影象分割_2

圖1

由於F是一個速度場,考慮到需要求解的偏微分方程PDE(1),我們希望F在遠離目標輪廓時變化快,在目標輪廓附近時變化慢。

一種從 影象中推導F的方法是藉助 邊緣檢測。邊緣檢測最簡單 的方式是 取影象的梯度,式(2):

(這個公式的意思就是梯度越大演化速度越慢,因為此時處於邊界附近;梯度越小演化速度越快,因為此時距離邊界較遠)

水平集_影象分割_2

Sooooooo,let‘s do it:

Import numpy as np

Import scipy。ndimage

Import scipy。signal

Import matplotlib。pyplot as plt

From skimage import color,io

Def grad(x):

Return np。array(np。gradient(x)) # 這個結果是2通道的哦

Def norm(x,axis=0):

Return np。sqrt(np。sum(np。square(x),axis=axis))#橫縱兩個方向的梯度正則化為1個值

Def stopping_fun(x): #F函式

Return 1。/(1。+norm(grad(x))**2)

img = io。imread(’twoObj。bmp‘)

img = color。rgb2gray(img)

img = img - np。mean(img)

# Smooth the image to reduce noise and separation between noise and edge #becomes clear

img_smooth = scipy。ndimage。filters。gaussian_filter(img, sigma)

F = stopping_fun(img_smooth)

水平集_影象分割_2

圖2

有了F函式,我們就可以將其直接用於PDE的求解了:

Def default_phi(x):

Phi=np。ones(x。shape[:2])

Phi[5:-5,5:-5]=-1。

Return phi

n_iter=1000

Dt=1。

for i in range(n_iter):

dphi = grad(phi)

dphi_norm = norm(dphi)

dphi_t = F * dphi_norm

phi = phi + dt * dphi_t

多次迭代後,結果如下:

水平集_影象分割_2

圖3

這是一個非常簡單的水平集分割方法。應用 更加複雜的F函式我們將得到更好 的結果。

測地線活動模型

在Geodesic Active Contour(GAC)模型中,F函式定義如下,式(3):

水平集_影象分割_2

式中,第一項為平滑項,它使曲線 沿曲率方向移動;第二項是氣球項,用於控制曲線的演化速度;最後一項是附加項,用於幫助曲線收斂

# 曲率是這麼計算的哦

Def curvature(f):

fy,fx=grad(f)

Norm=np。sqrt(fx**2+fy**2)

Nx=fx/(Norm+1e-8)

Ny=fy/(Norm+1e-8)

Return div(Nx,Ny)

Def div(fx,fy):

# 影象的散度對某幅影象連續求2次梯度得到的zx_x和zy_y的和是等於散度的。換句話說div(z) = zx_x +zy_y

Fyy,fyx=grad(fy)

Fxy,fxx=grad(fx)

Return fxx+fyy

Def dot(x,y,axis=0):

Return np。sum(x*y,axis=axis)

v=1。

Dt=1。

g=stopping_fun(img_smooth)#g=stopping_fun(img_smooth,alpha)

dg=grad(g)

for i in range(n_iter):

dphi = grad(phi)

dphi_norm = norm(dphi)

kappa = curvature(phi)

smoothing = g * kappa * dphi_norm

balloon = g * dphi_norm * v

attachment = dot(dphi, dg)

dphi_t = smoothing + balloon + attachment

phi = phi + dt * dphi_t

以下為分割結果:

水平集_影象分割_2

圖4

觀測發現,該分割結果比圖3更好,也即更平滑更貼合目標了

本章,我們實現了一個LSM在影象分割中的案例。我們發現 不同的速度函式F將實現不同的分割結果。