Opencv3笔记12——形态学滤波(2)

4 形态学滤波(2):开运算、闭运算、形态学梯度、顶帽、黑帽

4.1 开运算

开运算(Opening Operation)其实就是先腐蚀后膨胀的过程

dst = open(src,element) = dilate(erode(src,element));

开运算用来消除小物体,在纤细处分离物体并且在平滑较大的物体的边界不明显改变其体积

4.2 闭运算

先膨胀后腐蚀的过程(Closing Operation)
dst = cleose(src,element) = erode(dilate(src,element))

能够排除小型的黑洞

4.3 形态学梯度

膨胀图与腐蚀图之差,dst = morph-grad(src,element) = dilate(sec,element-) - erode(src,element)

保留物体的边缘轮廓

4.4 顶帽

Top Hat(礼帽),是原图与开运算的结果图之差
dst = tophat(src, element) = src - open(src, element)

用来分离比临近点亮一些的斑点,可以进行背景提取

4.5 黑帽

Black Hat 是闭运算与原图像之差
dst = blackhat(src, element) = close(src,element) -src
用来分离比邻近点暗一些的斑点,效果图有着非常完美的轮廓

4.6 morphologyEx()

morphologyEx函数利用基本的腐蚀核膨胀技术,来执行更加高级的形态学变换

void morphologyEx(InputArray src,OutputArray dst, int op, InputArray kernel, Point anchor = Point(-1,-1),int iterations = 1, int borderType = BORDER_CONSTANT, const Scalar & borderValue=morphologyDefaultBorderValue());

这里写图片描述

4.7 综合示例

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

using namespace std;
using namespace cv;

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

Mat g_srcImage, g_dstImage;         //原始图和效果图
int g_nElementShape = MORPH_RECT;   //元素结构形状

//变量接受TrackBar位置参数
int g_nMaxIterationNum = 10;
int g_nOpenCloseNum = 0;
int g_nErodeDilateNum = 0;
int g_nTopBlackHatNum = 2;

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

static void on_OpenClose(int, void *);
static void on_ErodeDilate(int, void *);
static void on_TopBlackHat(int, void *);

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

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

    //创建三个窗口
    namedWindow("【开运算/闭运算】", 1);
    namedWindow("【腐蚀/膨胀】", 1);
    namedWindow("【顶帽/黑帽】", 1);

    //参数幅值
    g_nOpenCloseNum = 9;
    g_nErodeDilateNum = 9;
    g_nTopBlackHatNum = 2;

    //创建轨迹条
    createTrackbar("迭代值", "【开运算/闭运算】", &g_nOpenCloseNum, g_nMaxIterationNum * 2 + 1, on_OpenClose);
    createTrackbar("迭代值", "【腐蚀/膨胀】", &g_nErodeDilateNum, g_nMaxIterationNum * 2 + 1, on_ErodeDilate);
    createTrackbar("迭代值", "【顶帽/黑帽】", &g_nTopBlackHatNum, g_nMaxIterationNum * 2 + 1, on_TopBlackHat);

    //轮询获取信息
    while (1)
    {
        int c;
        //执行回调函数
        on_OpenClose(g_nOpenCloseNum, 0);
        on_ErodeDilate(g_nErodeDilateNum, 0);
        on_TopBlackHat(g_nTopBlackHatNum, 0);
        //获取按键
        c = waitKey(0);

        if ((char)c == 'q' || (char)c == 27)
        {
            break;
        }
        //按下键盘按键1 使用椭圆elliptic结构元素MORPH_ELLIPSE
        if ((char)c == 49)
        {
            g_nElementShape = MORPH_ELLIPSE;
        }
        else if ((char)c == 50) //按键2
        {
            g_nElementShape = MORPH_RECT;
        }
        else if ((char)c == 51)
        {
            g_nElementShape = MORPH_CROSS;
        }
        else if ((char)c == ' ')
        {
            g_nElementShape = (g_nElementShape + 1) % 3;
        }
    }
    return 0;
}
//-------------------【on_OpenClose()函数】-------------------
//  描述:开运算/闭运算窗口的回调函数
//----------------------------------------------------------
static void on_OpenClose(int, void *)
{
    //偏移量
    int offset = g_nOpenCloseNum - g_nMaxIterationNum;
    int Absolute_offset = offset > 0 ? offset : -offset;    //绝对值
    Mat element = getStructuringElement(g_nElementShape, Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1), Point(Absolute_offset, Absolute_offset));
    if (offset < 0)
    {
        morphologyEx(g_srcImage, g_dstImage, MORPH_OPEN, element);
    }
    else
    {
        morphologyEx(g_srcImage, g_dstImage, MORPH_CLOSE, element);
    }
    imshow("【开运算/闭运算】", g_dstImage);
}

//-------------------------【on_ErodeDilate()函数】------------
//  描述:腐蚀膨胀的回调函数
//------------------------------------------------------------

static void on_ErodeDilate(int, void *)
{
    //偏移量
    int offset = g_nErodeDilateNum - g_nMaxIterationNum;
    int Absolute_offset = offset > 0 ? offset : -offset;    //绝对值
    Mat element = getStructuringElement(g_nElementShape, Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1), Point(Absolute_offset, Absolute_offset));
    if (offset < 0)
    {
        erode(g_srcImage, g_dstImage, element);
    }
    else
    {
        dilate(g_srcImage, g_dstImage, element);
    }
    imshow("【腐蚀/膨胀】", g_dstImage);
}

//------------------------【on_TopBlackHat()函数】--------------
//  描述:顶帽/黑帽的回调函数
//-------------------------------------------------------------
static void on_TopBlackHat(int, void *)
{
    //偏移量
    int offset = g_nTopBlackHatNum - g_nMaxIterationNum;
    int Absolute_offset = offset > 0 ? offset : -offset;    //绝对值
    Mat element = getStructuringElement(g_nElementShape, Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1), Point(Absolute_offset, Absolute_offset));
    if (offset < 0)
    {
        morphologyEx(g_srcImage, g_dstImage, MORPH_TOPHAT, element);
    }
    else
    {
        morphologyEx(g_srcImage, g_dstImage, MORPH_BLACKHAT, element);
    }
    imshow("【顶帽/黑帽】", g_dstImage);
}

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值