高斯滤波是一种线性平滑滤波,对于除去高斯噪声有很好的效果。在其官方文档中形容高斯滤波为”Probably the most useful filter”,同时也指出高斯滤波并不是效率最高的滤波算法。高斯算法在官方文档给出的解释是高斯滤波是通过对输入数组的每个点与输入的高斯滤波模板执行卷积计算然后将这些结果一块组成了滤波后的输出数组,通俗的讲就是高斯滤波是对整幅图像进行加权平均的过程,每一个像素点的值都由其本身和邻域内的其他像素值经过加权平均后得到。

高斯滤波的具体操作是:用一个模板(或称卷积、掩模)扫描图像中的每一个像素,用模板确定的邻域内像素的加权平均灰度值去替代模板中心像素点的值。

在图像处理中高斯滤波一半有两种实现方式:一种是用离散化窗口滑窗卷积,另一种是通过傅里叶变换。

最常见的就是第一种滑窗实现,只有当离散化的窗口非常大,用滑窗计算量非常大的情况下会考虑基于傅里叶变换的方法。

我们在参考其他文章的时候可能会出现高斯模糊和高斯滤波两种说法,其实这两种说法是有一定区别的。我们知道滤波器分为高通、低通、带通等类型,高斯滤波和高斯模糊就是一句滤波器是低通滤波器还是高通滤波器来区分的。

比如低通滤波器,像素能量低的通过,而对于像素能量高的部分将会采取加权平均的方法重新计算像素的值,将能量像素的值编程能量较低的值,我们知道对于图像而言其高频部分展现图像细节,所以经过低通滤波器之后整幅图像变成低频造成图像模糊,这就被称为高斯模糊;相反高通滤波是允许高频通过而过滤掉低频,这样将低频像素进行锐化操作,图像变的更加清晰,被称为高斯滤波。说白了很简单就是:高斯滤波是指用高斯函数作为滤波函数的滤波操作而高斯模糊是用高斯低通滤波器。

高斯滤波在图像处理中常用来对图像进行预处理操作,虽然耗时但是数字图像用于后期应用但是其噪声是最大的问题,噪声会造成很大的误差而误差在不同的处理操作中会累积传递,为了能够得到较好的图像,对图像进行预处理去除噪声也是针对数字图像处理的无奈之举。

高斯滤波器是一类根据高斯函数的形状来选择权值的线性平滑滤波器,高斯滤波器对于服从正太分布的噪声非常有效,一维高斯函数如下:

$$G(r) = \frac{1}{\sqrt(2 \pi \sigma ^2)^N}e^{\frac{-r^2}{2\sigma^2}}$$

二维高斯函数如下:

$$G(u,v)=\frac{1}{2\pi\sigma^2}e^{-\frac{(u^2+v^2)}{2\sigma^2}}$$

Opencv 提供了 GaussianBlur() 函数对图形进行高斯滤波,其原型如下:

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);
}
Last modification:October 27th, 2022 at 02:18 pm
如果觉得我的文章对你有用,请随意赞赏