OpenCV(python)一键入门--十九篇(图像形态学函数使用)

举报
拓佑豪 发表于 2021/08/17 12:00:50 2021/08/17
【摘要】 介绍图像形态学的基本运用

1:图像膨胀与腐蚀

import cv2 as cv
import numpy as np

#膨胀和腐蚀
src = cv.imread("D:/coin.jpg")
cv.imshow("input", src)

# 使用3x3 np.ones的结构元素进行膨胀与腐蚀操作
se = np.ones((3, 3), dtype=np.uint8)
dilate = cv.dilate(src, se, None, (-1, -1), 1)
erode = cv.erode(src, se, None, (-1, -1), 1)

cv.imshow("dilate", dilate)
cv.imshow("erode", erode)
cv.waitKey(0)
cv.destroyAllWindows()

1):cv.dilate 膨胀

函数原型:dst=cv.dilate(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])  

image 输入图像;通道数任意,但深度应为CV_8U、CV_16U、CV_16S、CV_32F或CV_64F其中之一。
dst 输出与 src 大小和类型相同的图像。
kernel 用于膨胀的结构元素
anchor 元素内锚点的位置;默认值 (-1, -1) 表示锚点位于元素中心。
iterations 应用扩张的次数。
borderType 像素外插方法
borderValue 边界不变的情况下的边界值

其中,像素外插方法,在官网有如下介绍,在这里不再赘述:

膨胀效果:

2):cv.erode 腐蚀

函数原型:dst=cv.erode(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])

和膨胀的函数解释类似

src 输入图像;通道数可以任意,但深度应为CV_8U、CV_16U、CV_16S、CV_32F或CV_64F之一。
dst 输出与 src 大小和类型相同的图像。
kernel 用于侵蚀的结构元素
anchor 元素内锚点的位置;默认值 (-1, -1) 表示锚点位于元素中心。
iterations 应用侵蚀的次数。
borderType 像素外插方法,具体请参见上图
borderValue 边界不变的情况下的边界值


效果如下:

3):结构元素

第一个demo,我们使用了np.ones直接生成一个3*3,全为1的“结构元素”。其实应对不同的应用场景,选择一个好的结构元素很重要。

import cv2 as cv
import numpy as np

#二值化图像
src = cv.imread("D:/coin.jpg")
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
cv.imshow("input", binary)

# 使用3x3 “矩形”结构元素
se = cv.getStructuringElement(cv.MORPH_RECT, (3, 3), (-1, -1))
dilate = cv.dilate(binary, se, None, (-1, -1), 1)
erode = cv.erode(binary, se, None, (-1, -1), 1)

cv.imshow("dilate", dilate)
cv.imshow("erode", erode)
cv.waitKey(0)
cv.destroyAllWindows()

对于cv.getStructuringElement,函数原型如下:

函数原型:retval=cv.getStructuringElement(shape, ksize[, anchor])

shape 结构元素形状类型,常见的有矩形,圆形,十字交叉。
ksize 结构元素的大小。
anchor 元素内的锚点位置。默认值( − 1 , − 1 )表示锚在中心。
只有十字形元素的形状取决于锚点位置。其他情况下,anchor 只调节形态操作的结果移动了多少。

通常其参数需要视情况调整

常见的结构元素介绍如下:

矩形结构元素: cv.MORPH_RECT
十字形结构元素:cv.MORPH_CROSS
椭圆结构元素:  cv.MORPH_ELLIPSE 内接矩形为 Rect(0, 0, esize.width, 0.esize.height) 的实心椭圆

效果如下:

2:cv.morphologyEx 形态学操作

(在这篇博客中,二值图像分析的案例使用了morphologyEx该函数:OpenCV(python)一键入门--十四篇(二值图像分析入门)

函数原型:dst=cv.morphologyEx(src, op, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])

src 源图像。通道的数量可以是任意的。深度应为 CV_8U、CV_16U、CV_16S、CV_32F 或 CV_64F 之一。
dst 与源图像大小和类型相同的目标图像。
op 形态学操作的类型
kernel 结构元素。可以用getStructuringElement创建结构元素。
anchor 用内核锚定位置。负值意味着锚点位于内核中心。
iterations 应用腐蚀和膨胀的次数。
borderType 像素外插方法,具体请参照上图
borderValue 边界不变的情况下的边界值。默认值具有特殊含义。

形态学操作类型:

MORPH_ERODE 腐蚀 当调用morphologyEx使用MORPH_ERODE类型时,与调用腐蚀函数erode效果相同
MORPH_DILATE 膨胀 当调用morphologyEx使用MORPH_DILATE类型时,与调用膨胀函数dilate效果相同
MORPH_OPEN 开运算 对图像先进行腐蚀再膨胀,等同于dilate(erode(src,kernal)),开运算对图像的边界进行平滑、去掉凸起等
MORPH_CLOSE 闭运算 对图像先进行膨胀在腐蚀,等同于erode(dilate(src,kernal)),闭运算用于填充图像内部的小空洞、填充图像的凹陷等
MORPH_GRADIENT 梯度图 用膨胀图减腐蚀图,等同于dilate(src,kernal)−erode(src,kernal),可以用于获得图像中物体的轮廓
MORPH_TOPHAT 顶帽,又称礼帽 用原图像减去开运算后的图像,等同于src−open(src,kernal),可以用于获得原图像中比周围亮的区域
MORPH_BLACKHAT 黑帽 闭运算图像减去原图像,等同于close(src,kernal)−src,可以用于获取原图像中比周围暗的区域
MORPH_HITMISS 击中击不中变换 用于匹配处理图像中是否存在核对应的图像,匹配时,需要确保核矩阵非0部分和为0部分都能匹配,注意该变换只能处理灰度图像。

2.1)开操作、闭操作:

import cv2 as cv
import numpy as np

src = cv.imread("D:/morph01.png")
cv.imshow("input", src)

# 高斯模糊去噪
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
dst = cv.GaussianBlur(gray, (9, 9), 2, 2)
binary = cv.adaptiveThreshold(dst, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY_INV, 45, 15)

# 开操作
se = cv.getStructuringElement(cv.MORPH_RECT, (5, 5), (-1, -1))
binary = cv.morphologyEx(binary, cv.MORPH_OPEN, se)

#闭操作
#se = cv.getStructuringElement(cv.MORPH_RECT, (5, 5), (-1, -1))
#binary = cv.morphologyEx(binary, cv.MORPH_CLOSE, se)

cv.imshow("binary", binary)

cv.waitKey(0)
cv.destroyAllWindows()

(自适应阈值adaptiveThreshold的介绍在这篇博客中: OpenCV(python)一键入门--十三篇(二值化去噪与图像连通域)

效果如下:

(开操作)

(闭操作)

附素材:

morph01.png

2.2)顶帽

对图像进行开运算,得到的是除去白色噪声的图像,再用原图减去开运算后的图像,得到的是图像的白色噪声。

import cv2 as cv
import numpy as np

src = cv.imread("D:/cells.jpg")
cv.imshow("input", src)

# 高斯模糊去噪
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)

# 顶帽操作
se = cv.getStructuringElement(cv.MORPH_RECT, (3, 3), (-1, -1))
binary = cv.morphologyEx(binary, cv.MORPH_TOPHAT, se)

cv.imshow("binary", binary)

cv.waitKey(0)
cv.destroyAllWindows()

效果如下:

附素材:

cells.jpg

2.3)黑帽

对图像进行闭运算,得到的是除去黑色噪声的图像,再用原图减去闭运算后的图像,得到的是图像的黑色噪声。

import cv2 as cv
import numpy as np

src = cv.imread("D:/morph01.png")
cv.imshow("input", src)

# 图像二值化
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)

# 黑帽操作
se = cv.getStructuringElement(cv.MORPH_RECT, (9, 9), (-1, -1))
binary = cv.morphologyEx(binary, cv.MORPH_BLACKHAT, se)

cv.imshow("black hat", binary)

cv.waitKey(0)
cv.destroyAllWindows()

效果如下:

2.4)图像梯度

import cv2 as cv

src = cv.imread("ma.jpg")
cv.imshow("input", src)

# 形态学梯度 - 基本梯度
se = cv.getStructuringElement(cv.MORPH_RECT, (3, 3), (-1, -1))
basic = cv.morphologyEx(src, cv.MORPH_GRADIENT, se)
cv.imshow("basic gradient", basic)

# 外梯度
dilate = cv.morphologyEx(src, cv.MORPH_DILATE, se)
exteral = cv.subtract(dilate, src)
cv.imshow("external gradient", exteral)

# 内梯度
erode = cv.morphologyEx(src, cv.MORPH_ERODE, se)
interal = cv.subtract(src, erode)
cv.imshow("interal gradient", interal)

cv.waitKey(0)
cv.destroyAllWindows()

· 基本梯度

基本梯度是用 膨胀后的图像 减去 腐蚀后的图像 得到差值图像,称为梯度图像

· 内部梯度

是用 原图像 减去 腐蚀之后的图像 得到差值图像,称为图像的内部梯度

· 外部梯度

膨胀后的图像  减去 原来的图像 得到的差值图像,称为图像的外部梯度。

效果如图:

2.*)击中击不中

import cv2 as cv
import numpy as np

src = cv.imread("D:/cross.png")
cv.imshow("input", src)

# 图像二值化
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU)

# 击中击不中
se = cv.getStructuringElement(cv.MORPH_CROSS, (11, 11), (-1, -1))
binary = cv.morphologyEx(binary, cv.MORPH_HITMISS, se)

cv.imshow("demo", binary)

cv.waitKey(0)
cv.destroyAllWindows()

效果如下:

附素材

cross.png

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

举报
请填写举报理由
0/200