opencv學習(二十)之高斯濾波GaussianBlur()

高斯濾波是一種線性平滑濾波,對於除去高斯噪聲有很好的效果。在其官方文檔中形容高斯濾波爲”Probably the most useful filter”,同時也指出高斯濾波並不是效率最高的濾波算法。高斯算法在官方文檔給出的解釋是高斯濾波是通過對輸入數組的每個點與輸入的高斯濾波模板執行卷積計算然後將這些結果一塊組成了濾波後的輸出數組,通俗的講就是高斯濾波是對整幅圖像進行加權平均的過程,每一個像素點的值都由其本身和鄰域內的其他像素值經過加權平均後得到。高斯濾波的具體操作是:用一個模板(或稱卷積、掩模)掃描圖像中的每一個像素,用模板確定的鄰域內像素的加權平均灰度值去替代模板中心像素點的值。
在圖像處理中高斯濾波一半有兩種實現方式:一種是用離散化窗口滑窗卷積,另一種是通過傅里葉變換。最常見的就是第一種滑窗實現,只有當離散化的窗口非常大,用滑窗計算量非常大的情況下會考慮基於傅里葉變換的方法。
我們在參考其他文章的時候可能會出現高斯模糊和高斯濾波兩種說法,其實這兩種說法是有一定區別的。我們知道濾波器分爲高通、低通、帶通等類型,高斯濾波和高斯模糊就是一句濾波器是低通濾波器還是高通濾波器來區分的。比如低通濾波器,像素能量低的通過,而對於像素能量高的部分將會採取加權平均的方法重新計算像素的值,將能量像素的值編程能量較低的值,我們知道對於圖像而言其高頻部分展現圖像細節,所以經過低通濾波器之後整幅圖像變成低頻造成圖像模糊,這就被稱爲高斯模糊;相反高通濾波是允許高頻通過而過濾掉低頻,這樣將低頻像素進行銳化操作,圖像變的更加清晰,被稱爲高斯濾波。說白了很簡單就是:高斯濾波是指用高斯函數作爲濾波函數的濾波操作而高斯模糊是用高斯低通濾波器。
高斯濾波在圖像處理中常用來對圖像進行預處理操作,雖然耗時但是數字圖像用於後期應用但是其噪聲是最大的問題,噪聲會造成很大的誤差而誤差在不同的處理操作中會累積傳遞,爲了能夠得到較好的圖像,對圖像進行預處理去除噪聲也是針對數字圖像處理的無奈之舉。
高斯濾波器是一類根據高斯函數的形狀來選擇權值的線性平滑濾波器,高斯濾波器對於服從正太分佈的噪聲非常有效,一維高斯函數如下:

這裏寫圖片描述

二維高斯函數如下:

這裏寫圖片描述

opencv提供了GaussianBlur()函數對圖形進行高斯濾波,其原型如下:

C++: void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT )

參數解釋:
. InputArray src: 輸入圖像,可以是Mat類型,圖像深度爲CV_8U、CV_16U、CV_16S、CV_32F、CV_64F。
. OutputArray dst: 輸出圖像,與輸入圖像有相同的類型和尺寸。
. Size ksize: 高斯內核大小,這個尺寸與前面兩個濾波kernel尺寸不同,ksize.width和ksize.height可以不相同但是這兩個值必須爲正奇數,如果這兩個值爲0,他們的值將由sigma計算。
. double sigmaX: 高斯核函數在X方向上的標準偏差
. double sigmaY: 高斯核函數在Y方向上的標準偏差,如果sigmaY是0,則函數會自動將sigmaY的值設置爲與sigmaX相同的值,如果sigmaX和sigmaY都是0,這兩個值將由ksize.width和ksize.height計算而來。具體可以參考getGaussianKernel()函數查看具體細節。建議將size、sigmaX和sigmaY都指定出來。
. int borderType=BORDER_DEFAULT: 推斷圖像外部像素的某種便捷模式,有默認值BORDER_DEFAULT,如果沒有特殊需要不用更改,具體可以參考borderInterpolate()函數。

爲了能更直觀的觀察到四個變量對濾波的影響,建立四個軌跡條分別調節,所以最後運行結果圖片有點醜,示例代碼如下:

#include <iostream>
#include <stdio.h>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>

using namespace std;
using namespace cv;

//定義全局變量
Mat g_srcImage;         //輸入圖像
Mat g_dstImage;         //輸出圖像

//定義軌跡條最大值參量
const int g_nKwidthTrackBarMaxValue = 9;
const int g_nKheightTrackBarMaxValue = 9;
const int g_nsigmaXTrackBarMaxValue = 5;
const int g_nsigmaYTrackBarMaxvalue = 5;

//定義每個軌跡條的初始值
int g_nKwidthTrackBarValue = 1;
int g_nKheightTrackBarValue = 1;
int g_nsigmaXTrackBarValue = 1;
int g_nsigmaYTrackBarValue = 1;

int g_kernelWidthValue;
int g_kernelHeightValue;

void on_GaussianBlurTrackbar(int, void*);       //定義回調函數

int main()
{
    g_srcImage = imread("lena.jpg");

    //判斷圖像是否加載成功
    if(!g_srcImage.data)
    {
        cout << "圖像加載失敗!" << endl;
        return -1;
    }
    else
        cout << "圖像加載成功!" << endl << endl;

    namedWindow("原圖像", WINDOW_NORMAL);         //定義窗口顯示屬性
    imshow("原圖像", g_srcImage);

    namedWindow("高斯濾波圖像", WINDOW_NORMAL);

    //定義每個軌跡條名字
    char widthTrackBarName[20];
    sprintf(widthTrackBarName, "核函數width %d", g_nKwidthTrackBarMaxValue);

    char heightTrackBarName[20];
    sprintf(heightTrackBarName,"核函數height %d", g_nKheightTrackBarMaxValue);

    char sigmaXTrackBarName[20];
    sprintf(sigmaXTrackBarName, "核函數sigmaX %d", g_nsigmaXTrackBarMaxValue);

    char sigmaYTrackBarName[20];
    sprintf(sigmaYTrackBarName, "核函數sigmaY %d", g_nsigmaYTrackBarMaxvalue);

    //創建軌跡條
    createTrackbar(widthTrackBarName, "高斯濾波圖像", &g_nKwidthTrackBarValue, 
                    g_nKwidthTrackBarMaxValue, on_GaussianBlurTrackbar);
    on_GaussianBlurTrackbar(g_nKwidthTrackBarValue, 0);

    createTrackbar(heightTrackBarName, "高斯濾波圖像", &g_nKheightTrackBarValue,
                    g_nKheightTrackBarMaxValue, on_GaussianBlurTrackbar);
    on_GaussianBlurTrackbar(g_nKheightTrackBarValue, 0);

    createTrackbar(sigmaXTrackBarName, "高斯濾波圖像", &g_nsigmaXTrackBarValue,
                    g_nsigmaXTrackBarMaxValue, on_GaussianBlurTrackbar);
    on_GaussianBlurTrackbar(g_nsigmaXTrackBarValue, 0);

    createTrackbar(sigmaYTrackBarName, "高斯濾波圖像", &g_nsigmaYTrackBarValue,
                    g_nsigmaYTrackBarMaxvalue, on_GaussianBlurTrackbar);
    on_GaussianBlurTrackbar(g_nsigmaYTrackBarValue, 0);

    waitKey(0);

    return 0;
}

void on_GaussianBlurTrackbar(int, void*)
{
    //根據輸入的width和height重新計算ksize.width和ksize.height
    g_kernelWidthValue = g_nKwidthTrackBarValue * 2 + 1;
    g_kernelHeightValue = g_nKheightTrackBarValue * 2 + 1;

    //高斯濾波
    GaussianBlur(g_srcImage, g_dstImage, Size(g_kernelWidthValue, g_kernelHeightValue),
                g_nsigmaXTrackBarValue, g_nsigmaYTrackBarValue);

    imshow("高斯濾波圖像", g_dstImage);
}

運行結果:
這裏寫圖片描述

發佈了98 篇原創文章 · 獲贊 630 · 訪問量 123萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章