I'm trying to detect when a zone has some "holes" and where they are located from a source image. Source images can be random and have more than 1 hole.
I would like to find the red circle zones with my code but I don't where to start from.
I don't see any function to help me with that. drawContours won't be helpful there I think (already has been usefull to get those "zones")
Does someone see a way to do that in Python ? (perhaps not using openCV, i'm open to any free library)
Thanks !
CodePudding user response:
One possible method involves extracting the biggest contour (this is the largest "path" in your image), the filtering criteria could also involve directly getting the outermost contour. Then, check for the discontinuous points, in other words, the endpoints of the path. You are essentially asking for a lot of code. Luckily, I've developed a similar algorithm. There are two steps:
- Find the biggest contour/blob/path
- Find the path’s endpoints.
Let's see the code:
# Imports
import cv2
import numpy as np
fileName = "shape01.png"
path = "D://opencvImages//"
# Reading an image in default mode:
inputImage = cv2.imread(path fileName)
# Prepare a deep copy of the input for results:
inputImageCopy = inputImage.copy()
# Grayscale conversion:
grayscaleImage = cv2.cvtColor(inputImage, cv2.COLOR_BGR2GRAY)
# Threshold via Otsu:
_, binaryImage = cv2.threshold(grayscaleImage, 0, 255, cv2.THRESH_BINARY_INV cv2.THRESH_OTSU)
# Find the biggest blob:
binaryImage = findBiggestBlob(binaryImage)
The first steps involves computing a binary image of the input. Then, extract the biggest contour from there. I have implemented a function called findBiggestBlob
, which just computes the biggest blob on the image using its area. It returns an image of the biggest blob isolated; this comes from a
Isolate the minimap and find the output. Some filtering with :
def highlightWalls(image):
img_hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
hsv_color3 = np.asarray([18, 98, 80])
hsv_color4 = np.asarray([28, 125, 137])
hsv_color5 = np.asarray([9, 0, 57])
hsv_color6 = np.asarray([71, 29, 134])
kernel = np.ones((3, 3))
mask1 = cv2.inRange(img_hsv, hsv_color3,hsv_color4)
mask2 = cv2.inRange(img_hsv, hsv_color5,hsv_color6)
mask = cv2.bitwise_xor(mask1, mask2)
blur = cv2.bilateralFilter(image,9,75,75)
image1= cv2.bitwise_and(blur,blur,mask=mask)
cv2.imshow("iamge1", image1)
finalMinimap = cv2.Canny(image1, 150, 200, None, 3)
img_dilate = cv2.dilate(finalMinimap, kernel, iterations=3)
cv2.imshow("walls", img_dilate)
return img_dilate
And Skeleton gives now :
Great job by now ! But I'm missing a last step : Remove all those little "branches" of the skeleton. If not :
Any idea from a boss there ? P.S. : If you have some ideas to better filter my first image let me know of course !