【Qt_OpenCV基础篇 - 003】线型滤波种类、特点、适用范围及OpenCV实现

一、开发环境

1、Windows 7 64位 SP1 旗舰版;

2、Qt 5.10.1;

3、OpenCV 3.4.1

二、线型滤波

    图像平滑处理又称为图像模糊,主要是用来减少图像上的噪声点或者失真。图像滤波是在尽量保留图像细节特征的条件下对目标图像的噪声进行抑制,是图像预处理中不可或缺的操作,其处理效果的好坏将直接影响后续图像处理和分析的效率。

    图像滤波分为线型滤波和非线性滤波,其中线型滤波根据滤波器特性可以分为低通滤波、高通滤波、带通滤波、带阻滤波器、全通滤波和陷波滤波等。由于图像的细节信息包含在图像的高频部分,因此低通滤波具有图像模糊的效果,而高通滤波具有图像锐化的特点。

    这里介绍的线型滤波包括方框滤波、均值滤波和高斯滤波,三者均为低通滤波,具有消除造成,图像模糊的特点。其中,均值滤波为归一化后的方框滤波,而高斯滤波主要用来去除图像混入的高斯噪声。

    这里仅介绍各滤波函数的实现方式,并通过OpenCV示例演示器效果,具体理论部分请参考相应教材或者论坛。

三、OpenCV实现

3.1 方框滤波

OpenCV函数原型及参数说明:

void boxFilter( InputArray src, OutputArray dst, int ddepth,
                Size ksize, Point anchor = Point(-1,-1),
                bool normalize = true,
                int borderType = BORDER_DEFAULT );
@param src input image.
@param dst output image of the same size and type as src.
@param ddepth the output image depth (-1 to use src.depth()).
@param ksize blurring kernel size.
@param anchor anchor point; default value Point(-1,-1) means that the anchor is at the kernel center.
@param normalize flag, specifying whether the kernel is normalized by its area or not.
@param borderType border mode used to extrapolate pixels outside of the image, see cv::BorderTypes	

3.2 均值滤波

OpenCV函数原型及参数说明:

void blur( InputArray src, OutputArray dst,
           Size ksize, Point anchor = Point(-1,-1),
           int borderType = BORDER_DEFAULT );
@param src input image; it can have any number of channels, which are processed independently, 
       but the depth should be CV_8U, CV_16U, CV_16S, CV_32F or CV_64F.
@param dst output image of the same size and type as src.
@param ksize blurring kernel size.
@param anchor anchor point; default value Point(-1,-1) means that the anchor is at the kernel center.
@param borderType border mode used to extrapolate pixels outside of the image, see cv::BorderTypes


3.3 高斯滤波

OpenCV函数原型及参数说明:

void GaussianBlur( InputArray src, OutputArray dst, Size ksize,
                   double sigmaX, double sigmaY = 0,
                   int borderType = BORDER_DEFAULT );
@param src input image; the image can have any number of channels, which are processed
       independently, but the depth should be CV_8U, CV_16U, CV_16S, CV_32F or CV_64F.
@param dst output image of the same size and type as src.
@param ksize Gaussian kernel size. ksize.width and ksize.height can differ but they both must be
       positive and odd. Or, they can be zero's and then they are computed from sigma.
@param sigmaX Gaussian kernel standard deviation in X direction.
@param sigmaY Gaussian kernel standard deviation in Y direction; if sigmaY is zero, it is set to be
       equal to sigmaX, if both sigmas are zeros, they are computed from ksize.width and ksize.height,
       respectively (see cv::getGaussianKernel for details); to fully control the result regardless of
       possible future modifications of all this semantics, it is recommended to specify all of ksize,
       sigmaX, and sigmaY.
@param borderType pixel extrapolation method, see cv::BorderTypes

四、示例设计与测试

4.1 示例设计思路

    基于MainWindow设计界面程序,演示三种线型滤波处理同一副图像的处理结果。界面设计如图1所示:

【Qt_OpenCV基础篇 - 003】线型滤波种类、特点、适用范围及OpenCV实现_第1张图片

图1 界面设计

4.2 示例源码及运行效果演示

    下面是软件源码,主要包括两部分,及mainwindow.h和mainwindow.cpp。由于代码内容清晰,无需太多注释和提示,直接参考即可。

mainwindow.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include 

#include "opencv2/opencv.hpp"
using namespace cv;

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void on_pushButton_clicked();

    void on_horizontalSlider_BoxFilter_valueChanged(int value);

    void on_horizontalSlider_Blur_valueChanged(int value);

    void on_horizontalSlider_GaussianBlur_valueChanged(int value);

    void on_horizontalSlider_FilterAll_valueChanged(int value);

private:
    Ui::MainWindow *ui;

    int m_kernelValueBoxFilter;
    int m_kernelValueBlur;
    int m_kernelValueGaussianBlur;
    int m_kernelAll;

    bool m_isOpenFile;

    Mat m_srcImage;
    Mat m_dstImage_BoxFilter;
    Mat m_dstImage_Blur;
    Mat m_dstImage_GaussianBlur;

public:
    void on_BoxFilter(void);
    void on_Blur(void);
    void on_GaussianBlur(void);
};

#endif // MAINWINDOW_H

mainwindow.cpp:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include 
#include 

#define KERNEL_MIN_VALUE    0
#define KERNEL_MAX_VALUE    40

Mat g_srcImage;
Mat g_dstImage_BoxFilter;
Mat g_dstImage_Blur;
Mat g_dstImage_GaussianBlur;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->menuBar->hide();    //隐藏菜单栏
    ui->mainToolBar->hide();//隐藏工具栏
    ui->statusBar->hide();  //隐藏状态栏
    setWindowTitle(tr("Qt_OpenCV线型滤波"));

    //初始化变量
    m_kernelValueBoxFilter = 3;
    m_kernelValueBlur = 3;
    m_kernelValueGaussianBlur = 3;
    m_kernelAll = 3;
    m_isOpenFile = false;

    //初始化控件
    ui->horizontalSlider_BoxFilter->setMinimum(KERNEL_MIN_VALUE);
    ui->horizontalSlider_BoxFilter->setMaximum(KERNEL_MAX_VALUE);
    ui->horizontalSlider_BoxFilter->setValue(m_kernelValueBoxFilter);

    ui->horizontalSlider_Blur->setMinimum(KERNEL_MIN_VALUE);
    ui->horizontalSlider_Blur->setMaximum(KERNEL_MAX_VALUE);
    ui->horizontalSlider_Blur->setValue(m_kernelValueBlur);

    ui->horizontalSlider_GaussianBlur->setMinimum(KERNEL_MIN_VALUE);
    ui->horizontalSlider_GaussianBlur->setMaximum(KERNEL_MAX_VALUE);
    ui->horizontalSlider_GaussianBlur->setValue(m_kernelValueGaussianBlur);

    ui->horizontalSlider_FilterAll->setMinimum(KERNEL_MIN_VALUE);
    ui->horizontalSlider_FilterAll->setMaximum(KERNEL_MAX_VALUE);
    ui->horizontalSlider_FilterAll->setValue(m_kernelAll);

    ui->label_Kernel_BoxFilter->setText(QString::number(m_kernelValueBoxFilter));
    ui->label_Kernel_Blur->setText(QString::number(m_kernelValueBlur));
    ui->label_Kernel_GuassianBlur->setText(QString::number(m_kernelValueGaussianBlur));
    ui->label_Kernel_All->setText(QString::number(m_kernelAll));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked()
{
    QString fileName = QFileDialog::getOpenFileName(this,tr("Open Image"),".",tr("Image File(*.png *.jpg *.jpeg *.bmp)"));
    if (fileName.isEmpty())
    {
        return;
    }

    m_srcImage = imread(fileName.toLatin1().data());//读取图片数据
    if (!m_srcImage.data)
    {
        m_isOpenFile = false;
        QMessageBox box(QMessageBox::Critical, "打开图像", "读取图像文件失败!请重新打开.");
        box.setStandardButtons(QMessageBox::Ok);
        box.setButtonText(QMessageBox::Ok, QString("确定"));
        box.exec();
        return;
    }
    m_isOpenFile = true;//修改打开标志

    on_BoxFilter();
    on_Blur();
    on_GaussianBlur();
}

void MainWindow::on_horizontalSlider_BoxFilter_valueChanged(int value)
{
    if (m_isOpenFile)
    {
        m_kernelValueBoxFilter = value;
        ui->label_Kernel_BoxFilter->setText(QString::number(m_kernelValueBoxFilter));
        on_BoxFilter();
    }
}

void MainWindow::on_horizontalSlider_Blur_valueChanged(int value)
{
    if (m_isOpenFile)
    {
        m_kernelValueBlur = value;
        ui->label_Kernel_Blur->setText(QString::number(m_kernelValueBlur));
        on_Blur();
    }
}

void MainWindow::on_horizontalSlider_GaussianBlur_valueChanged(int value)
{
    if (m_isOpenFile)
    {
        m_kernelValueGaussianBlur = value;
        ui->label_Kernel_GuassianBlur->setText(QString::number(m_kernelValueGaussianBlur));
        on_GaussianBlur();
    }
}

void MainWindow::on_horizontalSlider_FilterAll_valueChanged(int value)
{
    if (m_isOpenFile)
    {
        m_kernelAll = value;
        ui->label_Kernel_All->setText(QString::number(m_kernelAll));

        ui->horizontalSlider_BoxFilter->setValue(m_kernelAll);
        ui->horizontalSlider_Blur->setValue(m_kernelAll);
        ui->horizontalSlider_GaussianBlur->setValue(m_kernelAll);
    }
}

void MainWindow::on_BoxFilter()
{
    boxFilter(m_srcImage, m_dstImage_BoxFilter, -1, Size(m_kernelValueBoxFilter + 1, m_kernelValueBoxFilter + 1));
    cvtColor(m_dstImage_BoxFilter, m_dstImage_BoxFilter, COLOR_BGR2RGB);//图像格式转换
    QImage disImage = QImage((const unsigned char*)(m_dstImage_BoxFilter.data),m_dstImage_BoxFilter.cols,m_dstImage_BoxFilter.rows,QImage::Format_RGB888);
    ui->label_Display1->setPixmap(QPixmap::fromImage(disImage.scaled(ui->label_Display1->width(), ui->label_Display1->height(), Qt::KeepAspectRatio)));
}

void MainWindow::on_Blur()
{
    blur(m_srcImage, m_dstImage_Blur, Size(m_kernelValueBlur + 1, m_kernelValueBlur + 1), Point(-1, -1));
    cvtColor(m_dstImage_Blur, m_dstImage_Blur, COLOR_BGR2RGB);//图像格式转换
    QImage disImage = QImage((const unsigned char*)(m_dstImage_Blur.data),m_dstImage_Blur.cols,m_dstImage_Blur.rows,QImage::Format_RGB888);
    ui->label_Display2->setPixmap(QPixmap::fromImage(disImage.scaled(ui->label_Display2->width(), ui->label_Display2->height(), Qt::KeepAspectRatio)));
}

void MainWindow::on_GaussianBlur()
{
    GaussianBlur(m_srcImage, m_dstImage_GaussianBlur, Size(m_kernelValueGaussianBlur * 2 + 1, m_kernelValueGaussianBlur * 2 + 1), 0, 0);
    cvtColor(m_dstImage_GaussianBlur, m_dstImage_GaussianBlur, COLOR_BGR2RGB);//图像格式转换
    QImage disImage = QImage((const unsigned char*)(m_dstImage_GaussianBlur.data),m_dstImage_GaussianBlur.cols,m_dstImage_GaussianBlur.rows,QImage::Format_RGB888);
    ui->label_Display3->setPixmap(QPixmap::fromImage(disImage.scaled(ui->label_Display3->width(), ui->label_Display3->height(), Qt::KeepAspectRatio)));
}

    运行效果如下图2、图3、图4、图5所示:

【Qt_OpenCV基础篇 - 003】线型滤波种类、特点、适用范围及OpenCV实现_第2张图片

图2 原始图像

【Qt_OpenCV基础篇 - 003】线型滤波种类、特点、适用范围及OpenCV实现_第3张图片

图3 Kernel为3

【Qt_OpenCV基础篇 - 003】线型滤波种类、特点、适用范围及OpenCV实现_第4张图片

图4 Kernel为5(1)

【Qt_OpenCV基础篇 - 003】线型滤波种类、特点、适用范围及OpenCV实现_第5张图片

图5 Kernel为5(2)



你可能感兴趣的:(Qt_OpenCV基础篇,【Qt-OpenCV基础篇】)