圖像處理中,常用的濾波算法有均值濾波、中值濾波以及高斯濾波等。
濾波器種類 | 基本原理 | 特點 |
均值濾波 | 使用模板內所有像素的平均值代替模板中心像素灰度值 | 易收到噪聲的干擾,不能完全消除噪聲,只能相對減弱噪聲 |
中值濾波 | 計算模板內所有像素中的中值,並用所計算出來的中值體改模板中心像素的灰度值 | 對噪聲不是那麼敏感,能夠較好的消除椒鹽噪聲,但是容易導致圖像的不連續性 |
高斯濾波 | 對圖像鄰域內像素進行平滑時,鄰域內不同位置的像素被賦予不同的權值 | 對圖像進行平滑的同時,同時能夠更多的保留圖像的總體灰度分佈特徵 |
下面本文主要對高斯濾波展開詳細的介紹。
基本原理
數值圖像處理中,高斯濾波主要可以使用兩種方法實現。一種是離散化窗口滑窗卷積,另一種方法是通過傅里葉變化。最常見的就是滑窗實現,只有當離散化的窗口非常大,用滑窗計算量非常搭的情況下,可能會考慮基於傅里葉變化的實現方法。所以本文將主要介紹滑窗實現的卷積。
離散化窗口划船卷積時主要利用的是高斯核,高斯核的大小爲奇數,因爲高斯卷積會在其覆蓋區域的中心輸出結果。常用的高斯模板有如下幾種形式:
高斯模板是通過高斯函數計算出來的,公式如下:
以3 × 3的高斯濾波器模板爲例,以模板的中心位置爲座標原點進行取樣。模板在各個位置的座標,如下所示(x軸水平向右,y軸豎直向上)。
這樣,將各個位置的座標帶入到高斯函數G中,得到的每個值按照位置排列,就得到了模板。
這樣輸出的模板有兩種形式:
① 小數類型:直接計算得到的值,沒有經過任何處理。
② 整數類型:將得到的值進行歸一化處理,即將坐上叫的值歸一化爲1,其他每個係數都除以左上角的係數,然後取整。在使用整數模板時,則需要在模板的前面加一個係數,該係數爲模板係數之和的倒數。
例如:生成高斯核爲3 × 3,σ = 0.8的模板
小數模板:
0.057118 | 0.12476 | 0.057118 |
0.12476 | 0.2725 | 0.12476 |
0.057118 | 0.12476 | 0.057118 |
整數模板:
1 | 2.1842 | 1 |
2.1842 | 4.7707 | 2.1842 |
1 | 2.1842 | 1 |
再經過四捨五入和添加係數得到最終結果:
從以上描述中我們可以看出,高斯濾波模板中最重要的參數就是高斯分佈的標準差σ。它代表着數據的離散程度,如果σ較小,那麼生成的模板中心繫數越大,而周圍的係數越小,這樣對圖像的平滑效果就不是很明顯;相反,σ較大時,則生成的模板的各個係數相差就不是很大,比較類似於均值模板,對圖像的平滑效果就比較明顯。通過下面的一維高斯分佈圖也可驗證上述觀點。
GaussianBlur函數
函數原型:
void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT);
參數詳解如下:
src,輸入圖像,即源圖像,填Mat類的對象即可。它可以是單獨的任意通道數的圖片,但需要注意,圖片深度應該爲CV_8U,CV_16U, CV_16S, CV_32F 以及 CV_64F之一。
dst,即目標圖像,需要和源圖片有一樣的尺寸和類型。比如可以用Mat::Clone,以源圖片爲模板,來初始化得到如假包換的目標圖。
ksize,高斯內核的大小。其中ksize.width和ksize.height可以不同,但他們都必須爲正數和奇數(並不能理解)。或者,它們可以是零的,它們都是由sigma計算而來。
sigmaX,表示高斯核函數在X方向的的標準偏差。
sigmaY,表示高斯核函數在Y方向的的標準偏差。若sigmaY爲零,就將它設爲sigmaX,如果sigmaX和sigmaY都是0,那麼就由ksize.width和ksize.height計算出來。
應用示例
#include "stdafx.h"
#include <opencv2/opencv.hpp>
int main()
{
// 創建兩個窗口,分別顯示輸入和輸出的圖像
cv::namedWindow("Example2-5_in", cv::WINDOW_AUTOSIZE);
cv::namedWindow("Example2-5_out", cv::WINDOW_AUTOSIZE);
// 讀取圖像,並用輸入的窗口顯示輸入圖像
cv::Mat img = cv::imread("C:\\Users\\Bello\\Desktop\\test.jpg", -1);
cv::imshow("Example2-5_in", img);
// 聲明輸出矩陣
cv::Mat out;
// 進行平滑操作,可以使用GaussianBlur()、blur()、medianBlur()或bilateralFilter()
// 此處共進行了兩次模糊操作
cv::GaussianBlur(img, out, cv::Size(5, 5), 3, 3);
cv::GaussianBlur(out, out, cv::Size(5, 5), 3, 3);
// 在輸出窗口顯示輸出圖像
cv::imshow("Example2-5_out", out);
// 等待鍵盤事件
cv::waitKey(0);
// 關閉窗口並釋放相關聯的內存空間
cv::destroyAllWindows();
return 0;
}
運行結果:
平滑處理前 | 平滑處理後 |