【Qt&OpenCV 图像平滑/滤波处理 -- Blur/Gaussian/Median/Bilateral】

平滑 也称 模糊, 是一项简单且使用频率很高的图像处理方法。平滑处理的用途有很多,现在我们关注它减少噪声的功用 。平滑处理时需要用到一个 滤波器 。

文章目录

  • 前言
  • 一、函数介绍
    • 1、均值滤波--Blur
    • 2、高斯滤波--Gaussian
    • 3、中值滤波--Median
    • 4、双边滤波--Bilateral
  • 二、演示
    • 1、GUI
    • 2、实现代码
      • 1、 blurBtn的clicked()槽函数实现
      • 2、 gaussianBtn的clicked()槽函数实现
      • 3、 medianBtn的clicked()槽函数实现
      • 4、 bilateralBtn的clicked()槽函数实现
  • 总结


前言

越来越多的开发人员选择基于开源的Qt框架与OpenCV来实现界面和算法,其原因不单单是无版权问题,更多是两个社区的发展蓬勃,可用来学习的资料与例程特别丰富。以下是关于利用Qt构建GUI并使用OpenCV中的Blur/Gaussian/Median/Bilateral函数进行图像平滑处理。
软件版本:Qt-5.12.0/OpenCV-4.5.3
平台:Windows10/11–64

一、函数介绍

1、均值滤波–Blur

函数原型
cv::blur(InputArray src, OutputArray dst, Size ksize, Point anchor=Point(-1,-1), int borderType=BORDER_DEFAULT )

参数解释
src:输入图像,即源图像,填Mat类的对象即可。该函数对通道是独立处理的,且可以处理任意通道数的图片,但需要注意,待处理的图片深度应该为CV_8U, CV_16U, CV_16S, CV_32F 以及 CV_64F之一;
dst:即目标图像,需要和源图片有一样的尺寸和类型。比如可以用Mat::Clone,以源图片为模板,来初始化得到如假包换的目标图;
ksize:内核的大小。一般这样写Size( w,h )来表示内核的大小( 其中,w 为像素宽度, h为像素高度)。Size(3,3)就表示3x3的核大小,Size(5,5)就表示5x5的核大小
anchor:表示锚点(即被平滑的那个点),注意他有默认值Point(-1,-1)。如果这个点坐标是负值的话,就表示取核的中心为锚点,所以默认值Point(-1,-1)表示这个锚点在核的中心;
borderType:用于推断图像外部像素的某种边界模式。有默认值BORDER_DEFAULT;

2、高斯滤波–Gaussian

函数原型:

cv::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计算出来;

3、中值滤波–Median

函数原型
cv::medianBlur( InputArray src, OutputArray dst, int ksize )

参数解释
src:InputArray类型的src,输入图像,填Mat类的对象即可。待处理的图片深度应该为CV_8U, CV_16U, CV_16S, CV_32F 以及 CV_64F之一;
dst:OutputArray类型的dst,即输出图像,与源图片有一样的尺寸和类型;
ksize:Size类型的ksize,内核的大小,只能为奇数;

4、双边滤波–Bilateral

函数原型
cv::bilateralFilter(InputArray src, OutpuArray dst, Int d, double sigmaColor, double sigmaSpace, Int borderType)

参数解释

src: 是需要处理的图像,即原始图像。它能够有任意数量的通道,并能对各通道独立处理。图像深度应该是CV_8U、CV_16U、CV_16S、CV_32F或者CV_64F中的一 种。;
** dst**:是返回值,表示进行双边滤波后得到的处理结果;
d:是在滤波时选取的空间距离参数,这里表示以当前像素点为中心点的直径。如果该值为非正数,则会自动从参数 sigmaSpace计算得到。如果滤波空间较大(d>5),则速度较慢。因此,在实时应用中,推荐d=5。对于较大噪声的离线滤波,可以选择d=9;
sigmaColor:是滤波处理时选取的颜色差值范围,该值决定了周围哪些像素点能够参与到滤波中来。与当前像素点的像素值差值小于 sigmaColor 的像素点,能够参与到当前的滤波中。该值越大,就说明周围有越多的像素点可以参与到运算中。该值为0时,滤波失去意义;该值为255时,指定直径内的所有点都能够参与运算;
sigmaSpace:是坐标空间中的sigma值。它的值越大,说明有越多的点能够参与到滤波计算中来。当d>0时,无论sigmaSpace的值如何,d都指定邻域大小;否则,d与 sigmaSpace的值成比例;
borderType:是边界样式,该值决定了以何种方式处理边界。一般情况下,不需要考虑该值,直接采用默认值即可;

二、演示

1、GUI

【Qt&OpenCV 图像平滑/滤波处理 -- Blur/Gaussian/Median/Bilateral】_第1张图片如上图创建Blur/Gaussian/Median/Bilateral四个功能按钮QPushButton,对当前窗口的图像进行滤波操作,并输出状态信息。

2、实现代码

1、 blurBtn的clicked()槽函数实现

void MainWindow::on_blurBtn_clicked()
{
    std::size_t numView = ui->tabWidget->currentIndex() % 3;
    if (dispMat[numView]->empty())
    {
        outputInfo(2, tr("Please make sure the Mat exist!"));
        return;
    }
    int kernelVal = ui->kernelSpin->value();
    if (kernelVal % 2 == 0)
    {
        kernelVal += 1;
    }
    cv::blur(*dispMat[numView], *dispMat[numView], cv::Size(kernelVal, kernelVal),\ 	// 均值滤波Blur
             cv::Point(-1, -1));
    cvtMatPixmap(dispMat, dispPixmap, numView);
    outputInfo(1, tr("Blur done."));
}

2、 gaussianBtn的clicked()槽函数实现

void MainWindow::on_gaussianBtn_clicked()
{
    std::size_t numView = ui->tabWidget->currentIndex() % 3;
    if (dispMat[numView]->empty())
    {
        outputInfo(2, tr("Please make sure the Mat exist!"));
        return;
    }
    int kernelVal = ui->kernelSpin->value();
    if (kernelVal % 2 == 0)
    {
        kernelVal += 1;
    }
    cv::GaussianBlur(*dispMat[numView], *dispMat[numView], cv::Size(kernelVal, kernelVal),\ 	// 高斯滤波Gaussian
             0, 0);
    cvtMatPixmap(dispMat, dispPixmap, numView);
    outputInfo(1, tr("Gaussian done."));

}

3、 medianBtn的clicked()槽函数实现

void MainWindow::on_medianBtn_clicked()
{
    std::size_t numView = ui->tabWidget->currentIndex() % 3;
    if (dispMat[numView]->empty())
    {
        outputInfo(2, tr("Please make sure the Mat exist!"));
        return;
    }
    int kernelVal = ui->kernelSpin->value();
    if (kernelVal % 2 == 0)
    {
        kernelVal += 1;
    }
    cv::medianBlur(*dispMat[numView], *dispMat[numView], kernelVal); 	// 中值滤波Median
    cvtMatPixmap(dispMat, dispPixmap, numView);
    outputInfo(1, tr("Meidan done."));

}

4、 bilateralBtn的clicked()槽函数实现

void MainWindow::on_bilateralBtn_clicked()
{
    std::size_t numView = ui->tabWidget->currentIndex() % 3;
    if (dispMat[numView]->empty())
    {
        outputInfo(2, tr("Please make sure the Mat exist!"));
        return;
    }
    int kernelVal = ui->kernelSpin->value();
    if (kernelVal % 2 == 0)
    {
        kernelVal += 1;
    }
    cv::Mat tmpMat = cv::Mat::zeros(dispMat[numView]->rows, \
                                    dispMat[numView]->cols, \
                                    dispMat[numView]->type());
    double time = static_cast<double>(cv::getTickCount());

    cv::bilateralFilter(*dispMat[numView], tmpMat, kernelVal, \ 	// 双边滤波Bilateral
                        static_cast<double>(kernelVal * 2), \
                        static_cast<double>(kernelVal / 2));

    time = (static_cast<double>(cv::getTickCount()) - \				// 计算耗时
            time) / cv::getTickFrequency();
    QString costTime = "Cost time: " + QString::number(time);

    *dispMat[numView] = tmpMat.clone();
    cvtMatPixmap(dispMat, dispPixmap, numView);
    outputInfo(1, costTime);
    outputInfo(1, tr("Bilateral done."));

}

总结

以上是关于利用Qt进行GUI构建并使用OpenCV中的Blur/Gaussian/Median/Bilateral函数进行图像平滑/滤波处理。
参考:
链接: 往期https://blog.csdn.net/richard_yuu/article/details/127923490

其中疑问或错误,欢迎联系交流,微信:electrical_program

你可能感兴趣的:(Qt&OpenCV,opencv,qt)