Home > Net >  Getting duplicate contours
Getting duplicate contours

Time:07-28

I want to extract the number of contours/objects in each image along with its side i-e a function should return [num_contours, total_sides, (sides of individual contours)]

But i'm getting two contours for each shape (outer and inner both).

Original image Contour 1 Contour 2 Contour 3 Contour 4

My function:

def get_contour_details(img):
    image = img.copy()
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    blurred = cv2.GaussianBlur(gray, (5, 5), 0)
    value, thresh = cv2.threshold(blurred, 60, 255, cv2.THRESH_BINARY_INV)
    contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
    contour_edges = [len(cv2.approxPolyDP(contour, 0.01* cv2.arcLength(contour, True), True)) for contour in contours]
    num_contours = len(contours)
    total_edges = sum(contour_edges)
    return num_contours, total_edges, contour_edges

Expected answer: [2, 8, [4,4]]

Got: [4, 18, [4, 4, 4, 6]]

Use below image for processing:

enter image description here

Any kind of help will be appreciated!

CodePudding user response:

Open cv will recognize and return both inner and outer contours. You need to filter them based on your need. The relation between contours can be deduced from hierarchy. Hierarchy returns the following list,

[next, previous, first_child, parent]
# next and previous are with respect to same hierarchy level.

If you are interested in external contours, the rows with no parent ( parent = -1) show the external ones. If you need the internal contours the parents will be a nonnegative number (denoting the index of parent in the contours list).

The following code will do the job based on considering external contours and is tested on your sample image.

import numpy as np
import cv2

def get_contour_details(img):
    image = img.copy()
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    blurred = cv2.GaussianBlur(gray, (5, 5), 0)
    value, thresh = cv2.threshold(blurred, 60, 255, cv2.THRESH_BINARY_INV)
    contours, hierarchy = cv2.findContours(thresh, cv2.RETR_CCOMP,cv2.CHAIN_APPROX_SIMPLE)
    # Find external contours.
    index = np.argwhere(hierarchy[0,:,3] == -1).flatten()
    contours = [contours[i] for i in index]
    #
    contour_edges = [len(cv2.approxPolyDP(contour, 0.01* cv2.arcLength(contour, True), True)) for contour in contours]
    num_contours = len(contours)
    total_edges = sum(contour_edges)
    return num_contours, total_edges, contour_edges

img = cv2.imread('img.png', cv2.IMREAD_COLOR)
print(get_contour_details(img))

For learning better about contour hierarchy and its different types see Hierarchy explanation from opencv official tutorial.

CodePudding user response:

You are using the wrong retrieval mode. Why did you choose RETR_TREE ? According to the documentation:

CV_RETR_TREE retrieves all of the contours and reconstructs a full hierarchy of nested contours

So your code is finding both contours inner and outer. Using RETR_EXTERNAL can fix your problem. Because it will only draw the outer contour. By referring to the documentation again:

CV_RETR_EXTERNAL retrieves only the extreme outer contours.

More better option is using RETR_CCOMP which creates a hierarchy for all of the contours. Parent-child elationship, so you can easily seperate the contours.

  • Related