Это можно сделать, преобразовав входное изображение в изображение края и затем определив контуры. Но в этом случае есть разрыв края изображения (я пробовал с canny) на пересечении двух объектов, как показано ниже.
Break in Canny:
Whereas the expected edge image should have all the pixels at the boundary as white.
Expected edge image:
Thus to get this perfect edge image, I have created an algo shared below(This algo will work only on a binary image like this with objects filled with white color).
Before using this algo, make sure that the object does not lie on the boundary, that is, all the boundary pixels of the image should be black. If not black, add a border on all sides of the image of black colour and length 1 pixel.
# Creating black image of same shape and single channel
edge = np.zeros(img.shape, dtype = np.uint8)
h, w = img.shape[:2]
# Iterating over each pixel except those at the boundary
for i in range(1, h-1):
for j in range(1, w-1):
# if current pixel is white
if img[i][j] == 255:
# roi is the image of 9 pixel from around the current pixel
roi = img[i-1:i+2, j-1:j+2].copy()
# Counting number of black pixel in the neighbourhood of current pixel
blackCount = np.sum(roi == 0)
# if a neighbouring pixel is black, then current pixel is a boundary pixel.
if blackCount > 0:
edge[i][j] = 255
After finding the edge image, get all the contours in the image:
cont, hier = cv2.findContours(edge, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
For this image, you will get 3 contours, 2 for the two objects and 1 for the two objects combined. To eliminate the contour of both the objects combined, use the hierarchy information.
# I am taking only those contours which do not have a child contour.
finalContours = np.asarray([cont[i] for i in range(len(cont)) if hier[0][i][2] == -1])
"finalContours" will have the 2 contours for the two objects.
Обратитесь к этой ссылке для получения дополнительной информации о родительско-дочерних отношениях контуров