problem in python findContours() with connected and disconnected shapes [closed]
Hello everybody, I am running a project in python involving recognition of shapes in images and creation of a graph out of the recognition. The script should be as more general as possible in order to create a graph out of any image given in input. The approach I used is to find the contours of the shapes and re-draw them into a new image. However I am having some troubles when for example the image contains a circle connected to a line: in this case the line is lost and not drawn in the graph. I show you what I mean:
this is the input picture (please don't laught about it):
After the processing, the graph created is this:
It is noticeable that the line of the left "arm" is missing and after a all afternoon of trial, I didn't get to anything. Moreover, Also the "smile" is recognized as pentagon even if the shape is disconnected.
The code written in python is a little ugly because I am not such an expert in python programming, so please excuse me for that:
import numpy as np
import cv2
import Image, ImageDraw
import math
#Function to find a cosine of angle between vectors
#from pt0->pt1 and pt0->pt2
def angle_cos(p1, p2, p0):
dx1 = (p1[0]-p0[0]).astype('double')
dy1 = (p1[1]-p0[1]).astype('double')
dx2 = (p2[0]-p0[0]).astype('double')
dy2 = (p2[1]-p0[1]).astype('double')
return (dx1*dx2 + dy1*dy2) / np.sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10)
#function to create the final graph
def create_graph(vertex, color):
for g in range(0, len(vertex)-1):
for y in range(0, len(vertex[0][0])-1):
cv2.circle(newimg, (vertex[g][0][y], vertex[g][0][y+1]), 3, (255,255,255), -1)
cv2.line(newimg, (vertex[g][0][y], vertex[g][0][y+1]), (vertex[g+1][0][y], vertex[g+1][0][y+1]), color, 2)
cv2.line(newimg, (vertex[len(vertex)-1][0][0], vertex[len(vertex)-1][0][1]), (vertex[0][0][0], vertex[0][0][1]), color, 2)
#Routine
img = cv2.imread('draw.jpg')
cv2.imshow('starting picture', img)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#Remove of noise, if any
blur = cv2.GaussianBlur(gray, (5,5), 0)
#Create a new image of the same size of the starting image
height, width = gray.shape
newimg = np.zeros((height, width, 3), np.uint8)
#Edge detector
thresh = 175
edges = cv2.Canny(blur, thresh, thresh*2)
#Find contours
contours,hierarchy = cv2.findContours(edges, cv2.cv.CV_RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
for b,cnt in enumerate(contours):
if hierarchy[0,b,3] == -1: #Avoid inner contours
approx = cv2.approxPolyDP(cnt,0.025*cv2.arcLength(cnt,True), True)
if len(approx)==5:
if cv2.isContourConvex(approx):
print "pentagon" + " with area = " +str(cv2.contourArea(cnt))
clr = (255, 0, 0)
cv2.drawContours(img,[cnt],-1, clr,-1)
#draw the pentagon in the new image
create_graph(approx, clr)
else:
print ...