[圖形學]拉普拉斯網格變形(Laplace Deformation)原理及復現

本文原理參考論文: Laplacian Mesh Processing

本文復現參考:Mesh模型的Laplace Deformation(網格形變 - 拉普拉斯形變) - C++代碼實現


拉普拉斯網格變形是一個相當經典的工作,本工作復現了一下基礎的部分,這裏記錄下原理部分和結果。
復現結果演示如下:

在這裏插入圖片描述

拉普拉斯網格變形原理

可以用用一句話來解釋拉普拉斯網格變形的原理: 形變前的點的拉普拉斯座標與形變後的點的拉普拉斯座標儘可能相等。這句話裏面其實只有點的拉普拉斯座標是我們所不清楚的,下面闡述拉普拉斯座標爲何物。

拉普拉斯座標

拉普拉斯座標是一個相當簡單的概念,對於一個三角網格模型M=(V,E,F),V爲頂點集,E爲邊集,F爲三角面片集。V(v1,…vn)中每一個點的座標表示都是笛卡爾座標,下圖(源自論文Laplacian Mesh Processing)和公式定義了拉普拉斯座標的表示,點vi的笛卡爾座標減去所有vi的相鄰點vj的笛卡爾座標的平均值,di表示vi的相鄰點的個數。
圖源自論文Laplacian Mesh Processing

δi=(δi(x),δi(y),δi(z))=vi1dijN(i)vj \delta_{i}=\left(\delta_{i}^{(x)}, \delta_{i}^{(y)}, \delta_{i}^{(z)}\right)=\mathbf{v}_{i}-\frac{1}{d_{i}} \sum_{j \in N(i)} \mathbf{v}_{j}
拉普拉斯座標蘊含了網格模型中的細節信息,而細節信息正是我們在網格形變後不希望改變的,拉普拉斯網格變形正是基於這一約束。

拉普拉斯矩陣

拉普拉斯座標的計算我們可以按照上面的公式分別求解,但是爲了簡化計算,通常用矩陣乘法計算拉普拉斯座標。只需要定義拉普拉斯矩陣L,便可求解拉普拉斯座標 δ = L*V ( V表示所有點構成的笛卡爾座標矩陣)。下面給出L的定義:

L=ID1A L=I-D^{-1} A
其中,I爲單位矩陣,D矩陣是一個對角矩陣,對角線上的值Dii = di,di是第i個點的鄰接點數目 ,A 矩陣是鄰接矩陣。若點vi和vj相鄰,Aij = 1,若不相鄰,則 Aij = 0。
Aij={1(i,j)E0 otherwise  A_{i j}=\left\{\begin{array}{ll}{1} & {(i, j) \in E} \\ {0} & {\text { otherwise }}\end{array}\right.
在計算機中求矩陣的逆是比較麻煩的,因此再使用上面公式的時候我們通常兩邊同乘D將公式變成如下形式。之後便用Ls代替L。
LS=DL=DA L_{S}=D L=D-A

(LS)ij={dii=j1(i,j)E0 otherwise  \left(L_{S}\right)_{i j}=\left\{\begin{array}{ll}{d_{i}} & {i=j} \\ {-1} & {(i, j) \in E} \\ {0} & {\text { otherwise }}\end{array}\right.

原理分析

回到一開始說的拉普拉斯原理:形變前的點的拉普拉斯座標與形變後的點的拉普拉斯座標儘可能相等。現在將這句話用公式表達出來:

(L)nn * Xn3 = (L)nn * Cn3 = Bn3

用Ls矩陣代替L矩陣,等式兩邊同乘D,變爲下式:

(Ls)nn * Xn3 = (Ls)nn * Cn3 = D*Bn3

n表示網格中點的個數,Lnn表示拉普拉斯座標矩陣大小爲n*n,(Ls)nn=DL( L爲拉普拉斯矩陣,D爲上述描述的對角陣),X表示形變後的點的笛卡爾座標(需要求解的目標),C表示形變前的點的笛卡爾座標,B表示形變前的拉普拉斯座標。

寫到上面的矩陣的形式,是不是非常熟悉?這就是矩陣中最爲常見的Ax=b的形式啊,對應到這個問題就是LX=B

這裏簡單回顧一下矩陣裏求解Ax=b的方法,當A是可逆的: x= A~ b(這裏用A~表示A的逆),當A不是方陣的時候,通常我們用最小二乘求解最優解,等式兩邊同乘以AT :ATAx=ATb>x=(ATA)1ATbA^{T}A x=A^{T} b --> x = (A^{T}A)^{-1}A^{T} b(符號-1表示逆,ATA^{T}表示矩陣A的轉置)

在拉普拉斯變換中如果Ls是可逆的我們就可以直接計算 形變後的點的座標矩陣 X = (Ls)~ * D * Bn3

但是很遺憾,通常Ls是不可逆的,對於使得Ls可逆的解釋原文是那麼說的

爲了唯一地還原全局座標,需要解決一個完整的線性系統。 假設模型是相連的的,我們需要指定一個頂點的笛卡爾座標來解決平移自由度。 替換頂點i的座標等效於從L刪除第i行和第i列,這使矩陣可逆。

爲什麼需要增加錨點? 我的理解是這樣會增加Ls矩陣的秩,從而使得可以求解LsX = DB。

錨點是什麼呢? 現在可以滑動鼠標看看最開始的gif動態圖,圖中標識的紅色點和綠色點即爲錨點。錨點分成兩種:固定錨點(形變過程中,該點是雷打不動的,如圖中的綠色點),移動錨點(形變過程中,該點是控制移動的,如圖中的紅色點,這些紅色點繞着y軸順時針旋轉,可以說是移動錨點牽引着形變的進行)

有一個博客說的也很有趣:

因爲形變需要有控制點這種東西,所以在矩陣中增加錨點信息。也就是說,一個mesh,肯定有點移動了,才發生的laplace形變,不然形變個鬼啊。所以這些移動了的點和形變過程中保證不動的點,成爲錨點,因爲它們屬於我們不需要計算座標的點,因爲我們已經知道了。

添加錨點

直接給出添加錨點的公式:

(Ln×nAa×n)x=(Bn×3Aba×3)\left(\begin{array}{c}{L_{n \times n}} \\ { A_{a \times n}}\end{array}\right)\mathbf{x}=\left(\begin{array}{c}{B_{n \times 3}} \\ { Ab_{a \times 3}}\end{array}\right)

其中L和B爲已知的,A和Ab爲矩陣需要增加的錨點信息,Aa×3{ A_{a \times 3}}是一個標識矩陣,其中的a表示添加的錨點個數(固定錨點和移動錨點個數之和),n爲網格總點數。Aba×3{ Ab_{a \times 3}} 表示錨點的笛卡座標。

這樣看上去非常抽象,舉個栗子

設n = 5,a = 2(一個移動錨點,一個固定錨點),固定錨點的座標爲(Fx,Fy,Fz),下標爲1, 移動錨點的座標爲(Mx,My,Mz)下標爲4。則:

Aa×3=(0100000001){ A_{a \times 3}} = ( \begin{matrix} 0 & 1 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 & 1 \end{matrix}) Aba×3=(FxFyFzMxMyMz) { Ab_{a \times 3}} = ( \begin{matrix} Fx & Fy & Fz \\ Mx & My & Mz \end{matrix})

求解形變後的座標

L=(Ln×nAa×n),Ls=DL L^{*} = \left(\begin{array}{c}{L_{n \times n}} \\ { A_{a \times n}}\end{array}\right) , L_{s}^{*} = DL^{*}

則最終求解只需求解:LsX=DBL_{s}^{-}X = DB ,注意這時LsL_{s}^{-}不是方陣,需要兩邊同乘其轉置,將X左邊部分轉爲方陣。

(Ls)TLsX=(Ls)TDB(L_{s}^{*})^{T}L_{s}^{*} X = (L_{s}^{*})^{T}DB

最終求得X:

X=((Ls)TLs)1(Ls)TDB X = ((L_{s}^{*})^{T}L_{s}^{*} )^{-1}(L_{s}^{*})^{T}DB

接下來就只需要更新點的座標即可,注意只改變非錨點的點的座標

寫在最後
該方法經過測試對於點數少於100的模型具有較好的實時性,對於上千的點的模型程序處理就會變得很慢。

發佈了33 篇原創文章 · 獲贊 39 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章