简体   繁体   English

如何从 opencv 的 morhpologyEx 获得关于图像边界的预期行为?

[英]How to get expected behavior from opencv's morhpologyEx with regard to image boundaries?

I'm using opencv (version 4.1.0, with Python 3.7) to perform morphological closing on binary images.我正在使用 opencv(版本 4.1.0,使用 Python 3.7)对二进制图像执行形态学关闭。 I'm having trouble with boundaries when using big closing kernels.我在使用大的闭合内核时遇到边界问题。

My code is :我的代码是:

close_size = 20
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (close_size, close_size))
result = cv2.morphologyEx(im, cv2.MORPH_CLOSE, kernel)

I read this question and this question , and also the the docs , which lead me to also try to change the borderValue argument in morphologyEx() like so我阅读了这个问题这个问题,还有文档,这使我也尝试像这样更改morphologyEx()borderValue参数

result = cv2.morphologyEx(im, cv2.MORPH_CLOSE, kernel,borderValue=[cv2.BORDER_CONSTANT,0])

But both methods do not lead to what I want.但是这两种方法都不会导致我想要的。 I've summed up their behaviors in the image below.我在下图中总结了他们的行为。

在此处输入图片说明

My original image is on top.我的原图在上面。 The behavior I expect is for the two dots to remain separate for small kernels (eg, kernel = 1), and merge together for big enough kernels.我期望的行为是,对于小内核(例如,内核 = 1),这两个点保持分开,而对于足够大的内核,则合并在一起。
As you can see, for the default border (left column of the image), the merge is correct when the kernel = 6, but as soon as it gets bigger, the dots start to merge with the boundary.如您所见,对于默认边界(图像的左列),当内核 = 6 时合并是正确的,但一旦变大,点就开始与边界合并。
With constant border (right column of the image), bigger kernels can be used but an unexpected behavior occurs nevertheless with really bigger kernels (eg kernel = 20), where the points dissapear.对于恒定边界(图像的右列),可以使用更大的内核,但是对于真正更大的内核(例如内核 = 20),会出现意外行为,其中点消失了。

The closing kernel is left as a parameter for the user in the final software, in order to be able to merge dots which can be really far away.关闭内核在最终软件中作为参数留给用户,以便能够合并可能非常远的点。 So ideally, I would need to be able to handle smoothly kernels which are really bigger than the distance between objects and the boundaries.所以理想情况下,我需要能够平滑地处理比对象和边界之间的距离更大的内核。

Original image :原图: 在此处输入图片说明

This answer explains how to use MORPH_CLOSE around the edge of an image by adding a buffer to the image.这个答案解释了如何通过向图像添加缓冲区来在图像边缘使用MORPH_CLOSE

You can add a buffer by creating an image of zeros using numpy:您可以通过使用 numpy 创建零图像来添加缓冲区:

# Import packages
import cv2
import numpy as np
import matplotlib.pyplot as plt
# Read in the image
img = cv2.imread('/home/stephen/Desktop/OKoUh.png', 0)
# Create a black bufffer around the image
h,w = img.shape
buffer = max(h,w)
bg = np.zeros((h+buffer*2, w+buffer*2), np.uint8)
bg[buffer:buffer+h, buffer:buffer+w] = img

Then you can iterate and check how it looks at different kernel sizes:然后您可以迭代并检查它在不同内核大小下的外观:

for close_size in range(1,11):
    temp  = bg.copy()
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (close_size, close_size))
    result = cv2.morphologyEx(temp, cv2.MORPH_CLOSE, kernel)
    results = result[buffer:buffer+h, buffer:buffer+w]
    cv2.imshow('img', result)
    cv2.waitKey()

My results:我的结果: 结果

Based on Stephen's answer, here is the snippet I ended up implementing :根据斯蒂芬的回答,这是我最终实现的片段:

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (close_size, close_size))
# Padding
im=cv2.copyMakeBorder(im,close_size,close_size,close_size,close_size,
                      borderType=cv2.BORDER_CONSTANT, value = 0)
# Closing
im = cv2.morphologyEx(im, cv2.MORPH_CLOSE, kernel)
# Unpadding
im = im[close_size:-close_size,close_size:-close_size]

As I mentionned in a comment, this can lead to a much longer computation time for large kernel sizes.正如我在评论中提到的,对于大内核大小,这可能会导致更长的计算时间。 It's possible that padding with lower values, eg close_size/2 would be enough to prevent border issues (didn't test it).填充较低的值,例如 close_size/2 可能足以防止边界问题(未测试)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM