opencv(15)---图像膨胀腐蚀

基本概念

概述

  • 膨胀、腐蚀属于形态学的操作, 简单来说就是基于形状的一系列图像处理操作

  • 膨胀腐蚀是基于高亮部分(白色)操作的, 膨胀是対高亮部分进行膨胀, 类似“领域扩张”, 腐蚀是高亮部分被腐蚀, 类似“领域被蚕食”

  • 膨胀腐蚀的应用和功能:
    消除噪声
    分割独立元素或连接相邻元素
    寻找图像中的明显极大值、极小值区域
    求图像的梯度

  • 其他相关:
    开运算、闭运算
    顶帽、黑帽
    形态学梯度

代码

#include "mainwindow.h"
#include<opencv2/opencv.hpp>
#include<iostream>
#include <opencv2/imgproc/imgproc.hpp>

using namespace std;
using namespace cv;
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    Mat srcImg=imread("1.bmp");
    Mat dstImg;
    Mat element=getStructuringElement(MORPH_RECT,Size(5,5),Point(-1,-1));


    /*膨胀*/
    //dilate(srcImg,dstImg,element,Point(-1,-1),3);


    /*腐蚀*/
    //erode(srcImg,dstImg,element,Point(-1,-1),3);

    /*开运算*/
    //morphologyEx(srcImg,dstImg,MORPH_OPEN,element);

    /*闭运算---先膨胀再腐蚀*/
    morphologyEx(srcImg,dstImg,MORPH_CLOSR,element);

    /*形态学梯度*/
    morphologyEx(srcImg,dstImg,MORPH_GRADIENT,element);

    /*顶帽运算*/
    morphologyEx(srcImg,dstImg,MORPH_TOPHAT,element);

    /*黑帽运算*/
    morphologyEx(srcImg,dstImg,MORPH_BLACKHAT,element);


    imshow("srcImg",srcImg);
    imshow("dstImg",dstImg);

}

MainWindow::~MainWindow()
{

}

膨胀—dilate()

膨胀就是求局部最大值的操作, 从数学角度上来讲, 膨胀或腐蚀就是将图像(或区域)A与核B进行卷积。
核可以是任意大小和形状, 它有一个独立定义的参考点(锚点), 多数情况下, 核是一个小的中间带参考点和实心正方形或者圆盘, 可以看做是一个模板或掩码。
膨胀是求局部最大值的操做, 核B与图形卷积, 即核B覆盖的区域的像素点的最大值, 并把这个最大值复制给参考点指定的像素, 这样就会使图像中的高亮区域逐渐增长, 如下图所示:

函数原型

1. dilate


CV_EXPORTS_W void 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: 输出图像要求和src一样的尺寸和类型
  • kernel: 膨胀操作的核, 当为NULL时, 表示使用参考点位于中心的3x3的核
    一般使用getStructuringElement获得指定形状和尺寸的结构元素(核)
  • anchor: 锚的位置, 默认值Point(-1,-1), 表示位于中心
  • interations: 膨胀的次数
  • borderType: 边界模式, 一般采用默认值
  • borderValue: 边界值, 一般采用默认值
    2. getStructuringElement
  • 可选以下三种形状: 矩形、交叉形、椭圆形
  • ksize和anchor分别表示内核尺寸和锚点位置

    矩形

    交叉性

腐蚀—erode()

腐蚀和膨胀相反, 是取局部最小值, 高亮区域逐渐减小, 如下图所示:
这里写图片描述

函数原型

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

形态学其他操作—morphologyEx()

开运算、闭运算、顶帽、黒帽、形态学梯度
基于膨胀腐蚀基础, 利用morphologyEx()函数进行操作

函数原型

1.

CV_EXPORTS_W 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() );
  • src: 输入原图像
  • dst: 输出图像要求和src一样的尺寸和类型
  • op: 表示形态学运算的类型
  • kernel: 形态学运算内核, 若为NULL, 表示使用参考点位于中心的3x3内核, 一般使用 getStruecuringElement函数获得
  • anchor: 锚的位置, 默认值Point(-1,-1), 表示位于中心
  • interations: 迭代使用函数的次数, 默认为1
  • borderType: 边界模式, 一般采用默认值
  • borderValue: 边界值, 一般采用默认值

  • 2. OP取值类型

开运算(open)

概念

开运算是先腐蚀后膨胀的过程,
1)开运算可以用来消除小物体,
2)在纤细点处分离物体,
3)在平滑较大物体边界的同时不明显的改变其面积。

代码

morphologyEx(srcImg,dstImg,MORPH_OPEN,element);

运行结果
这里写图片描述

闭运算(close)

概念

闭运算是先膨胀后腐蚀的过程, 闭运算可以用来消除小型黑洞(黑色区域)

代码

morphologyEx(srcImg,dstImg,MORPH_CLOSR,element);

运行结果

这里写图片描述

形态学梯度(Gradient)

概念

形态学梯度是膨胀图与腐蚀图之差, 对二值图可以将团块(blob)边缘凸显出来来保留边缘轮廓

代码

morphologyEx(srcImg,dstImg,MORPH_GRADIENT,element);

运行结果

这里写图片描述

顶帽(Top Hat)

概念

顶帽运算也被称为”礼帽”, 是闭运算结果和原图像做差的结果, 可以用来分离比邻近点亮一些的斑块

代码

morphologyEx(srcImg,dstImg,MORPH_TOPHAT,element);

运行结果
这里写图片描述

黒帽(Black Hat)

概念

黑帽运算是原图像和开运算做差的结果, 可以用来分离比邻近点暗一些的斑块。

代码

 morphologyEx(srcImg,dstImg,MORPH_BLACKHAT,element);

运行结果

这里写图片描述

膨胀腐蚀小应用

膨胀腐蚀走迷宫

代码

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/core/core.hpp"

#include<iostream>
using namespace std;
using namespace cv;

const char* imgName;  //图片路径名称
int thres_min;  //二值化最小阈值

int main(int argc, char** argv)
{
    if(argc>2)
    {
        imgName=argv[1];
        thres_min=atoi(argv[2]);  //const char*转为int类型
    }
    else
    {
        cout<<"argv must more than 2 !\n"<<endl;
        return 0;
    }

    Mat img = imread(imgName, 1);
    if(!img.empty())     
    {
        threshold(img, img, thres_min, 255, THRESH_BINARY);
        imshow("img", img);
        Mat Copy;
        img.copyTo(Copy);

        cvtColor(Copy, Copy, CV_BGR2GRAY);
        threshold(Copy, Copy, thres_min, 255, THRESH_BINARY_INV);
        imshow("copy", Copy);

        vector<vector<Point>>contours;
        findContours(Copy, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
        if(contours.size()!=2)
        {
            cout<<"There are more than 2 walls"<<endl;
            return 0;
        }
        Mat draw;
        draw = Mat::zeros(img.size(), CV_32FC1);
        cout<<contours.size();
        drawContours(draw, contours, 0, Scalar(255), -2);
        imshow("img2", draw);

        Mat dilated, eroded;
        Mat kernel=Mat::ones(21, 21, CV_8UC1);

        dilate(draw, dilated, kernel, Point(-1,-1), 2, BORDER_CONSTANT);
        imshow("dilate", dilated);

        erode(dilated, eroded,  kernel, Point(-1,-1), 2, BORDER_CONSTANT);
        imshow("erode", eroded);

        Mat diff;
        absdiff(dilated, eroded, diff);
        diff.convertTo(diff, CV_8UC1);
        imshow("diff", diff);

        vector<vector<Point>>contours2;
        findContours(diff, contours2, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
        Mat draw2;
        draw2=Mat::zeros(img.size(), CV_32FC2);
        drawContours(img, contours2, 0, Scalar(0,255,0), -1);
        imshow("result", img);


    }
    else 
    {
        cout<<"Read image error,please try again!\n"<<endl;
        return 0;
    }


    waitKey(0);
    destroyAllWindows();

}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值