天天看點

方框濾波/均值濾波/高斯濾波/中值濾波/雙邊濾波

線性鄰域濾波

“平滑處理“(smoothing)也稱“模糊處理”(bluring),是一項簡單且使用頻率很高的圖像處理方法。平滑處理的用途有很多,最常見的是用來減少圖像上的噪點或者失真。在涉及到降低圖像分辨率時,平滑處理是非常好用的方法。

線性濾波器:線性濾波器經常用于剔除輸入信号中不想要的頻率或者從許多頻率中選擇一個想要的頻率。

濾波可分低通濾波和高通濾波兩種。而高斯濾波是指用高斯函數作為濾波函數的濾波操作,至于是不是模糊,要看是高斯低通還是高斯高通,低通就是模糊,高通就是銳化。

在新版本的OpenCV中,提供了如下三種常用的線性濾波操作,他們分别被封裝在單獨的函數中,使用起來非常友善:

方框濾波——boxblur函數

均值濾波——blur函數,均值濾波,是最簡單的一種濾波操作,輸出圖像的每一個像素是核視窗内輸入圖像對應像素的像素的平均值( 所有像素權重系數相等),其實說白了它就是歸一化後的方框濾波。

高斯濾波——GaussianBlur函數,高斯濾波是一種線性平滑濾波,适用于消除高斯噪聲,廣泛應用于圖像處理的減噪過程。通俗的講,高斯濾波就是對整幅圖像進行權重平均的過程,每一個像素點的值,都由其本身和鄰域内的其他像素值經過權重平均後得到。高斯濾波的具體操作是:用一個模闆(或稱卷積、掩模)掃描圖像中的每一個像素,用模闆确定的鄰域内像素的權重平均灰階值去替代模闆中心像素點的值。

大家常常說高斯濾波最有用的濾波操作,雖然它用起來,效率往往不是最高的。

高斯模糊技術生成的圖像,其視覺效果就像是經過一個半透明螢幕在觀察圖像,這與鏡頭焦外成像效果散景以及普通照明陰影中的效果都明顯不同。高斯平滑也用于計算機視覺算法中的預先處理階段,以增強圖像在不同比例大小下的圖像效果(參見尺度空間表示以及尺度空間實作)。從數學的角度來看,圖像的高斯模糊過程就是圖像與正态分布做卷積。由于正态分布又叫作高斯分布,是以這項技術就叫作高斯模糊。

圖像與圓形方框模糊做卷積将會生成更加精确的焦外成像效果。由于高斯函數的傅立葉變換是另外一個高斯函數,是以高斯模糊對于圖像來說就是一個低通濾波操作。

非線性濾波

線性濾波器是兩個信号之和的響應和他們各自響應之和相等。換句話說,每個像素的輸出值是一些輸入像素的權重和,線性濾波器易于構造,并且易于從頻率響應角度來進行分析。

其實在很多情況下,使用鄰域像素的非線性濾波也許會得到更好的效果。比如在噪聲是散粒噪聲而不是高斯噪聲,即圖像偶爾會出現很大的值的時候。在這種情況下,用高斯濾波器對圖像進行模糊的話,噪聲像素是不會被去除的,它們隻是轉換為更為柔和但仍然可見的散粒。

中值濾波(Median filter)是一種典型的非線性濾波技術,基本思想是用像素點鄰域灰階值的中值來代替該像素點的灰階值,該方法在去除脈沖噪聲、椒鹽噪聲的同時又能保留圖像邊緣細節,.

中值濾波是基于排序統計理論的一種能有效抑制噪聲的非線性信号處理技術,其基本原理是把數字圖像或數字序列中一點的值用該點的一個鄰域中各點值的中值代替,讓周圍的像素值接近的真實值,進而消除孤立的噪聲點,對于斑點噪聲(speckle noise)和椒鹽噪聲(salt-and-pepper noise)來說尤其有用,因為它不依賴于鄰域内那些與典型值差别很大的值。中值濾波器在處理連續圖像窗函數時與線性濾波器的工作方式類似,但濾波過程卻不再是權重運算。

中值濾波在一定的條件下可以克服常見線性濾波器如最小均方濾波、方框濾波器、均值濾波等帶來的圖像細節模糊,而且對濾除脈沖幹擾及圖像掃描噪聲非常有效,也常用于保護邊緣資訊, 儲存邊緣的特性使它在不希望出現邊緣模糊的場合也很有用,是非常經典的平滑噪聲處理方法。

中值濾波器與均值濾波器比較的優勢:在均值濾波器中,由于噪聲成分被放入平均計算中,是以輸出受到了噪聲的影響,但是在中值濾波器中,由于噪聲成分很難選上,是以幾乎不會影響到輸出。是以同樣用3x3區域進行處理,中值濾波消除的噪聲能力更勝一籌。中值濾波無論是在消除噪聲還是儲存邊緣方面都是一個不錯的方法。

中值濾波器與均值濾波器比較的劣勢:中值濾波花費的時間是均值濾波的5倍以上。

顧名思義,中值濾波選擇每個像素的鄰域像素中的中值作為輸出,或者說中值濾波将每一像素點的灰階值設定為該點某鄰域視窗内的所有像素點灰階值的中值。

雙邊濾波(Bilateral filter)是一種非線性的濾波方法,是結合圖像的空間鄰近度和像素值相似度的一種折衷處理,同時考慮空域資訊和灰階相似性,達到保邊去噪的目的。具有簡單、非疊代、局部的特點。

雙邊濾波器的好處是可以做邊緣儲存(edge preserving),一般過去用的維納濾波或者高斯濾波去降噪,都會較明顯地模糊邊緣,對于高頻細節的保護效果并不明顯。雙邊濾波器顧名思義比高斯濾波多了一個高斯方差sigma-d,它是基于空間分布的高斯濾波函數,是以在邊緣附近,離的較遠的像素不會太多影響到邊緣上的像素值,這樣就保證了邊緣附近像素值的儲存。但是由于儲存了過多的高頻資訊,對于彩色圖像裡的高頻噪聲,雙邊濾波器不能夠幹淨的濾掉,隻能夠對于低頻資訊進行較好的濾波。

示例程式

//-----------------------------------【頭檔案包含部分】---------------------------------------
//            描述:包含程式所依賴的頭檔案
//----------------------------------------------------------------------------------------------
#include "pch.h"
#include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include <iostream>

//-----------------------------------【命名空間聲明部分】---------------------------------------
//            描述:包含程式所使用的命名空間
//----------------------------------------------------------------------------------------------- 
using namespace std;
using namespace cv;


//-----------------------------------【全局變量聲明部分】--------------------------------------
//            描述:全局變量聲明
//-----------------------------------------------------------------------------------------------
Mat g_srcImage, g_dstImage1, g_dstImage2, g_dstImage3, g_dstImage4, g_dstImage5;
int g_nBoxFilterValue = 6;  //方框濾波核心值
int g_nMeanBlurValue = 10;  //均值濾波核心值
int g_nGaussianBlurValue = 6;  //高斯濾波核心值
int g_nMedianBlurValue = 10;  //中值濾波參數值
int g_nBilateralFilterValue = 10;  //雙邊濾波參數值


//-----------------------------------【全局函數聲明部分】--------------------------------------
//            描述:全局函數聲明
//-----------------------------------------------------------------------------------------------
//軌迹條回調函數
static void on_BoxFilter(int, void *);            //方框濾波
static void on_MeanBlur(int, void *);           //均值塊濾波器
static void on_GaussianBlur(int, void *);                    //高斯濾波器
static void on_MedianBlur(int, void *);               //中值濾波器
static void on_BilateralFilter(int, void*);                    //雙邊濾波器



//-----------------------------------【main( )函數】--------------------------------------------
//            描述:控制台應用程式的入口函數,我們的程式從這裡開始
//-----------------------------------------------------------------------------------------------
int main()
{
  //載入原圖
  g_srcImage = imread("jinan.jpg", 1);
  if (!g_srcImage.data) { printf("讀取srcImage錯誤~!\n"); return false; }

  //克隆原圖到四個Mat類型中
  g_dstImage1 = g_srcImage.clone();
  g_dstImage2 = g_srcImage.clone();
  g_dstImage3 = g_srcImage.clone();
  g_dstImage4 = g_srcImage.clone();
  g_dstImage5 = g_srcImage.clone();

  //顯示原圖
  namedWindow("【<0>原圖視窗】", 1);
  imshow("【<0>原圖視窗】", g_srcImage);


  //=================【<1>方框濾波】=========================
  //建立視窗
  namedWindow("【<1>方框濾波】", 1);
  //建立軌迹條
  createTrackbar("核心值:", "【<1>方框濾波】", &g_nBoxFilterValue, 50, on_BoxFilter);
  on_MeanBlur(g_nBoxFilterValue, 0);
  imshow("【<1>方框濾波】", g_dstImage1);
  //=====================================================


  //=================【<2>均值濾波】==========================
  //建立視窗
  namedWindow("【<2>均值濾波】", 1);
  //建立軌迹條
  createTrackbar("核心值:", "【<2>均值濾波】", &g_nMeanBlurValue, 50, on_MeanBlur);
  on_MeanBlur(g_nMeanBlurValue, 0);
  //======================================================


  //=================【<3>高斯濾波】===========================
  //建立視窗
  namedWindow("【<3>高斯濾波】", 1);
  //建立軌迹條
  createTrackbar("核心值:", "【<3>高斯濾波】", &g_nGaussianBlurValue, 50, on_GaussianBlur);
  on_GaussianBlur(g_nGaussianBlurValue, 0);
  //=======================================================


  //=================【<4>中值濾波】===========================
  //建立視窗
  namedWindow("【<4>中值濾波】", 1);
  //建立軌迹條
  createTrackbar("參數值:", "【<4>中值濾波】", &g_nMedianBlurValue, 50, on_MedianBlur);
  on_MedianBlur(g_nMedianBlurValue, 0);
  //=======================================================


  //=================【<5>雙邊濾波】===========================
  //建立視窗
  namedWindow("【<5>雙邊濾波】", 1);
  //建立軌迹條
  createTrackbar("參數值:", "【<5>雙邊濾波】", &g_nBilateralFilterValue, 50, on_BilateralFilter);
  on_BilateralFilter(g_nBilateralFilterValue, 0);
  //=======================================================


  //輸出一些幫助資訊
  cout << endl << "\t嗯。好了,請調整滾動條觀察圖像效果~\n\n"
    << "\t按下“q”鍵時,程式退出~!\n";
  while (char(waitKey(1)) != 'q') {}

  return 0;
}

//-----------------------------【on_BoxFilter( )函數】------------------------------------
//            描述:方框濾波操作的回調函數
//-----------------------------------------------------------------------------------------------
static void on_BoxFilter(int, void *)
{
  //方框濾波操作
  boxFilter(g_srcImage, g_dstImage1, -1, Size(g_nBoxFilterValue + 1, g_nBoxFilterValue + 1));
  //顯示視窗
  imshow("【<1>方框濾波】", g_dstImage1);
}

//-----------------------------【on_MeanBlur( )函數】------------------------------------
//            描述:均值濾波操作的回調函數
//-----------------------------------------------------------------------------------------------
static void on_MeanBlur(int, void *)
{
  blur(g_srcImage, g_dstImage2, Size(g_nMeanBlurValue + 1, g_nMeanBlurValue + 1), Point(-1, -1));
  imshow("【<2>均值濾波】", g_dstImage2);

}

//-----------------------------【on_GaussianBlur( )函數】------------------------------------
//            描述:高斯濾波操作的回調函數
//-----------------------------------------------------------------------------------------------
static void on_GaussianBlur(int, void *)
{
  GaussianBlur(g_srcImage, g_dstImage3, Size(g_nGaussianBlurValue * 2 + 1, g_nGaussianBlurValue * 2 + 1), 0, 0);
  imshow("【<3>高斯濾波】", g_dstImage3);
}


//-----------------------------【on_MedianBlur( )函數】------------------------------------
//            描述:中值濾波操作的回調函數
//-----------------------------------------------------------------------------------------------
static void on_MedianBlur(int, void *)
{
  medianBlur(g_srcImage, g_dstImage4, g_nMedianBlurValue * 2 + 1);
  imshow("【<4>中值濾波】", g_dstImage4);
}


//-----------------------------【on_BilateralFilter( )函數】------------------------------------
//            描述:雙邊濾波操作的回調函數
//-----------------------------------------------------------------------------------------------
static void on_BilateralFilter(int, void *)
{
  bilateralFilter(g_srcImage, g_dstImage5, g_nBilateralFilterValue, g_nBilateralFilterValue * 2, g_nBilateralFilterValue / 2);
  imshow("【<5>雙邊濾波】", g_dstImage5);
}      

運作截圖:

參考