Python 線上免費批量美顏,媽媽再也不用擔心我 P 圖兩小時啦
阿新 • • 發佈:2020-06-08
## 引言
首先我承認自己標題黨了,我就想提升點閱讀量我容易麼我,前幾天的篇純技術文閱讀量都扯著蛋了。
畢竟閱讀量太低實在是沒有寫下去的動力,我只能用點小手段偶爾提升下閱讀量。
這篇文章我轉換下套路,先放結果,感興趣的接著往下看,不感興趣的直接左上角,就當是我把你們騙進來的。
## 結果
![](https://cdn.geekdigging.com/opencv/bilateral-filter/bilateral_filter_result.png)
然後直接放原始碼:
```python
import cv2 as cv
source = cv.imread("zhaopian.jpg")
dst = cv.bilateralFilter(src=source, d=0, sigmaColor=30, sigmaSpace=15)
cv.imshow("source", source)
cv.imshow("dst", dst)
cv.waitKey()
cv.destroyAllWindows()
```
好了,本文結果部分介紹結束,想進一步瞭解一下原理的同學可以接著往下看了,沒啥興趣的可以左上角了。
## 雙邊濾波原理
上面的圖片美顏效果其實使用的是 OpenCV 中為我們提供的雙邊濾波器,是一種圖片降噪演算法。
對其他圖片降噪或者影象濾波器感興趣的可以參考前面的內容[「Python 影象處理 OpenCV (7):影象平滑(濾波)處理」](https://www.geekdigging.com/2020/06/06/8676263283/) 。
如果沒看過的同學十分建議先行閱讀,最少要把最後一部分的高斯濾波看一下,否則下面介紹的雙邊濾波會很難理解。
雙邊濾波(Bilateral filter)是一種非線性的濾波方法,本質是基於高斯濾波。
前面的文章介紹過,高斯濾波的方式會造成邊緣模糊化,這是沒辦法的事情,這是高斯濾波過濾方式而導致的。
而雙邊濾波就是在高斯濾波的基礎上,對高斯濾波的方式加以改進,結合影象的空間鄰近度和畫素值相似度的一種折處理,同時考慮 **空域資訊(domain)** 和 **值域資訊(range)** ,達到保邊降噪的目的。
說人話就是雙邊濾波在進行濾波的過程中,不光要考慮周圍畫素值與中點畫素值的大小之差,還需要考慮空間上的距離,進而確定該點對中間點的影響因子。
比如在一張影象中,相鄰的畫素點的顏色會非常相近,但是如果在邊緣區域,相鄰元素點的顏色變化會非常的大。
高斯過濾器的過濾過程中就是因為沒有考慮邊緣區域而導致過濾後圖像邊緣模糊,而雙邊濾波由於在過濾的過程中考慮到了周圍畫素值與中點畫素值的差值大小,從而會確定一個影響因子,從而實現圖片的保邊降噪。
具體的實現原理如下:
> 希望你們的高中數學沒有都還給你們的數學老師
整個雙邊濾波的演算法分為兩部分,一個是顏色值的相似度(值域核),公式如下:
$$
r(i, j, k, l) = exp( - \frac{||f(i, j) − f(k, l)||^2}{2{\sigma^2_r}} )
$$
另一個是計算空間距離的相似度(空域核),也就是說,離得越近,相似度越高,公式如下:
$$
d(i, j, k, l)=exp( - \frac{(i−k)^2 + (j−l)^2}{2{\sigma^2_d}})
$$
上面的邏輯還是很清晰,千萬不要被一堆符號弄暈了。
這裡 `(i, j)` 代表的是要處理的畫素點的座標點,而 `(k,l)` 則是要處理的範圍內,可能影響到其值的畫素點的座標。
最終的權重係數 w(i,j,k,l) 取決於空域核和值域核的乘積,公式如下:
$$
w(i,j,k,l)=d(i,j,k,l) ∗ r(i,j,k,l) = exp( - \frac{(i−k)^2 + (j−l)^2}{2{\sigma^2_d}} - \frac{||f(i, j) − f(k, l)||^2}{2{\sigma^2_r}})
$$
下面是一個經典的雙邊濾波的原理示意圖:
![](https://cdn.geekdigging.com/opencv/bilateral-filter/shuangbianyuanli.jpg)
從這個圖中可以看出,在圖(b)空域核上,每個畫素的權重是符合高斯分佈的,而在圖(c)的值域核上,由於畫素取值相差過大,不同顏色的權重係數相差也很大,雙邊過濾過濾完成後,邊緣兩側的畫素點保留了原有的色彩值。
接下來還是看下雙邊濾波的原函式:
```python
def bilateralFilter(src, d, sigmaColor, sigmaSpace, dst=None, borderType=None)
```
* src:原圖
* d:畫素鄰域的直徑。如果這個值設為非正數,那麼 OpenCV 會從第五個引數 sigmaSpace 來將它計算出來。
* sigmaColor:顏色空間濾波器的 $\sigma$ 值。這個引數的值越大,就表明該畫素鄰域內有更寬廣的顏色會被混合到一起,產生較大的半相等顏色區域。
* sigmaSpace:座標空間中濾波器的 $\sigma$ 值,座標空間的標註方差。他的數值越大,意味著越遠的畫素會相互影響,從而使更大的區域足夠相似的顏色獲取相同的顏色。當 d > 0 , d 指定了鄰域大小且與 sigmaSpace 無關。否則, d 正比於 sigmaSpace 。使用過程中我發現這個值越大,影象的過渡效果越好。
原始碼我就不放了,實際上只有那一行程式碼,不過希望看到本文的各位除了知道雙邊濾波能對影象進行美顏以外還是能稍微瞭解下原理。