图像处理之让手心长出眼睛,其实嘴也可以
無圖像,不處理,先上效果圖。手上長嘴當然也可以,不過感覺有點惡心 ~ 就不上那種圖了。
這里所采用的算法就是大名鼎鼎的泊松融合算法,它的應用非常廣泛,除了上面這種手上長眼睛的效果,還可以實現“紋理拼接”、“精細摳圖”、“移花接木”等等效果。我之前已經從純數學的角度討論過它的原理了。
但是,當初給出的代碼僅僅是為了算法演示的目的,所以并未進行優化。可以說是最簡單、最原始的實現方法。然后,我寫完就扔一邊很久沒碰了。今天有朋友向我了解,我表示印象中用高斯法解大稀疏矩陣也可以實現對泊松方程的求解,但是當初沒有深究。今天好奇心再次被喚起,想來再續前緣。沒想到一頓翻箱倒柜,還真找到些不錯的資料。其中一篇感性角度理解該算法的文章感覺很不錯。不僅介紹了算法的原理(而且完全不從數學角度,就從感性認識談也一樣深刻),還談及了優化的實現方法。今天我特別二次加工后與各位分享。
原文鏈接:http://eric-yuan.me/poisson-blending/
下面的圖基本都是盜的原文中的,原文是英文,我根據自己的理解翻譯+改編,希望能融合一些我個人的理解。
首先,讓我們從最最簡單的“一維”情況開始考慮。如下圖所示,我們的目標是將左圖中紅色的部分copy到右圖中,這個時候左圖中紅色部分就相當于是最開始圖中的“眼睛”,右圖就是一個手掌。
如果要做到天衣無縫,我們應該保證哪些條件?這個我在過去的文章中討論過,總而言之,言而總之,就兩條:1)將眼睛融入手掌之后,眼睛和手掌相連的邊緣過渡要平滑(用圖像處理的術語說,就是梯度小)。2)眼睛內部的自身紋理要最大程度保留,不能融合之后眼睛沒了,就剩手掌那肯定不行。
就我們當前所面對的這個例子,其實就是要求:
其中f?是右圖中的“信號”,而+1、-1、+2、-1、-1是原圖(左圖)本來的梯度。那我們有沒有什么是已知的呢?有的!f1=6,f6=1,即融合邊界的信息我們已知。于是化簡有
然后根據費馬定理,當有極值時,偏導數等于零,即
然后如果用矩陣形式來表示方程組便有
現在要解一個線性方程組,而且這個方程組還是稀疏的,顯然用高斯-塞德爾迭代法是非常不錯的選擇,這也是泊松方法的原作者最初使用的求解方法。而且高斯法會比雅各比法快很多。更多高斯-塞德爾迭代法的內容請見
Jacobi迭代法與Gauss-Seidel迭代法?_一九八網絡科技V客學院-IT技術博客
/baimafujinji/article/details/50582462
然后我們咔嚓一頓狂解,最后得到方程組的結為:f2=6,f3=4,f4=5,f5=3,這好像并不太直觀,于是用圖形來表示
哈啊!看出門道了嗎?首先,接合的地方過渡很自然(梯度小),內部紋理保持的也不錯(基本和原圖一致)。Yes, we get it!
然后呢?我們既然處理的對象是圖像,所以還得回到二維的情況來看看。其實,你應該理解,這個推廣的過程其實沒啥新鮮的東西。但它與你編程實現直接相關。下圖演示了我們將要開展的工作。數字方格是我要copy過來的像素點,紅色表示接合邊緣。
跟一維的情況一樣,我們現在要解線性方程組?Ax = b,其中A是一個N×N的方陣,N是我們要copy的像素數目,本題中N=10。我們用下面的偽代碼演示了創建一個所需的10×10方陣。
for i=1:row numberfor j=1:col numberif(i==j)matrix(i, j)=-4elif(adjacent(pixel(j), pixel(i)))matrix(i, j)=1elsematrix(i, j)=0endendend 最終我們生成的矩陣應該是長成下面這個樣子(我之前以為原博文作者這個地方寫錯了。直到我編碼實現的時候才發現其中另有玄妙。真是實踐出真知啊!在下一篇文章中,我會結合Matlab代碼來演示這個地方。):
在方程組?Ax = b中,b?是一個N元向量,它是由下面這個式子創建的
b[i] = div ( G( Source(x,y) ) ) + Neighbor(target i) ; ? ? ? ? ?i=1..N
其中G(·)是求梯度,散度由下面公式求得(這屬于經典離散數值解,不做過多解釋,如果你感覺困惑可以看我前面的文章,已經說得很詳細了)
div G = -4 f(x,y) + f(x-1,y) + f(x,y-1) + f(x+1,y) + f(x,y+1)
其中i的鄰域(Neighbor)指的是i的四鄰域點中屬于邊界的部分,例如從圖中可以看出
- Neighbor(pixel 1) 有三個點: left, up, right;
- Neighbor(pixel 8) 有兩個點: left, up;
- Neighbor(pixel 5) 有一個點: up.
這里我還想根據Patrick的經典論文之原文來對上面的結論做進一步的解釋。其中,p是S中的一個元素,Np是點p位于S內部的4鄰域點。<p,q>表示一個點對,其中q∈Np。Ω的邊界
請注意,S和Ω的所代表的意思我在前面的文章中已經給出,請讀者參考之前的文章。令fp 代表p點處的f值。那么原來的優化問題就變成了如下的離散形式:
vpq?是v((q+p)/2)在邊[p,q]方向上的投影,即
上述最優化問題的解滿足
? ??(7)
這就是我們上面給出的那個公式。對于位于S中的Ω的邊界像素點p,|Np|<4,即邊界上點的鄰域點少于4個,顯然邊界上的點p至少有一個鄰域點位于Ω內部。然而,對于那些位于Ω內部的像素點p而言,即Np∈Ω,等式右端的邊界項就不復存在了,即有
方程(7)是一個很大的稀疏矩陣,所以可以用經典的迭代法進行求解。作者指出他原文中的結果是采用高斯-塞德爾法得到的。
如果我們知道矩陣?A?和向量?b, 我們就可以根據x?=?A-1?*?b來計算向量x,這也就是目標圖像中要被填充的部分像素。
總結
以上是生活随笔為你收集整理的图像处理之让手心长出眼睛,其实嘴也可以的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于直方图的图像增强算法(HE、CLAH
- 下一篇: 图像的泊松(Poisson)编辑、泊松融