0

The problem statement is basically shape detection, when there is a shape inside another, and also list the hierarchy order, for example, "triangle inside hexagon". For this, I am using the numpy array that cv.findContours gives me. The problem I am encountering is that the hierarchial relationships are just not accurate at all, it just doesn't work and I am not able to figure out why. It would be great if someone could tell me if there is a problem in the fundamental logic in my code or if it's just a tweaking issue. I have attached my code below.

I am using opencv 4.2

I have also attached the image I am using below enter image description here

The image that I get in output is enter image description here

Also the output I get in console is

hexagon inside hexagon
hexagon inside hexagon
hexagon inside hexagon
hexagon inside hexagon
{1: {'id': 1, 'shape': 'hexagon', 'hierarchy_shit': array([-1, -1,  2,  0], dtype=int32), 'cx': 311, 'cy': 300, 'area': 193872.0}, 2: {'id': 2, 'shape': 'hexagon', 'hierarchy_shit': array([-1, -1,  3,  1], dtype=int32), 'cx': 311, 'cy': 300, 'area': 191480.0}, 3: {'id': 3, 'shape': 'hexagon', 'hierarchy_shit': array([-1, -1,  4,  2], dtype=int32), 'cx': 309, 'cy': 299, 'area': 189085.5}, 5: {'id': 5, 'shape': 'triangle', 'hierarchy_shit': array([7, 4, 6, 3], dtype=int32), 'cx': 357, 'cy': 281, 'area': 9062.5}, 6: {'id': 6, 'shape': 'triangle', 'hierarchy_shit': array([-1, -1, -1,  5], dtype=int32), 'cx': 356, 'cy': 281, 'area': 8902.0}}


import cv2 as cv
import numpy as np
capture = cv.imread("img.png")





gray = cv.cvtColor(capture, cv.COLOR_BGR2GRAY)
blurred = cv.GaussianBlur(gray, (3, 3), cv.BORDER_DEFAULT)
canny = cv.Canny(blurred, 50, 150, apertureSize=3)

contours, hierarchy = cv.findContours(canny, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
cv.imshow('frame', canny)
cv.drawContours(capture,contours, -1, (255,0,0))
ldic = {}
for idx,contour in enumerate(contours):
    if idx == 0:
        continue
    if cv.contourArea(contour) < 1200:
        continue

    epsilon = 0.01*cv.arcLength(contour, True)
    approx = cv.approxPolyDP(contour, epsilon, True)
    M = cv.moments(approx)


    sides = len(approx)
    if sides == 3:
        label = "triangle"
    elif sides == 4:
        label = "square"
    elif sides == 5:
        label = "pentagon"
    elif sides == 6:
        label = "hexagon"
    else:
        continue

    cont_dict = {
        "id":idx,
        "shape":label,
        "hierarchy_shit":hierarchy[0][idx],
        "cx":int(M['m10']/M['m00']),
        "cy": int(M['m01'] / M['m00']),
        "area": M['m00']
    }

    ldic[idx] = cont_dict

    if M['m00'] != 0:
        cx = int(M['m10']/M['m00'])
        cy = int(M['m01'] / M['m00'])
        cv.putText(capture, cont_dict["shape"], (cx, cy), cv.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 3, cv.FILLED)

        for key,val in ldic.items():
            parent_idx = int(val["hierarchy_shit"][3])
            if parent_idx != -1 and parent_idx in ldic and val["cx"]-ldic[val["hierarchy_shit"][3]]["cx"] >= 0 and val["cy"]-ldic[val["hierarchy_shit"][3]]["cy"] >= 0:
                cv.putText(capture, f"{val["shape"]} inside {ldic[val["hierarchy_shit"][3]]["shape"]}",
                           (cx, cy), cv.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 3, cv.FILLED)
                print(f"{val["shape"]} inside {ldic[val["hierarchy_shit"][3]]["shape"]}")
    cv.imshow('frame1', capture)


print(ldic)
cv.waitKey(0)
cv.destroyAllWindows()

2
  • 2
    are you using opencv version 3.1 or 3.0? show us exactly the output that you see. also minimal reproducible example required, and that means you have to provide all the input that your script requires. you cannot require VideoCapture because nobody can reproduce that. provide a picture as input. Commented Nov 9 at 15:54
  • draw the contours, with green color. you'll notice that your dark blue lines cause TWO contours each. Commented Nov 9 at 18:24

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.