I'm using opencv (version 4.1.0, with Python 3.7) to perform morphological closing on binary images. 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
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.
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.
With constant border (right column of the image), bigger kernels can be used but an unexpected behavior occurs nevertheless with really bigger kernels (e.g. kernel = 20), where the points dissapear.
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.
This answer explains how to use MORPH_CLOSE
around the edge of an image by adding a buffer to the image.
You can add a buffer by creating an image of zeros using 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()