1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > OpenCV与图像处理学习六——图像形态学操作:腐蚀 膨胀 开 闭运算 形态学梯度 顶帽和黑帽

OpenCV与图像处理学习六——图像形态学操作:腐蚀 膨胀 开 闭运算 形态学梯度 顶帽和黑帽

时间:2019-10-17 04:24:50

相关推荐

OpenCV与图像处理学习六——图像形态学操作:腐蚀 膨胀 开 闭运算 形态学梯度 顶帽和黑帽

OpenCV与图像处理学习六——图像形态学操作:腐蚀、膨胀、开、闭运算、形态学梯度、顶帽和黑帽

四、图像形态学操作4.1 腐蚀和膨胀4.1.1 图像腐蚀4.1.2 图像膨胀4.2 开运算与闭运算4.2.1 开运算4.2.2 闭运算4.3 形态学梯度(Gradient)4.4顶帽和黑帽

有关图像处理前三次的笔记:

OpenCV与图像处理学习三——图像基本操作(1)

OpenCV与图像处理学习四——图像基本操作(2)

OpenCV与图像处理学习五——图像基本操作(3)

这是有关图像基本操作的最后一次笔记,有关图像形态学操作。

四、图像形态学操作

形态学,是图像处理中应用最为广泛的技术之一,主要用于从图像中提取对表达和描绘区域形状有意义的图像分量,使后续的识别工作能够抓住目标对象最为本质的形状特征,如边界和连通区域等。

下面会经常用到一个概念,这里先进行说明:

结构元素:设有两幅图像B,X,若X是被处理的对象,而B是用来处理X的,则B称为结构元素(structure element),又被形象地称作刷子。结构元素通常都是一些比较小的图像。

下面将介绍形态学的几种常用操作:腐蚀、膨胀、开运算和闭运算等。

4.1 腐蚀和膨胀

图像的膨胀(Dilation)和腐蚀(Erosion)是两种基本的形态学运算,其中膨胀类似于“领域扩张”,将图像中的白色部分进行扩张,其运行结果图比原图的白色区域更大;而腐蚀类似于“领域被蚕食”,将图像中白色的部分进行缩减细化,其运行结果图比原图的白色区域更小。

4.1.1 图像腐蚀

把结构元素B平移a后得到Ba,若Ba包含于X,我们记下这个a点,所有满足上述条件的a点组成的集合称作X被B腐蚀(Erosion)的结果。如下图所示:

其中X是被处理的对象,B是结构元素。对于任意一个在阴影部分的点a,Ba包含于X,所以X被B腐蚀的结果就是那个阴影部分。阴影部分在X的范围之内,且比X小,就像X被剥掉了一层似的。

腐蚀后的结果如下图黑色部分所示:

相较于原来的灰色部分,仿佛变瘦了。

OpenCV中的函数为:

dst= cv2.erode( src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]] )

参数为:

src:输入图像,可以是灰度图或彩色图。kernel:腐蚀操作的结构元素,默认为一个3×3的简单矩阵。anchor:锚点,默认为结构元素的中心。iterations:腐蚀次数,默认为1。

下面看个例子:

import cv2import numpy as npimport matplotlib.pyplot as pltimg = cv2.imread('./image/morphology.png')img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)kernel = np.ones((3, 3), np.uint8)erosion = cv2.erode(img, kernel, iterations = 1)plt.subplot(121), plt.imshow(img), plt.title('Original')plt.xticks([]), plt.yticks([])plt.subplot(122), plt.imshow(erosion), plt.title('erosion')plt.xticks([]), plt.yticks([])plt.show()

结果如下所示:

若将结构元素的尺寸扩大到7,结果为:

ps:在构造结构元素的时候,可以使用numpy,也可以使用OpenCV提供的函数cv2.getStructuringElement()

函数:

retval = cv2.getStructuringElement( shape, ksize[, anchor] )

参数:

shape:结构元素内部的结构,有三种,分别是矩形、十字形和椭圆形:ksize:结构元素的尺寸。anchor:锚点位置,默认为中心位置。

看一下例子:

import numpy as npimport cv2kernel = np.ones((5, 5), np.uint8)print(kernel)

[[1 1 1 1 1][1 1 1 1 1][1 1 1 1 1][1 1 1 1 1][1 1 1 1 1]]

kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (7,7))print(kernel)

[[0 0 0 1 0 0 0][0 0 0 1 0 0 0][0 0 0 1 0 0 0][1 1 1 1 1 1 1][0 0 0 1 0 0 0][0 0 0 1 0 0 0][0 0 0 1 0 0 0]]

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (7,7))print(kernel)

[[0 0 0 1 0 0 0][0 1 1 1 1 1 0][1 1 1 1 1 1 1][1 1 1 1 1 1 1][1 1 1 1 1 1 1][0 1 1 1 1 1 0][0 0 0 1 0 0 0]]

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7,7))print(kernel)

[[1 1 1 1 1 1 1][1 1 1 1 1 1 1][1 1 1 1 1 1 1][1 1 1 1 1 1 1][1 1 1 1 1 1 1][1 1 1 1 1 1 1][1 1 1 1 1 1 1]]

我们可以用非矩形的结构元素来进行腐蚀操作:

#!/usr/bin/env python3import cv2image = cv2.imread("./image/morphology.png")gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)cv2.imshow("Gray Image", gray)kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (7, 7))eroded = cv2.erode(gray.copy(), kernel, 10)# eroded = cv2.erode(gray.copy(), None, 10)cv2.imshow("Eroded Image", eroded)cv2.waitKey(0)cv2.destroyAllWindows()

也是可以达到一定效果的,但是比矩形的那种腐蚀程度低一些些,因为毕竟结构元素里多了一些0。

4.1.2 图像膨胀

膨胀(dilation)可以看做是腐蚀的对偶运算,其定义是:把结构元素B平移后得到Ba,若Ba与X有交集,我们记下这个a点。所有满足上述条件的a点组成的集合称作X被B膨胀后的结果,如下图所示:

其中X是被处理的对象,B是结构元素,对于任意一个在阴影部分的点a,Ba与X有交集,所以X被B膨胀后的结果就是那个阴影部分,阴影部分包括X所有范围,就像是X膨胀了一圈似的。

膨胀后的图像,其中绿色是膨胀多出来的部分:

在OpenCV中的函数为:

dst= cv2.dilate( src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]] )

参数:

src:输入图像,可以是灰度图也可以是彩色图。kernel:膨胀运算的结构元素,默认为一个3×3的简单矩阵。anchor:同上。iterations:同上。

看个例子:

import cv2import numpy as npimport matplotlib.pyplot as pltimg = cv2.imread('./image/morphology.png')img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)#kernel = np.ones((3,),np.uint8)kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7,7))dilation = cv2.dilate(img,kernel,iterations = 1)plt.subplot(121),plt.imshow(img),plt.title('origin')plt.xticks([]), plt.yticks([])plt.subplot(122),plt.imshow(dilation),plt.title('dilation')plt.xticks([]), plt.yticks([])plt.show()

结果为:

若将运算元素尺寸扩大一点,扩大为11:

原本断开的地方或小孔都被填上了。

4.2 开运算与闭运算

4.2.1 开运算

开运算 = 先腐蚀运算,再膨胀运算,看上去把细微连在一起的两块目标分开了,开运算的效果图如下所示:

开运算对一些细微的小点,小块,细条等部分是可以消去的,因为先腐蚀消去它们,导致它们消失了无法再通过膨胀变回来,而一些比较大的块通过腐蚀操作只是会变瘦一点,不会被完全抹去,所以可以通过膨胀运算变回来,那么总的效果就是开运算去除了这些孤立的小点,细长的小条。

开运算总结:

开运算能够去除孤立的小点,毛刺和小条,而总的位置和形状不变。开运算是一个基于几何运算的滤波器。结构元素大小的不同将导致滤波效果的不同。不同的结构元素的选择导致了不同的分割,即提取出不同的特征。

开运算和闭运算都用如下函数来表示,这个函数是OpenCV中图像形态学变化的通用函数:

dst= cv2.morphologyEx( src, op, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]] )

参数如下所示:

src:输入图像,灰度图或彩色图均可。op:形态学操作的类型,包括腐蚀、运算、开运算以及后面要提及的闭运算、形态学梯度、顶帽、黑帽等类型。kernel:结构元素,可以使用cv2.getStructuringElement函数来定义。anchor:锚点位置,一般都用中心位置。iterations:腐蚀或膨胀的次数。

下面看个例子:

import cv2import numpy as npimport matplotlib.pyplot as pltimg = cv2.imread('./image/open.png')img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)#kernel = np.ones((5,5),np.uint8)kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)plt.subplot(121), plt.imshow(img), plt.title('Original')plt.xticks([]), plt.yticks([])plt.subplot(122), plt.imshow(opening), plt.title('opening')plt.xticks([]), plt.yticks([])plt.show()

结果如下所示:

一些细小的点被去除了很多,但是开运算的结构元素的尺寸很重要,太小可能去除效果不好,太大可能会得到不想要的结果,如将3改为9,结果将变为:

所以调节这个参数还是很关键的。

4.2.2 闭运算

闭运算 = 先膨胀运算,再腐蚀运算,看上去将两个细微连接的图块封闭在一起,闭运算的效果图如下图所示:

闭运算总结:

闭运算能够填平小孔,弥合小缝隙,而总的位置和形状不变。闭运算是通过填充图像的凹角来滤波图像的。结构元素大小的不同将导致滤波效果的不同。不同结构元素的选择导致了不同的分割。

看个例子:

import cv2 as cvimport numpy as npimport matplotlib.pyplot as pltimg = cv.imread('./image/close.png')img = cv.cvtColor(img,cv.COLOR_BGR2RGB)# kernel = np.ones((5,5),np.uint8)kernel = np.ones((7, 7), np.uint8)closing = cv.morphologyEx(img, cv.MORPH_CLOSE, kernel)plt.subplot(121), plt.imshow(img), plt.title('Original')plt.xticks([]), plt.yticks([])plt.subplot(122), plt.imshow(closing), plt.title('closing')plt.xticks([]), plt.yticks([])plt.show()

结果如下所示:

一些小孔被填满了。若把尺寸从7改为21,结果为:

就有点过了,把不需要连接和填补的地方也给连接、填补了,所以要合理选择参数。

4.3 形态学梯度(Gradient)

基础梯度:基础梯度是用膨胀后的图像减去腐蚀后的图像得到的差值图像,也是OpenCV中支持的计算形态学梯度的方法,而此方法得到梯度又称为基本梯度。内部梯度:是用原图减去腐蚀之后的图像得到的差值图像。外部梯度:图形膨胀后再减去原来图像得到的差值图像。

cv2.morphologyEx函数可以实现基础梯度操作,看下面这个例子:

import cv2 as cvimport numpy as npimport matplotlib.pyplot as pltimg = cv.imread('./image/morphology.png')img = cv.cvtColor(img, cv.COLOR_BGR2RGB)kernel = np.ones((3, 3), np.uint8)gradient = cv.morphologyEx(img, cv.MORPH_GRADIENT, kernel)plt.subplot(121), plt.imshow(img), plt.title('Original')plt.xticks([]), plt.yticks([])plt.subplot(122), plt.imshow(gradient), plt.title('gradient')plt.xticks([]), plt.yticks([])plt.show()

结果如下所示:

4.4顶帽和黑帽

顶帽(Top Hat):原图像与开运算图的差值,突出原图像中比周围亮的区域黑帽(Black Hat):闭运算图与原图的差值,突出原图中比周围暗的区域

看两个例子:

顶帽:

import cv2 as cvimport numpy as npimport matplotlib.pyplot as pltimg = cv.imread('./image/morphology.png')img = cv.cvtColor(img, cv.COLOR_BGR2RGB)kernel = np.ones((9, 9), np.uint8)tophat = cv.morphologyEx(img, cv.MORPH_TOPHAT, kernel)plt.subplot(121), plt.imshow(img), plt.title('Original')plt.xticks([]), plt.yticks([])plt.subplot(122), plt.imshow(tophat), plt.title('tophat')plt.xticks([]), plt.yticks([])plt.show()

结果为:

黑帽:

import cv2 as cvimport numpy as npimport matplotlib.pyplot as pltimg = cv.imread('./image/morphology.png')img = cv.cvtColor(img, cv.COLOR_BGR2RGB)kernel = np.ones((9, 9), np.uint8)tophat = cv.morphologyEx(img, cv.MORPH_BLACKHAT, kernel)plt.subplot(121), plt.imshow(img), plt.title('Original')plt.xticks([]), plt.yticks([])plt.subplot(122), plt.imshow(tophat), plt.title('blackhat')plt.xticks([]), plt.yticks([])plt.show()

图像处理之图像基本操作的笔记就暂时到这里,后面将学习传统方法进行图像分割,包括阈值分割、边缘检测算法、连通域分析以及一些其他区域生长算法。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。