【opencv学习笔记】012之形态学操作(开闭操作,形态学梯度,顶帽与黑帽)

目录

一、前言

二、形态学操作

1、回顾

2、开操作

3、闭操作

4、形态学梯度

5、顶帽

6、黑帽

三、OpenCV中的形态学操作

0、核生成的API

1、形态学操作

1.API

2.代码展示

3.执行结果


一、前言

继续填坑。

如果想看其他有关于OpenCV学习方法介绍、学习教程、代码实战、常见报错及解决方案等相关内容,可以直接看我的OpenCV分类:

【OpenCV系列】:https://blog.csdn.net/shuiyixin/article/category/7581855

如果你想了解更多有关于计算机视觉、OpenCV、机器学习、深度学习等相关技术的内容,想与更多大佬一起沟通,那就扫描下方二维码加入我们吧!

二、形态学操作

1、回顾

首先我们讲了膨胀和腐蚀,并举例说明。

我们先来直观的看一下执行膨胀前后的操作:

原图与膨胀后的操作

我们发现,经过膨胀操作,黑色变得更瘦了,我们可以理解为白色膨胀了。

我们再来直观的看一下执行腐蚀前后的操作:、

通过对比,我们发现,就是黑色的区域变胖了,我们考虑一下腐蚀,比如浓硫酸的腐蚀,越腐蚀,黑色的部分就越多,所以腐蚀就是深色越来越浓,越来越多。

上节课我们讲形态学操作,讲了5个形态学操作,我们先来回顾一下:

(1)开操作:先腐蚀后膨胀,可以去掉小的对象。

(2)闭操作:先膨胀后腐蚀,可以填充小对象。

(3)形态学梯度:膨胀减去腐蚀。

(4)顶帽:顶帽是原图像与开操作图像之间的差值图像。

(5)黑帽:黑帽是闭操作图像与原图像之间的差值图像。

接下来,我们来具体讲一下。

2、开操作

通过回顾上节课的知识,我们知道,开操作即为先腐蚀后膨胀。我们以单通道的黑白图像为例讲解,也就是我们先通过腐蚀操作,将黑色区域腐蚀扩大,再通过膨胀操作,将白色区域膨胀扩大。如果我有一个小白点,先通过腐蚀操作,就会被周围的黑色覆盖掉,再进行膨胀操作,因为小白点已经没有了,进行膨胀操作,也不会影响到周围的黑色,所以,开操作,可以去掉小白点。也就是合适的开操作,可以去掉小的对象。

原图

对于上面的原图,我们进行开操作,得到的图如下:

开操作

我们发现,图中的小白区域被去掉了。

3、闭操作

我们知道,闭操作即为先膨胀后腐蚀。我们以单通道的黑白图像为例讲解,也就是我们先通过膨胀操作,将白色区域膨胀扩大,再通过腐蚀操作,将黑色区域腐蚀扩大。如果我有一个小黑点,先通过膨胀操作,就会被周围的白色覆盖掉,再进行腐蚀操作,因为小黑点已经没有了,进行腐蚀操作,也不会影响到周围的白色,所以,闭操作,可以去掉小黑点。也就是合适的闭操作,可以填充小对象。

原图

对于上面的原图,我们进行闭操作,得到的图如下:

闭操作

我们发现,图中的小黑色区域被白色填充了。

 

4、形态学梯度

我们知道,形态学梯度即为膨胀减去腐蚀。我们以一个二维数组为例来讲解。对于下面左边的图像,进行膨胀之后的操作结果如下:

膨胀

而进行腐蚀操作如下:

腐蚀

形态学梯度就是膨胀减去腐蚀,如下:

在后面的实战中,我们会直观的看一下,如果我们采用形态学梯度,得到的是什么效果。

5、顶帽

顶帽是原图像与开操作图像之间的差值图像。开操作我们去掉了白色的小对象,其他地方没有变化,进行差值之后变成0,也就是变成黑色,不同的进行差值之后,我们就获得了去掉的白色的区域,然后我们就要考虑这个区域的颜色是什么颜色,因为原图是白色,对应的值是255,进行开操作之后变为黑色,对应的值是0,进行差值之后还是255,也就是还是白色,即原来的颜色。所以顶帽操作,求到的就是去掉的白色的小对象。

如下图:

原图

进行顶帽操作之后,得到的是:

顶帽

 

6、黑帽

黑帽是原图像与闭操作图像之间的差值图像。闭操作我们填充了黑色的小对象,其他地方没有变化,进行差值之后变成黑色,其他地方进行差值之后,我们就获得了填充的黑色的区域,然后我们就要考虑这个区域的颜色是什么颜色,因为原图是黑色,对应的值是0,进行闭操作之后变为白色,对应的值是255,进行差值之后是255,也就是变成白色。所以顶帽操作,求到的就是去掉的白色的小对象。

原图

进行黑帽之后,得到的图像如下:

标题

我们可以得到如下结论:

不管是顶帽还是黑帽,我们得到的都是原图像与开/闭操作的差值图像,差值地方是白色,其他地方是黑色

三、OpenCV中的形态学操作

所有的这些操作,用到的是同一个API,同时,我们也需要用到一个核生成API,上节课,我们已经讲过,这节课我们再回顾一下:

0、核生成的API

在形态学中,因为要涉及到区域像素操作,我们就要设计一个核,在核范围内对像素进行操作。所以我们需要创建一个核,在这里,我们用到一个新的API:getStructuringElement()

我们来看一下API:

Mat getStructuringElement(
    int shape, 
    Size ksize, 
    Point anchor = Point(-1,-1)
    );

其函数参数如下:

(1)int类型的shape,元素形状,可以是cv::MorphShapes之一。

(2)Size类型的ksize,结构化元素的大小。

(3)Point类型的anchor,默认值(-1,-1),表示锚定位于中心。请注意,只有十字形元素的形状取决于锚定位置。在其他情况下,锚只是调节形态学操作结果的移动量。

这里主要说一下第一个参数,该参数主要有如下几种选择:

(1)MORPH_RECT:矩形结构区域。

(2)MORPH_CROSS,十字形结构区域。

(3)MORPH_ELLIPSE,椭圆结构区域,内接于矩形Rect(0,0,esize.width,0.esize.height)的填充椭圆。

1、形态学操作

前面我们已经讲完了基本原理,也讲了对应的实现效果。现在我们来讲一下API。

1.API

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()
);

函数参数含义如下:

(1)InputArray类型的src,输入图像。通道数可以任意,但深度应为CV_8U、CV_16U、CV_16S、CV_32F或CV_64F之一。

(2)OutputArray类型的dst,即目标图像,与输入图像有相同的尺寸和类型。

(3)int类型的op,形态学操作的类型,请参见cv::MorphTypes

(4)InputArray类型的kernel,用于膨胀的结构元素;如果elemenat=Mat(),则使用3 x 3矩形结构元素。可以使用getStructuringElement创建内核。

(5)Point类型的anchor:锚定在元素中的位置;默认值(-1,-1)表示锚定在元素中心。

(6)int类型的iterations:应用膨胀的次数。

(7)int类型的borderType:像素外推方法,参见cv::BorderTypes。

(8)Scalar类型的borderValue:恒定边框时的边框值。

相比较膨胀和腐蚀,只是增加了第三个参数,其他参数是完全一致的,第三个参数是操作,即所有的形态学操作。主要有:

enum MorphTypes{
    MORPH_ERODE    = 0,  //腐蚀
    MORPH_DILATE   = 1,  //膨胀
    MORPH_OPEN     = 2,  //开操作
    MORPH_CLOSE    = 3,  //闭操作
    MORPH_GRADIENT = 4,  //梯度操作
    MORPH_TOPHAT   = 5,  //顶帽操作
    MORPH_BLACKHAT = 6,  //黑帽操作
};

前两个是我们之前讲过的膨胀和腐蚀,剩下的就是我们今天讲的五个形态学操作。

而我们的API,一般来说,我们只需要设置前四个参数,后面的参数默认即可。

2.代码展示

#include<opencv2\opencv.hpp>
#include<iostream>

using namespace std;
using namespace cv;

int main()
{
	Mat src, dst;
	src = imread("E:/image/girl2.png");
	if (!src.data)
	{
		cout << "could not load image !";
		return -1;
	}

	imshow("src", src);

	Mat kernel = getStructuringElement(MORPH_RECT, Size(7, 7), Point(-1, -1));

	morphologyEx(src, dst, CV_MOP_OPEN,kernel);
	imshow("open-src", dst);

	morphologyEx(src, dst, CV_MOP_CLOSE, kernel);
	imshow("close-src", dst);

	morphologyEx(src, dst, CV_MOP_GRADIENT, kernel);
	imshow("gradient-src", dst);

	morphologyEx(src, dst, CV_MOP_TOPHAT, kernel);
	imshow("tophat-src", dst);

	morphologyEx(src, dst, CV_MOP_BLACKHAT, kernel);
	imshow("blackhat-src", dst);

	waitKey(0);
	return 0;
}

3.执行结果

原图
开操作
闭操作
形态学梯度
顶帽
黑帽

 

好啦今天的内容就讲到这里啦,希望大家能够多多练习,才能真正学懂啊!

发布了250 篇原创文章 · 获赞 504 · 访问量 51万+

猜你喜欢

转载自blog.csdn.net/shuiyixin/article/details/104369163