Home > Net >  Find maximum inscribed circle in a non convex hull
Find maximum inscribed circle in a non convex hull

Time:04-10

By "non convex hull" I mean something like

enter image description here

the black portion of the image (my apologies if this is not "non convex hull", I do not have a better word to describe it).

What I am trying to get is a maximum inscribed circle within the black portion, like the red circle below. enter image description here

In other words, I would like to know the circle in a vacant space. Is this possible using opencv? When I try to get the circle using the following code

dist_map = cv2.distanceTransform(src_mask, cv2.DIST_L2, cv2.DIST_MASK_PRECISE)
_, radius, _, center = cv2.minMaxLoc(dist_map)
result = cv2.cvtColor(src_mask, cv2.COLOR_GRAY2BGR)
cv2.circle(result, tuple(center), int(radius), (0, 0, 255), 2, cv2.LINE_8, 0)

I got this instead. enter image description here As you can see, the circle goes out of bound. I'm happy to hear any suggestions and pointers. Thank you!

EDIT: I added a minimal example to reproduce this. Here is the script, and the outcome is attached below

import cv2
import numpy as np


##########
# create mask
# 0 if background, 255 if foreground
##########
src_mask = np.zeros((281, 500))
src_mask[100:170, 200:400] = 255
src_mask[127:143, 150:440] = 255
src_mask[213: 244, 30:59] = 255
src_mask[239: 279, 360:460] = 255
src_mask = src_mask.astype("uint8")
result = cv2.cvtColor(src_mask, cv2.COLOR_GRAY2BGR)
cv2.imwrite("mask.png", result)

##########
# draw contours
# the reason for 255-src_mask is that I want to have a circle in black portion instead of white portion 
##########
dist_map = cv2.distanceTransform(255 - src_mask, cv2.DIST_L2, cv2.DIST_MASK_PRECISE)
contours, _ = cv2.findContours(255 - src_mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[-2:]
result = cv2.cvtColor(src_mask, cv2.COLOR_GRAY2BGR)
cv2.drawContours(result, contours, -1, (255, 0, 0))
cv2.imwrite('contour.png', result)

##########
# circle
##########
dist_map = cv2.distanceTransform(255 - src_mask, cv2.DIST_L2, cv2.DIST_MASK_PRECISE)
_, radius, _, center = cv2.minMaxLoc(dist_map)
result = cv2.cvtColor(src_mask, cv2.COLOR_GRAY2BGR)
cv2.circle(result, tuple(center), int(radius), (0, 0, 255), 2, cv2.LINE_8, 0)
cv2.imwrite('circle.png', result)

and the output is enter image description here Again, the circle goes out of bound.

CodePudding user response:

This can do the magic. Mask also your frame edges, like:

src_mask[:, 0 ] = 255
src_mask[:, -1 ] = 255
src_mask[0, : ] = 255
src_mask[-1, : ] = 255

That way, the calculated distances would take the frame into account. (If you further need the mask copy it before changes)

I got with your example:

enter image description here

CodePudding user response:

umm, there’s some cases of occurring it:

case 1: set the variable center wrongly ;-;

case 2: because of cv2 coords ( 0, 0 ) is the top left of the screen, so that if center is correct, then make sure that you’ve made the the cv2 screen as your screen size, else that happens

  • Related