I generate noisy images with certain lines in them, like this one:
I'm trying to detect the lines using OpenCV, but something is going wrong.
Here's my code so far, including the code to generate the noisy images.
import cv2
import numpy as np
def draw_random_lines(img, w, n):
for i in range(n):
point1 = (np.random.randint(low = 0, high = w), np.random.randint(low = 0, high = w))
point2 = (np.random.randint(low = 0, high = w), np.random.randint(low = 0, high = w))
cv2.line(img,point1,point2,(255,0,0),5)
x = y = 0
while(y<w):
while(x<w):
if(np.any(img[x, y] != 0)):
if(np.random.randint(low=0, high=100) < 60):
img[x, y] = [255, 255, 255]
else:
img[x, y] = [0, 0, 0]
else:
if(np.random.randint(low=0, high=100) < 95):
img[x, y] = [255, 255, 255]
else:
img[x, y] = [0, 0, 0]
x+=1
x=0
y+=1
return img
w = 512
img = np.zeros((w,w,3), np.uint8)
img = draw_random_lines(img, w, 5)
cv2.imshow("Original", img)
cv2.imwrite("alo.png", img)
img = cv2.imread("alo.png")
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,50,150,apertureSize = 3)
lines = cv2.HoughLines(edges,1,np.pi/180,200)
for line in lines:
for rho,theta in line:
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.imshow("Detectada", img)
cv2.waitKey(0)
And here are the results I'm getting (very wrong):
So, how can I properly detect the lines in these noisy images?
Since OpenCV's Hough transform implementations look for white pixels on black background, the first important step for finding the lines is to invert your noisy images.
Slight median blurring will further help to get rid of the noise, thus improving the performance of the Hough transform.
For my suggested solution, I also used the HoughLinesP
method instead of HoughLines
. (From my experience, you'll get "better" results.)
So, here's my code snippet:
import cv2
import numpy as np
# Read input
img = cv2.imread('images/K9YLm.png', cv2.IMREAD_GRAYSCALE)
# Initialize output
out = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
# Median blurring to get rid of the noise; invert image
img = 255 - cv2.medianBlur(img, 3)
# Detect and draw lines
lines = cv2.HoughLinesP(img, 1, np.pi/180, 10, minLineLength=50, maxLineGap=30)
for line in lines:
for x1, y1, x2, y2 in line:
cv2.line(out, (x1, y1), (x2, y2), (0, 0, 255), 2)
cv2.imshow('out', out)
cv2.waitKey(0)
cv2.destroyAllWindows()
The output out
looks like this:
Due to the usage of HoughLinesP
, you get a quite large set of (smaller) lines. One would need to setup a kind of "grouping" of similar lines. (Or, maybe one could just draw the red lines on a separate image, and re-run the line detection.)
Hope that helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With