# Corners and lines detection in hand drawn pictures in Python

I'm working on a project and at some point I have to detect corners and lines in a hand drawn picture. I am doing the work in Python but the result I get is not that good.

The code I wrote is the following:

import sys
from math import sin, cos, sqrt, pi
import cv
cv.NamedWindow("Source", 1)
cv.NamedWindow("Result", 1)
dst = cv.CreateImage(cv.GetSize(src), 8, 1)
color_dst = cv.CreateImage(cv.GetSize(src), 8, 3)
storage = cv.CreateMemStorage(0)
lines = 0
cv.Canny(src, dst, 1.0, 4.0, aperture_size=3)
cv.CvtColor(dst, color_dst, cv.CV_GRAY2BGR)
lines = cv.HoughLines2(dst, storage, cv.CV_HOUGH_PROBABILISTIC, 1, pi / 180, 10, 0, 10)
for line in lines:
cv.Line(color_dst, line[0], line[1], cv.CV_RGB(0, 255, 0), 2, 8)
cornerMap = cv.CreateMat(dst.height, dst.width, cv.CV_32FC1)
cv.CornerHarris(dst,cornerMap,3)
for y in range(0,dst.height):
for x in range (0, dst.width):
harris = cv.Get2D(cornerMap, y, x)
if harris[0] >10e-06:
cv.Circle(color_dst, (x,y),2,cv.RGB(115,0,25))
cv.ShowImage("Source", src)
cv.ShowImage("Hough", color_dst)
cv.SaveImage("draw_det.png", color_dst)
cv.WaitKey()


The input picture can be seen here:

While the resultant picture can be seen here:

The result is not what I am expecting. What I want as output is to see the corner points detected in red and the lines connecting them in green. While what I get is something that does not make sense by looking at the pictures. What am I doing wrong?

edit retag close merge delete

Sort by » oldest newest most voted

First of all: don't use the old python interface, the cv2-interace is much cooler since you can use the mighty numpy-arrays --> i.e. use cv2 instead of cv.

You don't draw the lines in a correct way, thus they don't show up. For the Harris-corner-detector you just don't use the correct parameters, furthermore as suggested in the documentation a non-maximum suppression step should be used, to remove too close corners.

My solution, still not perfect though:

import cv2
import numpy as np

edges = cv2.Canny(img, 50, 200)

# find lines
lines = cv2.HoughLinesP(np.copy(edges), 1, np.pi/180.0, 10, 0, 10)
# draw found lines
img_dst = cv2.cvtColor(img, cv2.cv.CV_GRAY2BGR)
for line in lines[0]:
cv2.line(img_dst, (line[0], line[1]), (line[2], line[3]), (0,255,0), 2)

# find corners
dst = cv2.cornerHarris(img, 15, 5, 0.04)
# non-maximum suppression via dilation
kernel = np.ones((10,10))
max_dst = cv2.dilate(dst, kernel)
dst = dst * (dst == max_dst)
# sort points by strength, find their positions and take 5 highest ones
sortIdx = np.argsort(dst.flatten())[::-1][:5]
# draw them
w = img.shape[1]
for idx in sortIdx:
cv2.circle(img_dst, (idx % w, idx / w) , 3, (0,0,255), -1)


Result:

For the lines I just took your Hough-lines values, guess you could find better ones. Furthermore, Canny() produces two edges at each side of the lines which also results in two found lines, maybe other Canny-Parameters will work here better, too. For cornerHarris, I just draw the 5 most "corner-like" pixels according to the strength returned. However note that they are not sub-pixel accurate (maybe they could be refined w. cv2.cornerSubPix()).

more

1

Thank you so much! What you just give me is a great starting point! I will check the subPixel and the Canny. Thanks again! I will update the post as soon as I get something more. Could be helpful for others.

( 2013-12-17 03:42:07 -0500 )edit

Official site

GitHub

Wiki

Documentation