影像平滑(blur、GaussianBlur)
有時我們收到的影像雜訊過多,這時需要進行平滑化去除雜訊,不過為了去除雜訊,可能造成影像對比度下降,好的品質可能需要大量的處理時間,所以通常根據實際需求,選擇一個適合的手法,常見的有四種平滑方式,分別是平均平滑、高斯平滑、中值濾波、雙邊濾波,OpenCV對於這四種平滑方式皆有支援,只要呼叫即可使用。
由濾波方式可分兩種,線性濾波和非線性濾波:
- 線性濾波:有一個有固定參數的核心,常見的有平均平滑和高斯平滑。
- 非線性濾波:沒有一個有固定參數的核心,常見的有中值濾波和雙邊濾波。
這邊我們介紹平均平滑和高斯平滑。
平均平滑正如名稱所說,將每個像素替換為相鄰矩形內像素的平均值,以3×3大小的核心來說,每個像素權重佔1/9,用這些像素的加總,替換當前的像素值,接著用卷積對整張影像作處理,由於採用平均濾波,所以影像變模糊的現象很明顯,且核心越大模糊的後遺症越明顯,以下為3×3平均模板:
OpenCV平均平滑
void blur(const Mat &src, Mat &dst, Size ksize)
- src:輸入可以為多通道圖,會單獨處理各通道,但是通常使用單通道灰階圖,例如CV_8U或CV_16U。
- dst:輸出圖會和輸入圖尺寸、型態相同。
- ksize:模板大小,可分別指定長和寬。
平均平滑對鄰域內的像素一視同仁,所以有明顯模糊的副作用,高斯平滑改變核心的參數,將靠近中心的像素權重加大,來讓處理後的模糊現象減小,高斯模板核心參數是由高斯函數計算得來,用核心內各像素結果相加替換當前的像素值,接著用卷積對整張影像作處理。
實際使用時,如果標準差σ如果過小,偏離中心的像素權重會非常小,結果像沒有任何處理,標準差σ如果過大,高斯模板將退化成平均模板。實際當模板3×3時,σ為0.8左右,對於更大的模板可以適當的增加σ的值,以下分別為高斯函數和常用的3×3高斯模板。
高斯函數
高斯模板:
OpenCV高斯平滑
void GaussianBlur(const Mat &src, Mat &dst, Size ksize, double sigmaX, double sigmaY)
- src:輸入可以為多通道圖,會單獨處理各通道,但是通常使用單通道灰階圖,例如CV_8U或CV_16U。
- dst:輸出圖會和輸入圖尺寸、型態相同。
- ksize:模板大小,長寬可以不同,但是都必須為正的奇數。
- sigmaX:x方向的標準差。
- sigmaY:y方向的標準差。
使用GaussianBlur()函式時,如果我們令濾波器的核心尺寸為0,這時我們輸入σ值,OpenCV會自動設置合適的係數和尺寸,也可以提供核心尺寸,而令σ為0,當然也可以同時選擇尺寸和σ,讓我們能更彈性的進行高斯濾波。
這邊使用有雜訊的lena圖,來看平均平滑和高斯平滑3×3或5×5的模板,平滑之後的效果,模板越大平滑的效果越明顯,而高斯平滑由於有考慮權重的關係,所以不像平均平滑那麼模糊,以下為程式碼:
#include <cstdio>
#include <opencv2/opencv.hpp>
using namespace cv;
int main(){
Mat src = imread("lena_noise.jpg",CV_LOAD_IMAGE_GRAYSCALE);
Mat aveBlur1;
Mat aveBlur2;
Mat GaussianBlur1;
Mat GaussianBlur2;
blur(src, aveBlur1, Size(3,3));
blur(src, aveBlur2, Size(5,5));
GaussianBlur(src, GaussianBlur1, Size(3,3) ,0 ,0);
GaussianBlur(src, GaussianBlur2, Size(5,5) ,0 ,0);
imshow("origin", src);
imshow("aveBlur_3", aveBlur1);
imshow("aveBlur_5", aveBlur2);
imshow("gaussianBlur_3", GaussianBlur1);
imshow("gaussianBlur_5", GaussianBlur2);
waitKey(0);
return 0;
}