contour approximation in opencv python is giving wrong result everytime

Question:

I am an absolute beginner in image processing.I want to detect a nested shape among various different edges.from my program I have successfully detected my expected contour through hierarchy relation.but my problem arises when I am going to detect the shape.for contour approximation, I am using cv2.approxpolyDP() method/function on my desired contour using its index number.but every time it is resulting in the same output, which is “1”.I don’t know where I am mistaking.please have a look and suggest me some.The code is given below and the images to be detected is also given in those links. please help me…

import cv2
import numpy as np
maxx=0
original_color=cv2.imread("tri.jpg",1)
original=cv2.cvtColor(original_color,cv2.COLOR_BGR2GRAY)
#cv2.imshow("original",original)
blur=cv2.GaussianBlur(original,(5,5),0)
ret,thresh=cv2.threshold(blur,50,255,cv2.THRESH_BINARY)
edges = cv2.Canny(thresh,100,200)
image,contours,hierarchy=cv2.findContours(edges.copy(),cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
print len(contours)
##for c in range(0,len(hierarchy)) :
##    a=zip(hierarchy[c],contours[c])

for i in range(0,len(hierarchy[0])):
    if hierarchy[0][i][2]>=maxx :
         if(hierarchy[0][i][3]==(hierarchy[0][i][2]-2)):
             maxx=hierarchy[0][i][2]
             index=i
cnt=contours[index]
for c in cnt :
    peri=cv2.arcLength(c,True)
    approx=cv2.approxPolyDP(c,0.04*peri,True)
print hierarchy
print maxx
print len(approx)

cv2.drawContours(original_color,contours,index,(0,255,0),3)
cv2.imshow("Show",original_color)
cv2.waitKey()
cv2.destroyAllWindows()

Before Detection

before detection

Succesfully Detected

successfully detected

Asked By: kala_laka

||

Answers:

The result of findContours is a list of list of points, this means that the problem is here:

cnt=contours[index]
for c in cnt :
    peri=cv2.arcLength(c,True)
    approx=cv2.approxPolyDP(c,0.04*peri,True)

Here you select a contour(list of pointS) and then loop for each point and do the approxPolyDP with only 1 point. You should do it to the contour. So, if you want it to do it for the selected contour, you should do:

cnt=contours[index]
peri=cv2.arcLength(cnt,True)
approx=cv2.approxPolyDP(cnt,0.04*peri,True)

If you want to do it for each contour then do like this (keeping the print inside the loop, if not it will show only the last one):

for c in contours:
    peri=cv2.arcLength(c,True)
    approx=cv2.approxPolyDP(c,0.04*peri,True)
    print len(approx)
Answered By: api55