I have binary image, the image have many samll black-hole, I want to fill the hole so that I can get the object contours, but the cv.dilate
method work not very well, can someone have good method do that?
Need to fill the object like this(sample)
CodePudding user response:
You can try applying iterative morphological operations (Erode
Dilate
). this should join the white blobs while preserving their size. Get the external contours
and then just compute their bounding boxes
. Depending on your original input (not the binary mask you posted) some tweaks could be made. Let's work with that binary image, this is the code:
# Imports:
import numpy as np
import cv2
# Image path
path = "D://opencvImages//"
fileName = "9ZL1r.png"
# Reading an image in default mode:
inputImage = cv2.imread(path fileName)
# Deep Copy:
inputImageCopy = inputImage.copy()
# Convert RGB to grayscale:
grayscaleImage = cv2.cvtColor(inputImage, cv2.COLOR_BGR2GRAY)
# (Otsu) Threshold:
thresh, binaryImage = cv2.threshold(grayscaleImage, 0, 255, cv2.THRESH_BINARY cv2.THRESH_OTSU)
# Apply Dilate Erode:
kernel = np.ones((5, 5), np.uint8)
binaryImage = cv2.morphologyEx(binaryImage, cv2.MORPH_DILATE, kernel, iterations=5)
binaryImage = cv2.morphologyEx(binaryImage, cv2.MORPH_ERODE, kernel, iterations=5)
So far I've only read, thresholded and filtered the input image. This is the filtered result:
Looks good. Let's get the bounding rectangles:
# Find the EXTERNAL contours on the binary image:
contours, _ = cv2.findContours(binaryImage, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# Look for the outer bounding boxes (no children):
for _, c in enumerate(contours):
# Get the bounding rectangle:
boundRect = cv2.boundingRect(c)
# Draw the rectangle on the input image:
# Get the dimensions of the bounding rect:
rectX = boundRect[0]
rectY = boundRect[1]
rectWidth = boundRect[2]
rectHeight = boundRect[3]
# (Optional) Set color and draw:
color = (0, 0, 255)
cv2.rectangle(inputImageCopy, (int(rectX), int(rectY)),
(int(rectX rectWidth), int(rectY rectHeight)), color, 2)
# Show image:
cv2.imshow("Bounding Rectangles", inputImageCopy)
cv2.waitKey(0)