Opencv3笔记11——形态学滤波(1)

3 形态学滤波(1):腐蚀与膨胀

3.1 形态学概述

数学形态学

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

膨胀和腐蚀

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

3.2 膨胀

膨胀(dilate)就是求局部的最大值的操作。从数学的角度就是图像与核进行卷积
核可以是任何形状核大小,它拥有一个单独定义出来的参考点,称为锚点,可以把核视为模板或者掩码
数学公式

d s t ( x , y ) = max ( x , y ) : e l e m e n t ( x , y ) 0 s r c ( x + x , y + y )

3.3 腐蚀

腐蚀就是求局部最小值的操作。
数学公式:

d s t ( x , y ) = min ( x , y ) : e l e m e n t ( x , y ) 0 s r c ( x + x , y + y )

3.4 相关API函数讲解

1 膨胀:dilate函数

函数原型

void dilate(InputArray src, OutputArray dst, InputArray kernel, Point anchor = Point(-1,-1),int iteration = 1,int borderType = BORDER_CONSTANT,const Scalar& borderValue=morphologyDefaultBorderValue());
  1. InputArray 类型的kernel,膨胀操作的核,当为NULL,表示使用参考点位于3×3的核。使用getStructuringElement配合这个参数使用,返回指定形状和尺寸的结构元素。矩形:MORPH_RECT,交叉形:MORPH_CROSS,椭圆形MORPH_ELLIPSE
  2. Point类型的anchor,锚的位置,表示锚的位置
  3. int类型的iterations,迭代使用erode()函数的次数
  4. int类型的borderType用于推断图像外部像素的某种边界模式

2 腐蚀:erode函数

函数原型

void erode(InputArray src, OutputArray dst, InputArray kernal, Point anchor = Point(-1,-1),int iterations = 1, int borderType = BORDER_CONSTANT,const Scalar & borderValue=morphologyDefualtBorderValue())

3.6 综合示例

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>

using namespace cv;
using namespace std;


//-----------------------【全局变量声明部分】-----------------------
//  描述:全局变量声明
//---------------------------------------------------------------

Mat g_srcImage, g_dstImage;     //原始图和效果图
int g_nTrackbarNumer = 0;       //0表示腐蚀,1表示膨胀
int g_nSructElementSize = 3;    //结构元素(内核矩阵)尺寸

//-----------------------【全局函数声明部分】-----------------------
//  描述:全局函数声明
//---------------------------------------------------------------

void Process();                 //腐蚀和膨胀的处理函数
void on_TrackbarNumChange(int, void *); //回调函数
void on_ElementSizeChange(int, void *); //回调函数


int main()
{
    system("color 5E");

    //载入原图
    g_srcImage = imread("1.jpg");
    if (!g_srcImage.data)
    {
        printf("读取srcImage错误~!\n");
        return false;
    }

    //显示原图
    namedWindow("【原始图】");
    imshow("【原始图】", g_srcImage);

    //进行腐蚀和膨胀操作并显示效果图
    namedWindow("【效果图】");

    //获取自定义核
    Mat element = getStructuringElement(MORPH_RECT, Size(2 * g_nSructElementSize + 1, 2 * g_nSructElementSize + 1), Point(g_nSructElementSize, g_nSructElementSize));
    erode(g_srcImage, g_dstImage, element);
    imshow("【效果图】", g_dstImage);

    //创建轨迹条
    createTrackbar("腐蚀/膨胀", "【效果图】", &g_nTrackbarNumer, 1, on_TrackbarNumChange);
    createTrackbar("内核尺寸", "【效果图】", &g_nSructElementSize, 21, on_ElementSizeChange);

    //按键q退出
    while (char(waitKey(1)) != 'q') {}
    return 0;
}

//-----------------【Process()函数】------------------------
//  描述:进行自定义的腐蚀核膨胀操作
//---------------------------------------------------------
void Process()
{
    Mat element = getStructuringElement(MORPH_RECT, Size(2 * g_nSructElementSize + 1, 2 * g_nSructElementSize + 1), Point(g_nSructElementSize, g_nSructElementSize));

    if (g_nTrackbarNumer == 0)
    {
        erode(g_srcImage, g_dstImage, element);
    }
    else
    {
        dilate(g_srcImage, g_dstImage, element);
    }

    //显示效果图
    imshow("【效果图】", g_dstImage);
}

//------------------------【on_TrackbarNumChange()函数】--------
//  描述:腐蚀核膨胀之间切换开关回调函数
//------------------------------------------------------------

void on_TrackbarNumChange(int, void *)
{
    Process();
}


//------------------------【on_ElementSizeChange()函数】--------
//  描述:腐蚀核膨胀内核改变回调函数
//------------------------------------------------------------

void on_ElementSizeChange(int, void *)
{
    Process();
}

这里写图片描述

这里写图片描述

这里写图片描述


猜你喜欢

转载自blog.csdn.net/huayunhualuo/article/details/81486884