1

I'm trying to write a piece of code that can detect and isolate straight lines from an image. I'm using the opencv library, together with Canny edge detection and Hough transformation to achieve this. So far I've come up with the following:

import numpy as np
import cv2

# Reading the image
img = cv2.imread('sudoku-original.jpg')
# Convert the image to grayscale
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# Edge detection
edges = cv2.Canny(gray,50,150,apertureSize = 3)
# Line detection
lines = cv2.HoughLines(edges,1,np.pi/180,200)

for rho,theta in lines[0]:
    a = np.cos(theta)
    b = np.sin(theta)
    x0 = a*rho
    y0 = b*rho
    x1 = int(x0 + 1000*(-b))
    y1 = int(y0 + 1000*(a))
    x2 = int(x0 - 1000*(-b))
    y2 = int(y0 - 1000*(a))

    cv2.line(img,(x1,y1),(x2,y2),(0,0,255),2)

cv2.imwrite('linesDetected.jpg',img)

In theory this code snippet should do the job, but unfortunately it doesn't. The resulting picture clearly shows only one line being found. I'm not quite sure what I'm doing wrong here and why it's only detecting one specific line. Could someone possibly figure out the problem here?

enter image description here

  • It only shows one line because you tell it to display only the first detected line -- `lines[0]`. In fact this only works due to a quirk in the way OpenCV maps datatypes from C++ to Python. If you correctly loop over the whole array (as @teng suggests, although with the modification mentioned in my comment), it will visualize all the **detected** lines correctly. Now, the next question would be "Why doesn't this detect all the lines?" – Dan Mašek May 27 '19 at 01:01
  • Since you shouldn't ask multiple questions per question post, I'd suggest changing the title to something like "Why does this visualize only one detected line?". Then create a new question about why it doesn't detect all the lines (including the corrected `for` loop). – Dan Mašek May 27 '19 at 01:03
  • 1
    And save the `edges` image to file and look at it -- should give you a good hint why that second-from left line isn't found. IIRC the tutorial does adaptive threshold before further processing -- the inconsistent illumination of the image is definitely bound to cause issues. – Dan Mašek May 27 '19 at 01:05

1 Answers1

2

Despite opencv's Hough Transform tutorial is using just one loop, the shape of lines is actual [None,1,2], thus when you use lines[0] you will only get one item for rho and one item for theta, which will only get you one line. therefore, my suggestion is to use a double loop (below) or some numpy slice magic to maintain using just 1 loop. To get all the grid detected, as Dan Masek mentioned, you will need to play with the edge detection logic. Maybe see the solution that uses HoughLinesP.

for item in lines:
    for rho,theta in item:
        ...

enter image description here

pangyuteng
  • 1,749
  • 14
  • 29
  • 1
    It fixed something... Now it shows a lot more lines, but still not all of them... – Frederik Vanclooster May 27 '19 at 00:33
  • That second loop is unnecessary, a simple `rho, theta = item[0]` will do, since that inner list will always have just one item (this is a quirk of OpenCV's method of mapping between C++ and Python data structures). – Dan Mašek May 27 '19 at 00:47
  • Also some explanation of what the OP did wrong, and why the code you show should be used would be helpful. Even better if you show an example of what `lines` looks like. – Dan Mašek May 27 '19 at 01:10
  • 1
    @DanMašek will do. Thanks for the suggestion. – pangyuteng May 27 '19 at 03:46