欢迎来到军工软件开发人才培养基地——学到牛牛

形态学操作

时间:2024-05-06 07:01:10 来源:学到牛牛

形态学,即数学形态学,是图像处理过程中一个非常重要的研究方向。形态学主要从图像内提取分量信息,该分量信息通常对于表达形态学操作主要包含:腐蚀、膨胀、开运算、闭运算、形态学梯度运算、礼帽运算、黑帽运算等。

1、腐蚀操作

腐蚀能够消除图像的边界点,使得图像沿着边界向内收敛,也可以将小于指定结构元素的部分去除。借此可以实现去除噪声、元素分割等功能。

在OpenCV中,使用函数cv2.erode()实现腐蚀操作,其语法格式为:

dst = cv2.erode(src, kernel, iterations)

参数说明:

dst是腐蚀后所输出的目标图像,该图像和原始图像具有同样的类型和大小。

scr是需要进行腐蚀的原始图像,图像的通道数可以是任意的。

kernel卷积核,代表腐蚀操作时所采用的结构类型(即腐蚀笔形)。

iterations是腐蚀操作迭代的次数,该值默认为1,即只进行一次腐蚀操作。

 

腐蚀综合案例如下。

# 形态学——腐蚀操作

import cv2

import numpy

 

zs_img = cv2.imread("E:/tmp/img/name.png")

ls_img = cv2.imread("E:/tmp/img/LiSi.png")

# 将图片按比例缩小

zs_img2 = cv2.resize(zs_img, (0, 0), fx=0.5, fy=0.5)

ls_img2 = cv2.resize(ls_img, (0, 0), fx=0.5, fy=0.5)

 

# 显现原始图像

cv2.imshow("ZS Aboriginal", zs_img2)

cv2.imshow("LS Aboriginal", ls_img2)

 

# 设置核,即画笔形状,shape为画笔尺寸,dtype设置数据类型,默认为numpy.float64。

kernel = numpy.ones(shape=(3, 3), dtype=numpy.uint8)

 

# 1、对张三图片进行腐蚀

# 对指定的图像对象进行腐蚀,kernel使用的画笔,iterations腐蚀的深度

zs_erosion = cv2.erode(zs_img2, kernel=kernel, iterations=1)

# 2、对李四图片进行腐蚀

ls_erosion = cv2.erode(ls_img2, kernel=kernel, iterations=1)

 

# 显示腐蚀后的效果

cv2.imshow("zs_erosion", zs_erosion)

cv2.imshow("ls_erosion", ls_erosion)

cv2.waitKey(0)

cv2.destroyAllWindows()

 

运行结果。

图1.1 腐蚀效果

 

根据上述运行结果可知道,腐蚀是由深颜色向浅色腐蚀,即向浅色中侵吞1画笔的尺寸,如果设置iterations=n参数,表示向浅色侵吞n个画笔尺寸。

2、膨胀操作

膨胀操作和腐蚀操作的作用是完全相反的,膨胀操作能对图像的边界进行扩张。膨胀操作对于填补图像分割后图像内所存在的空白有帮助。

在OpenCV中,使用函数cv2.dilate()实现膨胀操作,其语法格式为:

dst = cv2.dilate(src, kernel, iterations)

参数说明:

dst是膨胀后所输出目标图像,该图像和原始图像具有同样的类型和大小。

src是需要进行膨胀的原始图像,图像的通道数可以是任意的。

kernel卷积核,代表膨胀操作时所采用的结构类型。

iterations是膨胀操作迭代的次数,该值默认为1,即只进行一次膨胀操作。

 

膨胀案例。

import cv2

import numpy

 

# 读取图像

zs = cv2.imread("E:/tmp/img/ZhangSan.png")

ls = cv2.imread("E:/tmp/img/LiSi.png")

 

# 缩小两张图像尺寸

zs_img = cv2.resize(zs, (0, 0), fx=0.5, fy=0.5)

ls_img = cv2.resize(ls, (0, 0), fx=0.5, fy=0.5)

 

# 设置膨胀画笔尺寸

kernel = numpy.ones((3, 3), numpy.uint8)

 

# 1、对zs图像进行膨胀

zs_dilate = cv2.dilate(src=zs_img, kernel=kernel, iterations=2)

 

# 2、对ls图像进行膨胀

ls_dilate = cv2.dilate(src=ls_img, kernel=kernel, iterations=2)

 

# 效果呈现

# 原始图像

cv2.imshow("zs_img", zs_img)

cv2.imshow("ls_img", ls_img)

 

# 膨胀后的图像

cv2.imshow("zs_dilate", zs_dilate)

cv2.imshow("ls_dilate", ls_dilate)

 

cv2.waitKey(0)

cv2.destroyAllWindows()

运行结果。

图2.1 膨胀运行结果

 

根据图2.1结果可知,膨胀是由浅色向深色腐蚀,即向深色中侵吞1个画笔的尺寸,如果设置iterations=n参数,表示向深色侵吞n个画笔尺寸。

 

腐蚀与膨胀综合案例:

实现去ZhangSan.png图像中的“飞边”,并保持文字真实大小。

import cv2

import numpy

 

# 读取图像

zs = cv2.imread("E:/tmp/img/ZhangSan.png")

# 缩小两张图像尺寸

zs_img = cv2.resize(zs, (0, 0), fx=0.5, fy=0.5)

 

# 1、设置画笔尺寸

kernel = numpy.ones((3, 3), numpy.uint8)

 

# 2、对ZhangSan.png图像进行腐蚀,去除“飞边”。

zs_erode = cv2.erode(src=zs_img, kernel=kernel, iterations=1)

 

# 3、腐蚀后有效字体会缩小,再使用膨胀将有效字体扩大

zs_dilate = cv2.dilate(src=zs_erode, kernel=kernel, iterations=1)

 

# 验证效果

cv2.imshow("zs_img", zs_img)

cv2.imshow("zs_erode", zs_erode)

cv2.imshow("zs_dilate", zs_dilate)

 

cv2.waitKey(0)

cv2.destroyAllWindows()

运行结果如图2.2。

 

国2.2 腐蚀和膨胀综合应用

 

3、通用形态学函数

腐蚀操作和膨胀操作是形态学运算的基础,将腐蚀和膨胀操作进行组合,就可以实现开运算、闭运算、形态学梯度运算、顶帽运算、黑帽运算等多种不同形式的运算。

OpenCV提供了函数cv2.morphologyEx来实现上述形态学运算,其常见语法结构如下:

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

其中:mor ph log 

dst代表经过形态学处理后所输出的目标图像,该图像和原始图像具有同样的类型和大小。

src代表需要进行形态学操作的原始图像。

op代表操作类型,如下表3.1所示。各种形态学运算的操作规则均是将腐蚀膨胀操作进行组合而得到的。

kernel卷积核,代表膨胀操作时所采用的结构类型。

iterations是膨胀操作迭代的次数,该值默认为1,即只进行一次膨胀操作。

表3.1

类型 说明 意义 操作

cv2.MORPH_ERODE 腐蚀 腐蚀 erode()

cv2.MORPH_DILATE 膨胀 膨胀 dilate()

cv2.MORPH_OPEN 开运算 先腐蚀后膨胀 dilate(erode())

cv2.MORPH_CLOSE 闭运算 先膨胀后腐蚀 erode(dilate())

cv2.MORPH_GRADIENT 形态学梯度运算 膨胀图减去腐蚀图 dilate()-erode()

cv2.MORPH_TOPHAT 顶帽运算 原始图像减开运算所得图像 src-open()

cv2.MORPH_BLACKHAT 黑帽 闭运算所得图像减原始图像 close()-src

3.1 开运算

开运算进行的操作是先对图像腐蚀,再对腐蚀后的对象进行膨胀,开运算可以用于去噪等。语法格式就是在通用形态学函数的基础上,将参数op设置为cv2.MORPH_OPEN即可。

示例代码如下所示。

# 开运算

import cv2

import numpy

 

# 读取图像

zs = cv2.imread("E:/tmp/img/ZhangSan.png")

# 缩小两张图像尺寸

zs_img = cv2.resize(zs, (0, 0), fx=0.5, fy=0.5)

 

# 1、设置画笔尺寸

kernel = numpy.ones((3, 3), numpy.uint8)

 

# 2、开运算

open = cv2.morphologyEx(src=zs_img, op=cv2.MORPH_OPEN, kernel=kernel)

 

# 显示结果

cv2.imshow("zs_img", zs_img)    # 原始图

cv2.imshow("open", open)        # 开运算

 

cv2.waitKey(0)

cv2.destroyAllWindows()

 

运行结果。

图3.1 开运算运行结果

3.2 闭运算

闭运算是先进行膨胀操作,然后再对膨胀后的图像进行腐蚀操作。闭运算有利于关闭前景物体内部的小孔,或去除物体上的小黑包,还可以将不同的前景图像进行连接。

闭运算示例代码如下所示。

# 闭运算

import cv2

import numpy

 

# 读取图像

zs = cv2.imread("E:/tmp/img/LiSi.png")

# 缩小两张图像尺寸

zs_img = cv2.resize(zs, (0, 0), fx=0.5, fy=0.5)

 

# 1、设置画笔尺寸

kernel = numpy.ones((3, 3), numpy.uint8)

 

# 2、闭运算

close = cv2.morphologyEx(src=zs_img, op=cv2.MORPH_CLOSE, kernel=kernel, iterations=2)

 

# 显示结果

cv2.imshow("zs_img", zs_img)    # 原始图

cv2.imshow("close", close)      # 闭运算

 

cv2.waitKey(0)

cv2.destroyAllWindows()

闭运算运行结果。

图3.2 闭运算运行结果

 

3.3 梯度运算

形态学梯度运算是用图像的膨胀图像减去腐蚀图像的操作,该操作可以获取原始图像中前景图像的边缘。

梯度运算示例代码。

import cv2

import numpy

 

# 读取图像

zs = cv2.imread("E:/tmp/img/ZhangSan.png")

# 缩小两张图像尺寸

zs_img = cv2.resize(zs, (0, 0), fx=0.5, fy=0.5)

 

# 1、设置画笔尺寸

kernel = numpy.ones((3, 3), numpy.uint8)

 

# 2、梯度运算

gradient = cv2.morphologyEx(src=zs_img, op=cv2.MORPH_GRADIENT, kernel=kernel)

 

# 显示结果

cv2.imshow("zs_img", zs_img)    # 原始图

cv2.imshow("gradient", gradient)      # 梯度运算

 

cv2.waitKey(0)

cv2.destroyAllWindows()

梯度运算运行结果。

图3.3 梯度运算

 

3.4 礼帽运算(顶帽运算)和黑帽运算

礼帽运算是用原始图像减去该图像开运算后的图像。礼帽运算能够获取图像的噪声信息,还可以得到比原始图像的边缘更亮的边缘信息。

黑帽运算是用闭运算后的图像减去原始图像。黑帽运算能够获取图像内部的小孔,或前景中的小黑点,或者得到比原始图像的边缘更暗的边缘部分。

顶帽黑帽综合案例。

import cv2

import numpy

 

# 读取图像

zs = cv2.imread("E:/tmp/img/ZhangSan.png")

# 缩小两张图像尺寸

zs_img = cv2.resize(zs, (0, 0), fx=0.5, fy=0.5)

 

# 1、设置画笔尺寸

kernel = numpy.ones((3, 3), numpy.uint8)

 

# 2.1 顶帽运算

top_hat = cv2.morphologyEx(src=zs_img, op=cv2.MORPH_TOPHAT, kernel=kernel)

# 2.2 黑帽运算

black_hat = cv2.morphologyEx(src=zs_img, op=cv2.MORPH_BLACKHAT, kernel=kernel)

 

# 显示结果

cv2.imshow("zs_img", zs_img)        # 原始图

cv2.imshow("top_hat", top_hat)      # 顶帽运算

cv2.imshow("black_hat", black_hat)  # 黑帽运算

 

cv2.waitKey(0)

cv2.destroyAllWindows()

运行结果。

图3.4 顶帽和黑帽运行结果