能使曲线变平滑的一维滤波器_双边滤波器的原理及实现
雙邊濾波(Bilateral filter)是一種非線性的濾波方法,是結合圖像的空間鄰近度和像素值相似度的一種折衷處理,同時考慮空域信息和灰度相似性,達到保邊去噪的目的。
雙邊濾波器之所以能夠做到在平滑去噪的同時還能夠很好的保存邊緣(Edge Preserve),是由于其濾波器的核由兩個函數生成:
一個函數由像素歐式距離決定濾波器模板的系數
另一個函數由像素的灰度差值決定濾波器的系數
其綜合了高斯濾波器(Gaussian Filter)和α" role="presentation" style="font-size: 14px; display: inline; line-height: normal; word-spacing: normal; overflow-wrap: normal; float: none; direction: ltr; max-width: none; max-height: none; min-width: 0px; min-height: 0px; border-width: 0px; border-style: initial; border-color: initial;">αα-截尾均值濾波器(Alpha-Trimmed mean Filter)的特點。高斯濾波器只考慮像素間的歐式距離,其使用的模板系數隨著和窗口中心的距離增大而減小;Alpha截尾均值濾波器則只考慮了像素灰度值之間的差值,去掉α%" role="presentation" style="font-size: 14px; display: inline; line-height: normal; word-spacing: normal; overflow-wrap: normal; float: none; direction: ltr; max-width: none; max-height: none; min-width: 0px; min-height: 0px; border-width: 0px; border-style: initial; border-color: initial;">α%α%的最小值和最大值后再計算均值。
雙邊濾波器使用二維高斯函數生成距離模板,使用一維高斯函數生成值域模板。
距離模板系數的生成公式如下:
其中,(k,l)" role="presentation" style="font-size: 14px; display: inline; line-height: normal; word-spacing: normal; overflow-wrap: normal; float: none; direction: ltr; max-width: none; max-height: none; min-width: 0px; min-height: 0px; border-width: 0px; border-style: initial; border-color: initial;">(k,l)(k,l)為模板窗口的中心坐標;(i,j)" role="presentation" style="font-size: 14px; display: inline; line-height: normal; word-spacing: normal; overflow-wrap: normal; float: none; direction: ltr; max-width: none; max-height: none; min-width: 0px; min-height: 0px; border-width: 0px; border-style: initial; border-color: initial;">(i,j)(i,j)為模板窗口的其他系數的坐標;σd" role="presentation" style="font-size: 14px; display: inline; line-height: normal; word-spacing: normal; overflow-wrap: normal; float: none; direction: ltr; max-width: none; max-height: none; min-width: 0px; min-height: 0px; border-width: 0px; border-style: initial; border-color: initial;">σdσd為高斯函數的標準差。使用該公式生成的濾波器模板和高斯濾波器使用的模板是沒有區別的。
值域模板系數的生成公式如下:
其中,函數f(x,y)" role="presentation" style="font-size: 14px; display: inline; line-height: normal; word-spacing: normal; overflow-wrap: normal; float: none; direction: ltr; max-width: none; max-height: none; min-width: 0px; min-height: 0px; border-width: 0px; border-style: initial; border-color: initial;">f(x,y)f(x,y)表示要處理的圖像,f(x,y)" role="presentation" style="font-size: 14px; display: inline; line-height: normal; word-spacing: normal; overflow-wrap: normal; float: none; direction: ltr; max-width: none; max-height: none; min-width: 0px; min-height: 0px; border-width: 0px; border-style: initial; border-color: initial;">f(x,y)f(x,y)表示圖像在點(x,y)" role="presentation" style="font-size: 14px; display: inline; line-height: normal; word-spacing: normal; overflow-wrap: normal; float: none; direction: ltr; max-width: none; max-height: none; min-width: 0px; min-height: 0px; border-width: 0px; border-style: initial; border-color: initial;">(x,y)(x,y)處的像素值;(k,l)" role="presentation" style="font-size: 14px; display: inline; line-height: normal; word-spacing: normal; overflow-wrap: normal; float: none; direction: ltr; max-width: none; max-height: none; min-width: 0px; min-height: 0px; border-width: 0px; border-style: initial; border-color: initial;">(k,l)(k,l)為模板窗口的中心坐標;(i,j)" role="presentation" style="font-size: 14px; display: inline; line-height: normal; word-spacing: normal; overflow-wrap: normal; float: none; direction: ltr; max-width: none; max-height: none; min-width: 0px; min-height: 0px; border-width: 0px; border-style: initial; border-color: initial;">(i,j)(i,j)為模板窗口的其他系數的坐標;σr" role="presentation" style="font-size: 14px; display: inline; line-height: normal; word-spacing: normal; overflow-wrap: normal; float: none; direction: ltr; max-width: none; max-height: none; min-width: 0px; min-height: 0px; border-width: 0px; border-style: initial; border-color: initial;">σrσr為高斯函數的標準差。
將上述兩個模板相乘就得到了雙邊濾波器的模板
實現(參考OpenCV源代碼)
這里的實現主要參考OpenCV中的bilateralFilter實現,其實現主要有兩個優化:
使用查表的方式計算灰度值模板系數
將二維的模板轉換為一維,降低算法復雜度。
在濾波之前,首先將灰度值模板系數計算出來。
double color_coeff = -0.5 / (color_sigma * color_sigma);vector<double> _color_weight(channels * 256); // 存放差值的平方double *color_weight = &_color_weight[0];for (int i = 0; i < channels * 256; i++) color_weight[i] = exp(i * i * color_coeff);灰度值的模板系數計算公式參見上面的公式,是兩個灰度值的差值的平方。這里表的長度是channels * 256沒有想通,應該255的長度就足夠了。在使用的時候,首先取出模板中心的灰度值val0,然后依次取出模板其他位置的灰度值val,使用abs(val - val0)的差值從color_weight查表得到灰度值模板的系數。
距離的模板是二維的,這里使用的方法就i比較巧妙,將其化為了一維。
vector<double> _space_weight(ksize * ksize); // 空間模板系數vector<int> _space_ofs(ksize * ksize); // 模板窗口的坐標// 生成空間模板 int maxk = 0; for (int i = -radius; i <= radius; i++) { for (int j = -radius; j <= radius; j++) { double r = sqrt(i*i + j * j); if (r > radius) continue; space_weight[maxk] = exp(r * r * space_coeff); // 存放模板系數 space_ofs[maxk++] = i * temp.step + j * channels; // 存放模板的位置,和模板系數相對應 } }使用一維數組存放空間模板系數,同時使用另一個一維數組存放模板位置,和系數相對應。
整個代碼的實現如下:
需要注意圖像像素值的獲取,首先獲取到每行的坐標指針
const uchar *sptr = temp.data + (i + radius) * temp.step + radius * channels;uchar *dptr = dst.data + i * dst.step;在濾波循環中,從space_ofs中取出每個模板位置偏移地址
int?val?=?sptr[j?+?space_ofs[k]];這種實現方法,大大的降低濾波的時間復雜度。
結果對比:
實現的結果和OpenCV的實現相差無幾。sigma = 80,模板大小為20
總結
雙邊濾波器,在平滑圖像的同時,還能夠很好的保護圖像的邊緣信息,例如上圖中,圖像的平滑效果非常明顯了,但是頭發的發絲還是很明顯的。
雙邊濾波器的最重要參數仍然是標準差sigma,其值小于10時,平滑效果不是很明顯。
總結
以上是生活随笔為你收集整理的能使曲线变平滑的一维滤波器_双边滤波器的原理及实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 荣耀一跃,要越过华为
- 下一篇: Redmi Note 12 4G配色及内