雙邊濾波器的原理及實現

2021-01-16 芯視tof

雙邊濾波(Bilateral filter)是一種非線性的濾波方法,是結合圖像的空間鄰近度和像素值相似度的一種折衷處理,同時考慮空域信息和灰度相似性,達到保邊去噪的目的。

雙邊濾波器之所以能夠做到在平滑去噪的同時還能夠很好的保存邊緣(Edge Preserve),是由於其濾波器的核由兩個函數生成:

一個函數由像素歐式距離決定濾波器模板的係數

另一個函數由像素的灰度差值決定濾波器的係數

其綜合了高斯濾波器(Gaussian Filter)和αα-截尾均值濾波器(Alpha-Trimmed mean Filter)的特點。高斯濾波器只考慮像素間的歐式距離,其使用的模板係數隨著和窗口中心的距離增大而減小;Alpha截尾均值濾波器則只考慮了像素灰度值之間的差值,去掉α%α%的最小值和最大值後再計算均值。

雙邊濾波器使用二維高斯函數生成距離模板,使用一維高斯函數生成值域模板。
距離模板係數的生成公式如下:



其中,(k,l)(k,l)為模板窗口的中心坐標;(i,j)(i,j)為模板窗口的其他係數的坐標;σdσd為高斯函數的標準差。使用該公式生成的濾波器模板和高斯濾波器使用的模板是沒有區別的。

值域模板係數的生成公式如下:



其中,函數f(x,y)f(x,y)表示要處理的圖像,f(x,y)f(x,y)表示圖像在點(x,y)(x,y)處的像素值;(k,l)(k,l)為模板窗口的中心坐標;(i,j)(i,j)為模板窗口的其他係數的坐標;σ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; } }

使用一維數組存放空間模板係數,同時使用另一個一維數組存放模板位置,和係數相對應。
整個代碼的實現如下:

void myBilateralFilter(const Mat &src, Mat &dst, int ksize, double space_sigma, double color_sigma){    int channels = src.channels();    CV_Assert(channels == 1 || channels == 3);    double space_coeff = -0.5 / (space_sigma * space_sigma);    double color_coeff = -0.5 / (color_sigma * color_sigma);    int radius = ksize / 2;    Mat temp;    copyMakeBorder(src, temp, radius, radius, radius, radius, BorderTypes::BORDER_REFLECT);    vector<double> _color_weight(channels * 256);     vector<double> _space_weight(ksize * ksize);     vector<int> _space_ofs(ksize * ksize);     double *color_weight = &_color_weight[0];    double *space_weight = &_space_weight[0];    int    *space_ofs = &_space_ofs[0];    for (int i = 0; i < channels * 256; i++)        color_weight[i] = exp(i * i * color_coeff);        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;         }    }        for (int i = 0; i < src.rows; i++)    {        const uchar *sptr = temp.data + (i + radius) * temp.step + radius * channels;        uchar *dptr = dst.data + i * dst.step;        if (channels == 1)        {            for (int j = 0; j < src.cols; j++)            {                double sum = 0, wsum = 0;                int val0 = sptr[j];                 for (int k = 0; k < maxk; k++)                {                    int val = sptr[j + space_ofs[k]];                    double w = space_weight[k] * color_weight[abs(val - val0)];                     sum += val * w;                    wsum += w;                }                dptr[j] = (uchar)cvRound(sum / wsum);            }        }        else if (channels == 3)        {            for (int j = 0; j < src.cols * 3; j+=3)            {                double sum_b = 0, sum_g = 0, sum_r = 0, wsum = 0;                int b0 = sptr[j];                int g0 = sptr[j + 1];                int r0 = sptr[j + 2];                for (int k = 0; k < maxk; k++)                {                    const uchar *sptr_k = sptr + j + space_ofs[k];                    int b = sptr_k[0];                    int g = sptr_k[1];                    int r = sptr_k[2];                    double w = space_weight[k] * color_weight[abs(b - b0) + abs(g - g0) + abs(r - r0)];                    sum_b += b * w;                    sum_g += g * w;                    sum_r += r * w;                    wsum += w;                }                wsum = 1.0f / wsum;                b0 = cvRound(sum_b * wsum);                g0 = cvRound(sum_g * wsum);                r0 = cvRound(sum_r * wsum);                dptr[j] = (uchar)b0;                dptr[j + 1] = (uchar)g0;                dptr[j + 2] = (uchar)r0;            }        }    }}

需要注意圖像像素值的獲取,首先獲取到每行的坐標指針

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時,平滑效果不是很明顯。


相關焦點

  • 高斯濾波器的原理和實現
    高斯濾波器是一種線性濾波器,能夠有效的抑制噪聲,平滑圖像。其作用原理和均值濾波器類似,都是取濾波器窗口內的像素的均值作為輸出。其窗口模板的係數和均值濾波器不同,均值濾波器的模板係數都是相同的為1;而高斯濾波器的模板係數,則隨著距離模板中心的增大而係數減小。所以,高斯濾波器相比於均值濾波器對圖像個模糊程度較小。
  • 均值濾波器(平滑空間濾波器)基本原理及Python實現
    基本原理使用元素的領域內像素的平均值代替該元素,可明顯的降低圖像灰度的尖銳變換。它的一種重要應用是模糊處理:得到感興趣的區域的粗略表示,將次要的/小的元素與背景融合,使得主要的/較大的元素變得易於檢測$$ R=\frac{1}{m} \sum_{i=1}^{m} z_{i} $$ 2.
  • FIR濾波器原理
    在數位訊號處理系統中較基本的元件,今天帶大家了解FOR濾波器的原理本文引用地址:http://www.eepw.com.cn/article/275887.htm如果超出1/2採樣頻率的頻率分量不佔主要地位,通常的解決辦法是在模數轉換電路之前放置一個低通濾波器(即抗混疊濾波器)將超過的高頻成分濾除。否則就必須用模擬濾波器實現要求的功能。  數字濾波器具有比模擬濾波器更高的精度,甚至能夠實現後者在理論上也無法達到的性能。
  • 高手講解濾波器原理(一),腔體濾波器原理解析
    越來越多的朋友想要了解濾波器原理,但對於不同的濾波器,其濾波器原理總是存在一定差異。而本文主要講解腔體濾波器原理,並於闡述濾波器原理後,向大家介紹腔體濾波器的應用。如果你對本文的內容存在一定興趣,那便耐心往下看吧。近年來,伴隨著科學技術的飛速發展,無線通信系統也在微波、毫米波技術的迅猛發展中得到了長足的進步。
  • 電源濾波器原理
    脈動係數(S)=輸出電壓交流分量的基波最大值/輸出電壓的直流分量  電源濾波器的原理就是一種阻抗適配網絡:電源濾波器輸入、輸出側與電源和負載側的阻抗適配越大,對電磁幹擾的衰減就越有效。  具體工作原理如下:交流電經過二極體整流之後,方向單一了,但是大小(電流強度)還是處在不斷地變化之中。這種脈動直流一般是不能直接用來給無線電裝供電的。
  • 高手講解濾波器原理(四),巴特沃斯濾波器原理全知曉
    濾波器在生活中應用很多,因此很多朋友想一窺濾波器原理。通常,對於濾波器原理的理解往往基於一定技術基礎,所以學習濾波器原理需要耐心、堅持。本文中,將為大家詳細講解巴特沃斯濾波器原理,並向大家介紹巴特沃斯濾波器的一些相關知識,一起來看看吧。一、什麼是巴特沃斯濾波器巴特沃斯濾波器是電子濾波器的一種。巴特沃斯濾波器的特點是通頻帶的頻率響應曲線最平滑。
  • 濾波器原理
    導讀:濾波器是一種選頻裝置,本文主要介紹的是濾波器的原理,下面我們就一起來學習一下吧~~~本文引用地址:http://www.eepw.com.cn/article/272535.htm1.濾波器原理--簡介  濾波器是一種選頻裝置,可以使信號中特定的頻率成分通過
  • 一文了解高斯濾波器,附原理及實現過程
    高斯濾波器是一種線性濾波器,能夠有效的抑制噪聲,平滑圖像。其作用原理和均值濾波器類似,都是取濾波器窗口內的像素的均值作為輸出。其窗口模板的係數和均值濾波器不同,均值濾波器的模板係數都是相同的為1;而高斯濾波器的模板係數,則隨著距離模板中心的增大而係數減小。所以,高斯濾波器相比於均值濾波器對圖像個模糊程度較小。
  • 正弦波濾波器原理_正弦波濾波器的作用
    打開APP 正弦波濾波器原理_正弦波濾波器的作用 發表於 2019-08-30 14:55:52   正弦波濾波器原理   正弦波濾波器
  • 梳狀濾波器以及積分梳狀濾波器的FPGA實現
    梳狀濾波器以及積分梳狀濾波器的FPGA實現 lee 發表於 2020-11-21 09:57:00 作者:lee
  • EMI濾波器設計原理
    除此之外,可以利用EMI濾波器衰減電網與開關電源對彼此的噪聲幹擾。EMI騷擾通常難以精確描述,濾波器的設計通常是通過反覆迭代,計算製作以求逐步逼近設計要求。本文從EMI濾波原理入手,分別通過對其共模和差模噪聲模型的分析,給出實際工作中設計濾波器的方法,並分步驟給出設計實例。
  • 高手講解濾波器原理(二),輕鬆搞定LC濾波器原理
    很多朋友看來,濾波器原理屬於難以掌控的內容。但事實上,只要耐心學習,濾波器原理可被輕鬆掌握。本文中,將為大家講解LC濾波器原理,並附帶LC濾波電路實例。希望通過本文,大家能對LC濾波器原理有更深的理解。
  • 巴特沃斯濾波器的原理_巴特沃斯濾波器優點介紹
    巴特沃斯濾波器原理   巴特沃斯型濾波器在現代設計方法設計的濾波器中,是最為有名的濾波器,由於它設計簡單,性能方面又沒有明顯的缺點,又因它對構成濾波器的元件Q值較低,因而易於製作且達到設計性能,因而得到了廣泛應用。其中,巴特沃斯濾波器的特點是通頻帶的頻率響應曲線最平滑。
  • 共模濾波器的原理_共模濾波器的作用
    打開APP 共模濾波器的原理_共模濾波器的作用 發表於 2019-08-30 14:31:04   共模濾波器的原理   共模電感又叫共模濾波器,是一個以鐵氧體為磁芯的共模幹擾抑制器件,它由兩個尺寸相同,匝數相同的線圈對稱地繞制在同一個鐵氧體環形磁芯上,形成一個四端器件,要對於共模 信號呈現出大電感具有抑制作用,而對於差模信號呈現出很小的漏電感幾乎不起作用。
  • IIR數字濾波器的Matlab和FPGA實現
    摘要:提出一種通過兩個二階節級聯構成四階IIR數字橢圓濾波器的設計方法,並利用Matlab仿真軟體設計了通帶內波紋不大於0.1 dB,阻帶衰減不小於42 dB的IIR數字濾波器。論述了一種採用可編程邏輯器件,通過VHDL硬體描述語言實現該濾波器的方法。
  • 一階低通濾波器_一階低通濾波器公式_一階低通濾波器原理
    打開APP 一階低通濾波器_一階低通濾波器公式_一階低通濾波器原理 發表於 2017-08-16 17:28:42   濾波電路又稱為濾波器
  • 三種濾波器的工作原理
    打開APP 三種濾波器的工作原理 發表於 2019-11-26 15:09:29 濾波器主要有低通濾波器、高通濾波器和帶通濾波器三種,按照電路工作原理又可分為無源和有源濾波器兩大類。本文主要對低通、高通還有帶通三種濾波器做以下簡單的介紹,希望電子愛好者的朋友們看完有一點小小的收穫。     1 低通濾波器 電感阻止高頻信號通過而允許低頻信號通過,電容的特性卻相反。
  • 基於FPGA高階FIR濾波器的實現
    摘要:從FIR數字濾波器的基本結構模型出發,分析了FIR濾波器的設計思路及具體實現方法,詳細介紹了FIR濾波器的分布式算法(DA)結構。通過分析計算,得到普通DA結構實現高階濾波器會消耗大量的查找表資源,這樣的資源消耗甚至令硬體資源不可接受。
  • 採用FPGA實現多種類型的數位訊號處理濾波器
    高通濾波器與低通濾波器相反,只允許頻率高於截止頻率的信號通過。帶通濾波器只允許頻率在預設帶寬內的信號通過,不允許其它頻率的信號通過。帶阻濾波器與帶通濾波器相反,不允許頻率在預設帶寬內的信號通過,但允許其它頻率的信號通過。大多數數字濾波器都採用下列兩種方法之一來實現: 有限脈衝響應(FIR) 和無限脈衝響應 (IIR)。首先我們深入探討如何設計和實現 FIR 濾波器。
  • 基於FPGA的實時中值濾波器硬體實現
    在許多實際應用場合,如高清視頻監控、X光圖像的降噪等,需要快速且實時地進行中值濾波,軟體實現達不到實時處理的要求,因此選用硬體實現。 在硬體實現上,文獻[1]、[2]等採用行延遲的方法形成鄰域數據,以實現3×3的中值濾波。文獻[7]為了提高紅外成像跟蹤器設計了大窗口的中值濾波器。