Qt+opencv图像形态学滤波:腐蚀与膨胀学习

Qt+opencv图像腐蚀与膨胀

概述

形态学操作就是基于形状的一系列图像处理操作。通过将 结构元素 作用于输入图像来产生输出图像。
最基本的形态学操作有二:腐蚀与膨胀(Erosion 与 Dilation)。
腐蚀和膨胀是对白色部分(高亮部分)而言的,不是黑色部分。膨胀就是图像中的高亮部分进行膨胀,“领域扩张”,效果图拥有比原图更大的高亮区域。腐蚀就是原图中的高亮部分被腐蚀,“领域被蚕食”,效果图拥有比原图更小的高亮区域。
一般操作之前会先用getStructuringElement取得指定形状核尺寸的内核矩阵的结构元素。核的形状可以自定义,可以是矩形、十字形、椭圆形。

enum MorphShapes {
    
    
    MORPH_RECT    = 0, //!< a rectangular structuring element:  \f[E_{ij}=1\f]
    MORPH_CROSS   = 1, //!< a cross-shaped structuring element:
                       //!< \f[E_{ij} =  \fork{1}{if i=\texttt{anchor.y} or j=\texttt{anchor.x}}{0}{otherwise}\f]
    MORPH_ELLIPSE = 2 //!< an elliptic structuring element, that is, a filled ellipse inscribed
                      //!< into the rectangle Rect(0, 0, esize.width, 0.esize.height)
};

膨胀与腐蚀可实现多种功能,如下:

  • 消除噪声
  • 分割出独立的图像元素,在图像中连接相邻的元素
  • 寻找图像中的明显的极大值区域或极小值区域
  • 求图像的梯度

膨胀

膨胀就是求局部区域最大值,输入图与内核做卷积,计算出核覆盖的区域的像素点最大值,然后把这个最大值赋值给指定的像素,这一最大化操作将会导致图像中的亮区开始”扩展” ,即是膨胀效果。
公式:
在这里插入图片描述
函数原型:
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() )
参数说明:
src 输入图像
dst 输出图像
kernel 膨胀操作的核,为NULL时,默认采用参考点位于中心的3x3的核。
anchor 锚点
iterations 膨胀操作的次数,默认为1次
borderType 用于推断图像外部的某种边界
borderValue 边界为常数时的边界值

代码:

// 全局变量
Mat srcImage, erosion_dst, dilation_dst;
int erosion_size = 0;
int dilation_elem = 0;
int dilation_size = 0;

ErosionDilation::ErosionDilation(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ErosionDilation)
{
    
    
    ui->setupUi(this);
    
    srcImage = imread("F:/work/opencv/morph/sss.jpg");
    erosion_dst = srcImage.clone();
    dilation_dst = srcImage.clone();
    connect(ui->horizontalSlider,&QSlider::valueChanged,[=](int value)
    {
    
    
        int k_size = 2*value+1;
        ui->label_2->setText(QString("内核大小:%1").arg(k_size));
        //Erosion(value);
        Dilation(value);
    });
    bgrMat2Image(srcImage);
    ui->radioButton_1->setChecked(true);
}

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

void ErosionDilation::bgrMat2Image(cv::Mat &mat)
{
    
    
    cv::Mat rgb = mat.clone();
    if(mat.channels() == 3)
    {
    
    
        cv::cvtColor(rgb, rgb, CV_BGR2RGB);
        mImage = QImage((const uchar*)(rgb.data),rgb.cols,rgb.rows,rgb.cols*rgb.channels(),QImage::Format_RGB888);
    }
    else if(mat.channels() == 4)
    {
    
    
        cv::cvtColor(mat, mat, CV_BGRA2RGBA);
        mImage = QImage((const uchar*)(mat.data),mat.cols,mat.rows,QImage::Format_ARGB32);
    }
    else
    {
    
    
        cv::cvtColor(mat, mat, CV_GRAY2RGB);
        mImage = QImage((const uchar*)mat.data,mat.cols,mat.rows,QImage::Format_Indexed8);
    }
    mImage.bits();

    //QLabel显示
    ui->label->setPixmap(QPixmap::fromImage(mImage));
}

void ErosionDilation::Dilation(int value)
{
    
    
  int dilation_type;
  if(ui->radioButton_1->isCheckable())
  {
    
    
      dilation_type = MORPH_RECT;
  }
  else if(ui->radioButton_2->isCheckable())
  {
    
    
      dilation_type = MORPH_CROSS;
  }
  else if(ui->radioButton_3->isCheckable())
  {
    
    
      dilation_type = MORPH_ELLIPSE;
  }
  dilation_size = value;

  Mat element = getStructuringElement( dilation_type,
                                       Size( 2*dilation_size + 1, 2*dilation_size+1 ),
                                       Point( dilation_size, dilation_size ) );
  // 膨胀操作
  dilate( srcImage, dilation_dst, element );
  // 显示
  bgrMat2Image(dilation_dst);
}

效果展示:
在这里插入图片描述

腐蚀

腐蚀提取的是覆盖下的相素最小值。
进行腐蚀操作时,输入图与内核做卷积,计算出核覆盖的区域的像素点最小值,然后把这个最小值赋值给指定的像素,并代替锚点位置的相素。
公式:
在这里插入图片描述
函数原型:
void erode( InputArray src, OutputArray dst, InputArray kernel,
Point anchor = Point(-1,-1), int iterations = 1,
int borderType = BORDER_CONSTANT,
const Scalar& borderValue = morphologyDefaultBorderValue() );
参数说明:
src 输入图像
dst 输出图像
kernel 膨胀操作的核,为NULL时,默认采用参考点位于中心的3x3的核。
anchor 锚点
iterations 膨胀操作的次数,默认为1次
borderType 用于推断图像外部的某种边界
borderValue 边界为常数时的边界值

测试代码:

void ErosionDilation::Erosion(int value)
{
    
    
  int erosion_type;
  if(ui->radioButton_1->isCheckable() )
  {
    
    
      erosion_type = MORPH_RECT;
  }
  else if(ui->radioButton_2->isCheckable())
  {
    
    
      erosion_type = MORPH_CROSS;
  }
  else if(ui->radioButton_3->isCheckable())
  {
    
    
      erosion_type = MORPH_ELLIPSE;
  }
  erosion_size = value;

  Mat element = getStructuringElement( erosion_type,
                                       Size( 2*erosion_size + 1, 2*erosion_size+1 ),
                                       Point( erosion_size, erosion_size ) );

  // 腐蚀操作
  erode( srcImage, erosion_dst, element );
  // 显示
  bgrMat2Image(erosion_dst);
}

效果展示:
在这里插入图片描述

作者:费码程序猿
欢迎技术交流:QQ:255895056
转载请注明出处,如有不当欢迎指正

猜你喜欢

转载自blog.csdn.net/haohaohaihuai/article/details/106358831