'Find maximum inscribed circle in a non convex hull
By "non convex hull" I mean something like
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.

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.
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)
Solution 1:[1]
This can do the magic. Mask also your frame boundaries, 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's boundaries into account. (If you further need the mask copy it before changes)
I got with your example:
Solution 2:[2]
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
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Dharman |



