說起為什么會看到這個東西,那還真的繞一圈。首先在寫《Single Image Haze Removal Using Dark Channel Prior》一文中圖像去霧算法的原理、實現、效果及其他。 一文時里面提到了導向濾波,然后看何凱明的《Guided Image Filtering》一文時又多次提到雙邊濾波,結果我就又把以前研究的雙邊濾波的文章翻出來看看,就再次翻到了Fast O(1) bilateral filtering using trigonometric range kernels 一文,在論文的第10頁有如下這段文字:
The Java source code can be downloaded from the web at http://bigwww.epfl.ch/algorithms/bilateral-filter
我試着打開這個網頁,結果遇到了CSDN常見的404錯誤,然后想既然來了,就在這個網站多看看,哇,原來這個真是個好網站,有大量的圖像算法可以學習。一眼我就看到了最左側有一個Download Algorithms項目,於是進去瞧瞧,並在瀏覽器里搜索bilateral,結果的確搜到了於有關bilateral的一個代碼,如下所示:
BEEPS. This ImageJ plugin smoothes an image without altering its edges. The smoothing is applied by the way of a bi-exponential filter, itself realized by a pair of one-tap recursions. It is therefore very fast; moreover, its computational cost is truly independent of the amount of smoothing. Meanwhile, the preservation of edges is obtained by a range filter akin to the range filter found in a bilateral filter。
初步一看,我以為是作者對論文又有了新了改進,於是下載代碼,並試着將這個插件安裝到ImageJ中,運行后,效果和運行速度果然不錯,但是,仔細看論文,確發現和上述的快速雙邊濾波不是一回事。
好了,言歸正文。BEEPS,是Bi-Exponential Edge-Preserving Smoother 一文各字母的縮寫,這篇文章里涉及到了很多數學理論,比如Z變換等等,這些我都基本上已經丟給老師了,不過不要緊,那些驗證工作是寫論文的這些牛人們需要去做的工作。我們最關心的是算法的流程。 幸好在這篇論文中,算法的流程在算法的第二頁就已經完全的展示了, 並且過程特別簡單,為避免翻譯錯誤,先直接貼原文:
The first recursion is progressive. Letting x[k] be the current sample of an input sequence x at location k ∈ Z,were cursively compute the elements of an auxiliary sequence ϕ as:
where:
The second recursion is regressive and very similar to thefirst one, except for a reversal of the order in which the indices are traversed. We recursively compute a second auxiliary sequence φ as:
where:
We complete our algorithm by merging the resulting progressive sequence ϕ and regressive sequence φ to produce the samples of the output sequence y as:
We propose the trivial choice:
小注:博客園團隊建議我用他們內置的公式編輯器輸入公式,我看還是算了吧,那個東西還需要記憶一堆東西,不如直接貼圖來的快又准確。
對上述過程稍作解釋:x[k]可以看做是已經離散后的輸入數據,λ ∈[0,1)是一個用戶輸入的用來控制空域濾波的程度,r是一個雙變量的函數,用於控制值域濾波系數,對於雙邊濾波,該函數可取經典的高斯分布函數,也可以取其他的函數。
上述過程就是一個簡單的前向迭代和反向迭代,然后再按一定的規則去平均值的過程。因此計算非常簡單。
但是上述是個一維的過程,對於二維的圖像數據,論文中也給出了解決方式,首先:對圖像數據進行一次水平迭代計算,然后再對該數據進行垂直迭代計算,該過程稱之為BEEPSHorizontalVertical。然后再對原始圖像數據先進行垂直方向的迭代計算,在對該結果進行垂直方向的迭代計算,該過程稱之為BEEPSVerticalHorizontal。最后的圖像結果為(BEEPSHorizontalVertical+BEEPSVerticalHorizontal)/2;
比如上述公式1中最后體現在代碼中可能如下(progressive):
for (int k = startIndex + 1, K = startIndex + length;(k < K); k++) { mu = data[k] - rho * data[k - 1]; mu = spatialContraDecay * exp(c * mu * mu); data[k] = data[k - 1] * mu + data[k] * (1.0 - mu) / rho; }
式3的代碼可能為(regressive):
for (int k = startIndex + length - 2; (startIndex <= k); k--) { mu = data[k] - rho * data[k + 1]; mu = spatialContraDecay * exp(c * mu * mu); data[k] = data[k + 1] * mu + data[k] * (1.0 - mu) / rho; }
具體的代碼可以從上述提供的相關網頁里尋找,或者直接從這里下載。
話說JAVA的源碼要修改成C#的,那簡直就是很爽啊,有些復制過來基本都不要改動的。
這個算法特別適合於並行計算。
使用這個濾鏡的過程就會發現,他對邊緣的保護很好,而對一些變化平坦的區域總是會其更加平滑,總體感覺和表面模糊很像(表面模糊其實也是一種雙邊濾波器),以前曾考慮過用表面模糊來實現磨皮,但是由於目前所知道的表面模糊的任何優化算法都還是比較慢(但效果和PS是完全一致的),因此一直沒有真正實踐,這次看到這篇論文,經過我的實踐,如果參數取的適當,如在和膚色檢測或其他方式配合,完全可以實現較好的自動磨皮效果。
比如,針對一些圖像,我做了如下測試和比較:
原 圖 本文 λ=0.02,photometricStandardDeviation =10
美圖秀秀智能磨皮,參數為深 可牛影像超級磨皮
和美圖秀秀的比較,似乎看不出有什么區別,而可牛的明顯的有不少瑕疵。
再做一些比較:
原 圖 本文 λ=0.02,photometricStandardDeviation =10
美圖秀秀智能磨皮,參數為深 可牛影像超級磨皮
再來一副:
原圖 本文 美圖 可牛
無論是那一副圖,似乎可牛的效果總會碩一些,有顆粒感。
在看看一些皮膚嚴重粗糙的圖片的效果:
原 圖 本文 λ=0.02,photometricStandardDeviation =20
美圖秀秀智能磨皮,參數為深 可牛影像超級磨皮
本文通過適當的調整參數,是的皮膚部位的磨皮效果比美圖秀秀和可牛要好,但是頭發部位的信息有所丟失。
從上面這副圖中,可以看出,可牛的算法在最下部產生了一條黑線,這明顯是可牛在算法層面上有BUG所致。國內的軟件這些細節方面注意的不到位啊。
在http://www.cnblogs.com/celerychen/archive/2013/03/09/2951581.html的博客中,他的算法對上面這幅獲得更好的效果,但他對使用的算法沒有提到。
上述所有的圖像都是直接拿這個雙指數邊緣保留平滑濾波實現的,未使用任何其他的輔助的技術。
當然,美圖這些軟件應該還是更專業些,我這里舉得例子可能都是找了一些對我這個有利的來說明的,但無論如何,這種邊緣保留特性的濾波器作為磨皮的一種輔助手段是必然有其生存空間的。
習慣性動作,提供一個可供大家測試效果的程序: 基於雙指數邊緣保留平滑器的磨皮測試
無論文章寫得好不好,都希望能獲得各位看客的支持,有的時候一個小點擊或小回復也是給作者繼續寫作的動力源泉。
*********************************作者: laviewpbt 時間: 2013.8.31 聯系QQ: 33184777 轉載請保留本行信息************************