学习Qt_OpenCV形态学腐蚀、膨胀及OpenCV实现

参考教程:https://blog.csdn.net/qingyang8513/article/details/80413402

数学形态学是一门建立在格论和拓扑学基础之上的图像分析学科,是数学形态学图像处理的基本理论,其基本运算包括:二值腐蚀和膨胀、二值开闭运算、骨架抽取、极限腐蚀、击中击不中变换、形态学梯度、Top-hat变换、颗粒分析、流域变换、灰度腐蚀和膨胀、灰度形态学梯度等。

    腐蚀与膨胀主要功能:

    1)消除噪声;

    2)分割;

    3)寻找图像中的明显极大值区域或极小值区域;

    4)求图像梯度;

    膨胀就是求局部最大值的操作,针对的是图像中的高亮部分。从数学角度,膨胀或者腐蚀均是将图像A与核B进行卷积运算。核可以是任意形状和大小,其拥有一个单独定义出来的参考点,称其为锚点。膨胀运算是将核B与图像A进行卷积运算,求出局部最大值,并幅值给锚点。直观地,膨胀处理的结果是使图像的高亮部分区域增加。

    腐蚀与膨胀的原理相同,均是采用图像A与核B进行卷积运算,不同的是腐蚀是求局部最小值的过程,运算结果是使图像高亮部分区域减少,或者可以说是图像较暗的区域增加。

膨胀原理:求局部最大值

实现方法:

①定义一个卷积核B,核可以是任何的形状和大小,且拥有一个单独定义出来的参考点 - 锚点(anchorpoint);

通常和为带参考点的正方形或者圆盘,可将核称为模板或掩膜;

②将核B与图像A进行卷积,计算核B覆盖区域的像素点最大值;

③将这个最大值赋值给参考点指定的像素;

因此,图像中的高亮区域逐渐增长。

腐蚀原理:求局部最小值(与膨胀相反);

实现方法:

①定义一个卷积核B,核可以是任何的形状和大小,且拥有一个单独定义出来的参考点 - 锚点(anchorpoint);

通常和为带参考点的正方形或者圆盘,可将核称为模板或掩膜;

②将核B与图像A进行卷积,计算核B覆盖区域的像素点最小值;

③将这个最小值赋值给参考点指定的像素;

因此,图像中的高亮区域逐渐减小。


原文:https://blog.csdn.net/qq_39861376/article/details/82111292 
 

OpenCV实现

1、膨胀函数原型:

dilate()

void cv::dilate ( InputArray  src,
    OutputArray  dst,
    InputArray  kernel,
    Point  anchor = Point(-1,-1),
    int  iterations = 1,
    int  borderType = BORDER_CONSTANT,
    const Scalar &  borderValue = morphologyDefaultBorderValue() 
  )    

 

#include

通过使用特定的结构元素来扩展图像。

该函数使用指定的结构元素扩展源图像,该结构元素确定采用最大值的像素邻域的形状:

该功能支持就地模式。扩张可以应用几次(迭代)次。在多通道图像的情况下,每个通道被独立处理。

参数

SRC 输入图像; 通道数可以是任意的,但深度应该是CV_8U,CV_16U,CV_16S,CV_32F或CV_64F之一。
DST 输出与src相同大小和类型的图像。
核心 结构元素用于扩张; 如果elemenat = Mat(),则使用3 x 3矩形结构元素。可以使用getStructuringElement创建内核
锚点在元素内的位置; 默认值(-1,-1)表示锚点位于元素中心。
迭代 应用扩张的次数。
borderType 像素外推法,参见BorderTypes
borderValue 边界不变的边界值

 

2、腐蚀函数原型:

erode()

void cv::erode ( InputArray  src,
    OutputArray  dst,
    InputArray  kernel,
    Point  anchor = Point(-1,-1),
    int  iterations = 1,
    int  borderType = BORDER_CONSTANT,
    const Scalar &  borderValue = morphologyDefaultBorderValue() 
  )    

 

#include

使用特定的结构元素侵蚀图像。

该函数使用指定的结构元素侵蚀源图像,该结构元素确定采用最小值的像素邻域的形状:

该功能支持就地模式。侵蚀可以应用几次(迭代)次。在多通道图像的情况下,每个通道被独立处理。

参数

SRC 输入图像; 通道数可以是任意的,但深度应该是CV_8U,CV_16U,CV_16S,CV_32F或CV_64F之一。
DST 输出与src相同大小和类型的图像。
核心 用于侵蚀的结构元素; if element=Mat(),使用3 x 3矩形结构元素。可以使用getStructuringElement创建内核。
锚点在元素内的位置; 默认值(-1,-1)表示锚点位于元素中心。
迭代 腐蚀的次数。
borderType 像素外推法,参见BorderTypes
borderValue 边界不变的边界值

示例设计与测试

 界面设计

学习Qt_OpenCV形态学腐蚀、膨胀及OpenCV实现_第1张图片

mainwindow.ui



 MainWindow
 
  
   
    0
    0
    655
    416
   
  
  
   MainWindow
  
  
   
    
     
      30
      20
      54
      12
     
    
    
     原始图像:
    
   
   
    
     
      360
      20
      54
      12
     
    
    
     运行效果:
    
   
   
    
     
      30
      70
      261
      191
     
    
    
     border:1px solid black
    
    
     Original  Image
    
   
   
    
     
      360
      70
      261
      191
     
    
    
     border:1px solid black
    
    
     Processed  Image
    
   
   
    
     
      30
      320
      54
      12
     
    
    
     核大小:
    
   
   
    
     
      120
      320
      21
      20
     
    
    
     background-color: rgb(255, 85, 127);
    
    
     
    
    
     Qt::AlignCenter
    
   
   
    
     
      160
      320
      221
      20
     
    
    
     Qt::Horizontal
    
   
   
    
     
      550
      320
      75
      23
     
    
    
     打开图像
    
   
   
    
     
      468
      321
      71
      21
     
    
   
   
    
     
      400
      320
      61
      16
     
    
    
     操作类型:
    
   
  
  
   
    
     0
     0
     655
     23
    
   
  
  
   
    TopToolBarArea
   
   
    false
   
  
  
 
 
 
 

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:
    Ui::MainWindow *ui;

    int m_KernelValue;
    bool m_isOpenFile;
    int m_typeCurSel;

    Mat m_srcImage;
    Mat m_dstImage;

public:
    void on_Dilate(void);
    void on_Erode(void);
private slots:
    void on_pushButton_OpenImg_clicked();
    void on_comboBox_Type_currentIndexChanged(int index);
    void on_horizontalSlider_KernelValue_valueChanged(int value);
};

#endif // MAINWINDOW_H

mainwindow.cpp

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

#define KERNEL_MIN_VALUE    0
#define KERNEL_MAX_VALUE    40

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    setWindowTitle(tr("Qt_OpenCV线型滤波"));

    //初始化变量
    m_KernelValue = 1;
    m_isOpenFile = false;
    m_typeCurSel = 0;

    //初始化控件
    ui->horizontalSlider_KernelValue->setMinimum(KERNEL_MIN_VALUE);
    ui->horizontalSlider_KernelValue->setMaximum(KERNEL_MAX_VALUE);
    ui->horizontalSlider_KernelValue->setValue(m_KernelValue);
    ui->label_KernelValue->setText(QString::number(m_KernelValue));

    ui->comboBox_Type->insertItem(0, "膨胀");
    ui->comboBox_Type->insertItem(1, "腐蚀");
    ui->comboBox_Type->setCurrentIndex(m_typeCurSel);
}

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

void MainWindow::on_pushButton_OpenImg_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;//修改打开标志

    Mat disImageTemp;
    cvtColor(m_srcImage, disImageTemp, COLOR_BGR2RGB);//图像格式转换
    QImage disImage = QImage((const unsigned char*)(disImageTemp.data),disImageTemp.cols,disImageTemp.rows,QImage::Format_RGB888);
    ui->label_OriginalImg->setPixmap(QPixmap::fromImage(disImage.scaled(ui->label_OriginalImg->width(), ui->label_OriginalImg->height(), Qt::KeepAspectRatio)));

    if (m_typeCurSel == 0)
    {
        on_Dilate();
    }
    else
    {
        on_Erode();
    }
}

void MainWindow::on_horizontalSlider_KernelValue_valueChanged(int value)
{
    if (m_isOpenFile)
    {
        m_KernelValue = value;
        ui->label_KernelValue->setText(QString::number(m_KernelValue));
        if (m_typeCurSel == 0)
        {
            on_Dilate();
        }
        else
        {
            on_Erode();
        }
    }
}

void MainWindow::on_Dilate()
{
    //获取内核形状和尺寸
    Mat element = getStructuringElement(MORPH_RECT, Size(m_KernelValue * 2 + 1, m_KernelValue * 2 + 1), Point(m_KernelValue, m_KernelValue));

    //膨胀操作
    dilate(m_srcImage, m_dstImage, element);

    //显示
    cvtColor(m_dstImage, m_dstImage, COLOR_BGR2RGB);//图像格式转换
    QImage disImage = QImage((const unsigned char*)(m_dstImage.data),m_dstImage.cols,m_dstImage.rows,QImage::Format_RGB888);
    ui->label_ProcessedImg->setPixmap(QPixmap::fromImage(disImage.scaled(ui->label_ProcessedImg->width(), ui->label_ProcessedImg->height(), Qt::KeepAspectRatio)));
}

void MainWindow::on_Erode()
{
    //获取内核形状和尺寸
    Mat element = getStructuringElement(MORPH_RECT, Size(m_KernelValue * 2 + 1, m_KernelValue * 2 + 1), Point(m_KernelValue, m_KernelValue));

    //腐蚀操作
    erode(m_srcImage, m_dstImage, element);

    //显示
    cvtColor(m_dstImage, m_dstImage, COLOR_BGR2RGB);//图像格式转换
    QImage disImage = QImage((const unsigned char*)(m_dstImage.data),m_dstImage.cols,m_dstImage.rows,QImage::Format_RGB888);
    ui->label_ProcessedImg->setPixmap(QPixmap::fromImage(disImage.scaled(ui->label_ProcessedImg->width(), ui->label_ProcessedImg->height(), Qt::KeepAspectRatio)));
}

void MainWindow::on_comboBox_Type_currentIndexChanged(int index)
{
    m_typeCurSel = index;
    if (m_isOpenFile)
    {
        if (m_typeCurSel == 0)
        {
            on_Dilate();
        }
        else
        {
            on_Erode();
        }
    }
}

pro文件:

#-------------------------------------------------
#
# Project created by QtCreator 2019-07-12T14:41:02
#
#-------------------------------------------------

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = OpenCV_Filter
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

CONFIG += c++11

SOURCES += \
        main.cpp \
        mainwindow.cpp

HEADERS += \
        mainwindow.h

FORMS += \
        mainwindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
INCLUDEPATH += $$PWD/../opencv_qt/include\
             $$PWD/../opencv_qt/include/opencv\
              $$PWD/../opencv_qt/include/opencv2

unix|win32: LIBS += -L$$PWD/../opencv_qt/bin/ -llibopencv_calib3d410
unix|win32: LIBS += -L$$PWD/../opencv_qt/bin/ -llibopencv_core410
unix|win32: LIBS += -L$$PWD/../opencv_qt/bin/ -llibopencv_dnn410
unix|win32: LIBS += -L$$PWD/../opencv_qt/bin/ -llibopencv_features2d410
unix|win32: LIBS += -L$$PWD/../opencv_qt/bin/ -llibopencv_flann410
unix|win32: LIBS += -L$$PWD/../opencv_qt/bin/ -llibopencv_highgui410
unix|win32: LIBS += -L$$PWD/../opencv_qt/bin/ -llibopencv_imgcodecs410
unix|win32: LIBS += -L$$PWD/../opencv_qt/bin/ -llibopencv_imgproc410
unix|win32: LIBS += -L$$PWD/../opencv_qt/bin/ -llibopencv_ml410
unix|win32: LIBS += -L$$PWD/../opencv_qt/bin/ -llibopencv_objdetect410
unix|win32: LIBS += -L$$PWD/../opencv_qt/bin/ -llibopencv_photo410
unix|win32: LIBS += -L$$PWD/../opencv_qt/bin/ -llibopencv_stitching410
unix|win32: LIBS += -L$$PWD/../opencv_qt/bin/ -llibopencv_video410
unix|win32: LIBS += -L$$PWD/../opencv_qt/bin/ -llibopencv_videoio410
unix|win32: LIBS += -L$$PWD/../opencv_qt/bin/ -lopencv_ffmpeg410

演示结果:

学习Qt_OpenCV形态学腐蚀、膨胀及OpenCV实现_第2张图片

学习Qt_OpenCV形态学腐蚀、膨胀及OpenCV实现_第3张图片

可以看到膨胀就是让企鹅图像中白色(高亮)部分增多,腐蚀让企鹅黑色(暗色)部分增多。

你可能感兴趣的:(学习笔记)