We have multiple contours. Some are positive and some are negative (holes). Here is the code i'm using
def get_corners(grid: np.ndarray, show=False):
corners = set()
hole_corners = set()
# Filter using contour hierarchy
cnts, hierarchy = cv.findContours(grid, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)[-2:]
hierarchy = hierarchy[0]
for component in zip(cnts, hierarchy):
currentContour = component[0]
currentHierarchy = component[1]
# x,y,w,h = cv.boundingRect(currentContour)
# Has hole which means it is IN
if currentHierarchy[2] < 0:
for corner in currentContour[:, 0, :]:
corner_coords = tuple(corner.tolist())
hole_corners.add(corner_coords)
# cv.putText(image, 'IN', (x,y-10), cv.FONT_HERSHEY_SIMPLEX, 0.7, (36,255,12), 2)
# No child which means it is OUT
elif currentHierarchy[3] < 0:
for corner in currentContour[:, 0, :]:
corner_coords = tuple(corner.tolist())
corners.add(corner_coords)
the problem with it is that, when there is more than one positive contour, it doesn't work as expected. every positive contour > 1 gets counted as a hole. here is it displayed.
- Red: positive contours
- Green: negatives/holes
As you can see its not working as expected.
all counted as holes
one counted correctly, rest mostly incorrectly
image with contours labelled correctly (ignore corner color here)
Another failure case with islands with no child being counted as holes
hierarchy for this: [[ 1 -1 -1 -1]
[ 3 0 2 -1]
[-1 -1 -1 1]
[-1 1 -1 -1]]
CodePudding user response:
Figured it out. using RETR_CCOMP and checking for currentHierarchy[3] worked for me. Corners is a set with all corners of the outer contours, hole_corners is a set with all corners of the inner, or hole contours.
(cnts, hierarchy) = cv.findContours(grid,mode=cv.RETR_CCOMP, method=cv.CHAIN_APPROX_TC89_KCOS)
corners = set()
hole_corners = set()
# Filter using contour hierarchy
hierarchy = hierarchy[0]
for component in zip(cnts, hierarchy):
currentContour = component[0]
currentHierarchy = component[1]
(hnext, hprev, hchild, hparent) = currentHierarchy
if hparent < 0:
# Has no parent, which means it is not a hole
for corner in currentContour[:, 0, :]:
corner_coords = tuple(corner.tolist())
corners.add(corner_coords)
else:
# Has a parent, which means it is a hole
for corner in currentContour[:, 0, :]:
corner_coords = tuple(corner.tolist())
hole_corners.add(corner_coords)