Home > Software design >  Detect a "Hole" or "output" in a delimited zone with OpenCV
Detect a "Hole" or "output" in a delimited zone with OpenCV

Time:12-16

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.

enter image description here

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:

  1. Find the biggest contour/blob/path
  2. 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 enter image description here

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

gives : enter image description here

And Skeleton gives now :

enter image description here

Great job by now ! But I'm missing a last step : Remove all those little "branches" of the skeleton. If not : enter image description here

Any idea from a boss there ? P.S. : If you have some ideas to better filter my first image let me know of course !

  • Related