From what I understand, you're trying to differentiate between outer and inner contours. To determine what contours are IN and OUT, you can simply use contour hierarchy to differentiate between the two. Specifically, when using cv2.findContours
you can use cv2.RETR_TREE
to extract outer or inner contours. See understanding contour hierarchies: how to distinguish between contours for the full explanation. From the full topology map we are given, we can filter out the contours, the idea is that if a parent contour has inner contours, it means that it's an OUT
contour and the child inside is the IN
contour. Another case is if a contour has no inner child then we know it is an IN
contour.
Here's an example to demonstrate:
Input image

Result

Code
import cv2
# Load image, grayscale, Otsu's threshold
image = cv2.imread('2.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
# Filter using contour hierarchy
cnts, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[-2:]
hierarchy = hierarchy[0]
for component in zip(cnts, hierarchy):
currentContour = component[0]
currentHierarchy = component[1]
x,y,w,h = cv2.boundingRect(currentContour)
# Has inner contours which means it is IN
if currentHierarchy[2] < 0:
cv2.putText(image, 'IN', (x,y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (36,255,12), 2)
# No child which means it is OUT
elif currentHierarchy[3] < 0:
cv2.putText(image, 'OUT', (x,y-5), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (36,255,12), 2)
cv2.imshow('image', image)
cv2.waitKey()