前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >OpenCV中一个最容易搞错的形态学操作

OpenCV中一个最容易搞错的形态学操作

作者头像
OpenCV学堂
发布2020-02-24 16:40:35
1.9K0
发布2020-02-24 16:40:35
举报

微信公众号:OpenCV学堂 关注获取更多计算机视觉与深度学习知识

击中击不中解释

OpenCV中除了常见腐蚀、膨胀、开闭操作之外,还有个非常有用的形态学操作,就是击中击不中。击中击不中也是基础形态学操作组合,它可以实现对象的细化跟剪枝操作。形态学操作都是基于各种形状的结构元素,基于输入图像,跟结构元素操作得到输出图像,击中击不中操作是在二值图像的模式匹配跟发现上非常有用,它是基于两个结构元素分别是B1跟B2、第一个结构元素B1在图像上完成腐蚀操作、然后第二个结构元素B2在图像完成腐蚀操作,然后合并最终输出得到。详解步骤如下:

1.使用B1完成对图像腐蚀 2.使用B2完成对图像腐蚀 3.对上述两步的输出结果进行位与操作输出最终结果

上述步骤可以把结构元素B1+B2得到一个结构元素B,可以直接完成一次操作就为击中击不中(Hit And Miss)

举例如下,假设有如下的结构元素:

上图B1、B2对图像进行腐蚀,可以合并为B1 + B2,其中中心元素-1表示该点为背景像素点,上下左右四个点值为1表示前景像素点,角上四个点为0表示任意像素值均可。这里就是Hit And Miss的结构元素定义。使用该结构元素对输入图像二值图像完成操作,得到输出图像,图示如下:

通过设计不同的结构元素会得到不同的输出图像,图示如下:

OpenCV中的Hit And Miss

OpenCV中的击中击不中的函数,是跟开闭操作一样的功能函数

代码语言:javascript
复制
void cv::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表示输出图像
  • op 这里必须是MORPH_HITMISS
  • kernel 表示结构元素
  • anchor 表示锚定位置,默认是结构元素中心位置

剩下的参数默认即可,一般情况都不用设置。

代码演示-二值对象边缘发现

使用击中击不中实现二值对象的边缘提取,如下:

左侧是原图、右侧是基于击中击不中提取到轮廓边缘。

代码实现如下:

代码语言:javascript
复制
image = cv.imread("D:/images/my_mask.png")
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
cv.imshow("input", binary)
hmk1 = np.zeros((3, 3), dtype=np.int32)
hmk1[0, 0] = 1
hmk1[1, 1] = -1
print(hmk1)
h1 = cv.morphologyEx(binary, cv.MORPH_HITMISS, hmk1)

hmk1 = np.zeros((3, 3), dtype=np.int32)
hmk1[2, 2] = 1
hmk1[1, 1] = -1
print(hmk1)
h2 = cv.morphologyEx(binary, cv.MORPH_HITMISS, hmk1)

dst = cv.add(h1, h2)
cv.imshow("output", dst)

cv.waitKey(0)
cv.destroyAllWindows()

使用的结构元素为:

另外一个运行测试

原图

运行结果

掉坑的记录

OpenCV中的结构元素通过Mat来表示,默认的数据类是CV_8UC1, 但是对Hit And Miss来说,数据类型必须是 CV_32SC 如果使用默认数据类型就会导致-1溢出错误。但是多数初学者都不会意识到这个问题,一般如下定义结构元素,然后去执行Hit And Miss操作:

代码语言:javascript
复制
hmk1 = np.zeros((3, 3), dtype=np.uint8)
hmk1[0, 0] = 1
hmk1[1, 1] = -1
h1 = cv.morphologyEx(binary, cv.MORPH_HITMISS, hmk1)

输出结果跟原图一样,没有任何改变,很多人都会因此发狂,还反馈说OpenCV的Hit And Miss根本无法使用,我晕!这个时候只需要把结构元素定义改为

代码语言:javascript
复制
hmk1 = np.zeros((3, 3), dtype=np.int32)
hmk1[0, 0] = 1
hmk1[1, 1] = -1
print(hmk1)
h1 = cv.morphologyEx(binary, cv.MORPH_HITMISS, hmk1)

就会运行正确了。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-02-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 OpenCV学堂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档