简体   繁体   中英

trouble with findContours and hierarchy (tell if a contour is a hole or not)

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]]

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]
    # Has inner contours which means it is IN
    if currentHierarchy[3] < 0:
        for corner in currentContour[:, 0, :]:
            corner_coords = tuple(corner.tolist())
            corners.add(corner_coords)
    # No child which means it is OUT
    elif currentHierarchy[3] >= 0:
        for corner in currentContour[:, 0, :]:
            corner_coords = tuple(corner.tolist())
            hole_corners.add(corner_coords)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM