GrabCut算法详解:从GMM模型说起

GrabCut算法详解:从GMM模型说起

最近正在学习CG,争取有时间就看点论文写写代码。

GrabCut在OpenCv里面是有内置函数的,不过我还是用C++纯手工实现了一边原汁原味的论文,github链接GrabCut,里面有具体的实现代码和步骤,还有实现结果,欢迎来hack

简介

GrabCut是04年的一篇文章,是少数用传统方法~~(对,就是没用神经网络的意思)~~解决前景和背景分离的算法。

需要的前置知识有:

  1. 混合多高斯模型

  2. 最小割集合划分

下面先介绍这两个模型

备注:本文不含任何数学证明,仅仅介绍算法,如果想要严格证明请移步百度

GMM模型

多维单高斯模型和混合模型

平平无奇的一手公式:维数是 D D D,均值是 μ \mu μ,协方差 Σ \Sigma Σ,参数集合 θ = { μ , Σ } \theta=\{\mu, \Sigma\} θ={μ,Σ}

X ∼ N ( μ , Σ ) : P ( x ∣ θ ) = ϕ ( x ∣ μ , Σ ) = 1 ( 2 π ) D / 2 s q r t ∣ Σ ∣ e x p { ( x − μ ) T Σ − 1 ( x − μ ) } X\sim N(\mu,\Sigma):P(x|\theta)=\phi(x|\mu,\Sigma)=\frac{1}{(2\pi)^{D/2} sqrt{|\Sigma}|}exp\{(x-\mu)^T\Sigma^{-1}(x-\mu)\} XN(μ,Σ):P(xθ)=ϕ(xμ,Σ)=(2π)D/2sqrt∣Σ1exp{(xμ)TΣ1(xμ)}

其实混合模型就是字面意思,把很多个模型通过一定的概率混合起来,我们首先定义模型的个数 K K K,那么参数集合就变成了 θ = { μ k , Σ k , π k } \theta=\{\mu_k,\Sigma_k,\pi_k\} θ={μk,Σk,πk},其中 π k \pi_k πk是第 k k k个模型的混合加权系数

P ( x ∣ θ ) = ∑ k K π k ϕ ( x ∣ μ k , Σ k ) P(x|\theta)=\sum_k^K\pi_k\phi(x|\mu_k,\Sigma_k) P(xθ)=kKπkϕ(xμk,Σk)

混合高斯模型的应用和EM算法

应用很简单:聚类。也就是如果我们假设一堆数据恰好分成K堆并且可以看成每类都是正太分布,那么如果能用GMM模型去拟合这些数据,我们只需要算出每个数据属于某个高斯模型的概率,就可以把这些数据分类了。

拟合的算法有一个经典的EM算法。本质似乎是最大似然概率优化。不过本文通过Local/Global的视角去看待这个算法。

EM算法

输入:数据 z 1 ⋯ z n z_1\cdots z_n z1zn和指定的参数 K K K

输出:拟合参数 θ = { μ k , Σ k , π k } \theta = \{\mu_k,\Sigma_k,\pi_k\} θ={μk,Σk,πk}

  1. 初始化参数,包括正则化数据,随机化均值,单位化方差和混合比

  2. Esitimate步骤,计算后验概率 γ j k \gamma_{jk} γjk

  • γ j k = π k ϕ ( z j ∣ θ k ) ∑ k K π k ϕ ( z i ∣ θ k ) \gamma_{jk}=\frac{\pi_k\phi(z_j|\theta_k)} {\sum_k^K\pi_k \phi(z_i|\theta_k)} γjk=kKπkϕ(ziθk)πkϕ(zjθk)
  1. Maximize步骤,根据后验概率计算新的均值和协方差矩阵以及混合比
  • μ k n e w = ∑ i N γ i k x i ∑ i N γ i k \mu_{k}^{new}=\frac{\sum_i^N\gamma_{ik}x_i}{\sum_i^N \gamma_{ik}} μknew=iNγikiNγikxi

  • Σ k n e w = ∑ i N γ i k ( x i − μ k n e w ) ( x i − μ k n e w ) T ∑ i N γ i k \Sigma_{k}^{new}=\frac{\sum_i^N\gamma_{ik}(x_i-\mu_k^{new})(x_i-\mu_k^{new} )^T}{\sum_i^N\gamma_{ik}} Σknew=iNγikiNγik(xiμknew)(xiμknew)T

  • π k n e w = ∑ i N γ i k / n \pi_k^{new}=\sum_i^N\gamma_{ik}/n πknew=iNγik/n

  1. 重复第2步,一直到收敛

这个算法用Local/Global理解非常make sense。也就是先固定参数,计算出对应的每个数据属于某个模型的概率(Local Phase),计算好概率之后,再用对应的概率和数据去更新均值和协方差矩阵以及混合概率。

最小割集合划分

输入:大小为 n n n的集合 S S S,对于集合的一个划分 A / B A/B A/B,定义能量贡献如下:

  1. w ( i ) = [ i ∈ A ] A i + [ i ∈ B ] B i w(i)=[i\in A]A_i+[i\in B]B_i w(i)=[iA]Ai+[iB]Bi,也就是每个元素分到某个集合有一定的代价。

  2. e ( i , j ) = [ α i ≠ α j ] w i j e(i,j)=[\alpha_i\neq \alpha_j]w_{ij} e(i,j)=[αi=αj]wij α \alpha α表示 i i i的归属。也就是若干对元素,如果他们不在同一个集合,那么有一定的代价

输出:一个划分,最小化能量。

算法:建图, S r c → i : A i , i → S i n k : B i , u n d i r e c t e d _ e d g e ( i , j , w i j ) Src\to i:A_i,i\to Sink:B_i,undirected\_edge(i,j,w_{ij}) Srci:Ai,iSink:Bi,undirected_edge(i,j,wij),求最小割即可。

经典算法了,不多解释

GrabCut算法

输入数据:

  1. 一张彩色图片,可以转化为三通道向量的二维表数据 z 1 ⋯ z N z_1\cdots z_N z1zN

  2. 用户交互,先圈定一段区域 T u T_u Tu,表示这个区域内可能是前景,剩下的部分 T B = T ˉ u T_B=\bar T_u TB=Tˉu,表示剩余部分一定是背景

输出数据:

一个 α i j ∈ { 0 , 1 } \alpha_{ij}\in\{0,1\} αij{0,1}透明度二维表,0表示背景,1表示前景

形式化问题

事实上,上述算法描述是很有问题,因为没有对一个分割做出评估,我并不知道哪个 α \alpha α表是最优的。

GrabCut算法的核心就是,把背景和前景分别看成GMM混合模型。并以GMM混合模型参数的拟合程度作为优化目标。

所以优化的参数列表就是,GMM的参数 θ = { μ ( α , k ) , π ( α , k ) , Σ ( α , k ) } \theta=\{\mu(\alpha, k),\pi(\alpha, k), \Sigma(\alpha, k)\} θ={μ(α,k),π(α,k),Σ(α,k)},以及每个像素的透明度 α n ∈ { 0 , 1 } \alpha_n\in\{0,1\} αn{0,1}和分类 k n ∈ { 0 ⋯ K − 1 } k_n\in\{0\cdots K-1\} kn{0K1}(属于第几个高斯模型),也就是每一类的混合高斯模型参数。其中 K K K取5。

对于这些参数,我们可以首先定义一个能量函数

U ( α , θ , k , z ) = ∑ n D ( α n , k n , θ , z n ) U(\alpha, \theta, k, z)=\sum_n D(\alpha_n,k_n,\theta,z_n) U(α,θ,k,z)=nD(αn,kn,θ,zn)

其中

D ( α n , k n , θ , z n ) = − log ⁡ p ( z n ∣ α n , k n , θ ) − log ⁡ π ( α n , k n ) = − log ⁡ π ( α n , k n ) + log ⁡ d e t ( Σ ( α n , k n ) ) / 2 + [ z n − μ ( α n , k n ) ] T Σ ( α n , k n ) [ z n − μ ( α n , k n ) ] / 2 D(\alpha_n, k_n,\theta, z_n)=-\log p(z_n|\alpha_n,k_n,\theta)-\log \pi(\alpha_n,k_n)\\ =-\log \pi(\alpha_n,k_n)+\log det(\Sigma(\alpha_n,k_n))/2 +[z_n-\mu(\alpha_n,k_n)]^T\Sigma(\alpha_n,k_n)[z_n-\mu(\alpha_n,k_n)]/2 D(αn,kn,θ,zn)=logp(znαn,kn,θ)logπ(αn,kn)=logπ(αn,kn)+logdet(Σ(αn,kn))/2+[znμ(αn,kn)]TΣ(αn,kn)[znμ(αn,kn)]/2

也就是第k类的混合加权系数以及在这一类的高斯分布的概率密度的log值

当然,除了这个部分以外,分割还关心的是边界的情况,所以论文还定义了另一个能量函数来描述边界的情况

V ( α , z ) = γ ∑ ( m , n ) ∈ C [ α n ≠ α m ] e x p − β ∣ ∣ z m − z n ∣ ∣ 2 V(\alpha,z)=\gamma \sum_{(m,n)\in C}[\alpha_n\neq \alpha_m]exp-\beta||z_m-z_n||^2 V(α,z)=γ(m,n)C[αn=αm]expβ∣∣zmzn2

C C C是8相邻的像素, γ \gamma γ一般取50,后面那一项实际上表示,边界相差越大,分割得越好,能量越小。

所以 β \beta β参数就应该是图上相邻像素相差的平均情况,也就是 β = ( 2 < ∣ ∣ z m − z n ∣ ∣ 2 > ) − 1 , < ⋅ > \beta=(2<||z_m-z_n||^2>)^{-1},<\cdot> β=(2<∣∣zmzn2>)1,<>表示在全图上的期望

那么最终的能量优化目标就是

E ( α n , k n , θ , z n ) = U ( α , θ , k , z ) + V ( α , z ) E(\alpha_n,k_n,\theta,z_n)=U(\alpha,\theta, k, z)+V(\alpha, z) E(αn,kn,θ,zn)=U(α,θ,k,z)+V(α,z)

我们先上算法,目前还未实现border matting,只实现了硬分割

算法流程

GrabCut算法详解:从GMM模型说起_第1张图片

初始化

对于用户给予的初始分割,我们可以把两个区域内的像素看成数据,并应用GMM算法估计出两个区域内的GMM模型

经典的Local/Global模型

接下来的步骤是不断迭代如下过程,直到能量函数收敛

  1. 先固定GMM参数 θ \theta θ,我们算出每个点属于哪个高斯模型的概率最高。

  2. 得到了k,我们根据每一类的数据,反推出每一类的参数 θ \theta θ,也就是分别计算每类的均值 μ \mu μ和方差 Σ \Sigma Σ

  3. 现在我们确定优化了 k , μ , Σ k,\mu,\Sigma k,μ,Σ,固定前面这些参数,我们优化 α \alpha α以最小化 E E E

具体地,我们可以发现, E E E的模型在 k , μ , Σ k,\mu, \Sigma k,μ,Σ确定的情况下, α = 0 , 1 \alpha=0,1 α=0,1的代价是固定的,而 V V V则相当于是在划分不同类的时候产生贡献。这就是我们的最小割模型,因此得以解决。

你可能感兴趣的:(计算机图形学,c++,计算机视觉)