So I'm trying to obtain hough lines on a chessboard, but the algorithm results in only one line being detected. I'm using python 2.7 and opencv 3.0. Here's the code:
def applyHoughLineTransform():
image1 = cv2.imread('pictures/board1.png',0)
image2 = cv2.imread('pictures/board2.png',0)
image3 = cv2.imread('pictures/board3.png')
image4 = cv2.imread('pictures/board4.png')
lines1 = cv2.HoughLines(image1,1,math.pi/180.0,5)
lines2 = cv2.HoughLines(image2,1,math.pi/180.0,5)
lines1 = lines1[0]
lines2 = lines2[0]
for rho,theta in lines1:
print ('Rho and theta:',rho,theta)
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))
print (x1,y1)
print (x2,y2)
cv2.line(image3,(x1,y1),(x2,y2),(0,0,255),2)
for rho,theta in lines2:
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(image4,(x1,y1),(x2,y2),(0,0,255),2)
cv2.imwrite('pictures/board1.png',image1)
cv2.imwrite('pictures/board2.png',image2)
cv2.imshow('hough line 1',image3)
cv2.imshow('hough line 2',image4)
Here's the canny edge image on which i perform the hough line algorithm:
And here are the results:
As you can see, pretty lame. The canny algorithm seems to be providing really nice edges to operate on. I'm not entirely sure what I'm doing wrong. I imagine it has something to do with the arguments inputted into the houghLines function. If someone could point me in the right direction (or fix my problem entirely :) ) I would greatly appreciate it. Here's a link to the tutorial site I'm using:
http://opencv-python-tutroals.readthedocs.org/en/latest/py_tutorials/py_imgproc/py_houghlines/py_houghlines.html
OPENCV 3.1.0
After checking the example from the package This is what you should use to get it right in Opencv 3.0.0 +
import cv2
import numpy as np
import math
image1 = cv2.imread('img.png')
gray=cv2.cvtColor(image1,cv2.COLOR_BGR2GRAY)
dst = cv2.Canny(gray, 50, 200)
lines= cv2.HoughLines(dst, 1, math.pi/180.0, 100, np.array([]), 0, 0)
#lines1 = cv2.HoughLines(image1,1,math.pi/180.0,5)
#lines2 = cv2.HoughLines(image2,1,math.pi/180.0,5)
#lines1 = lines1[0]
#lines2 = lines2[0]
a,b,c = lines.shape
for i in range(a):
rho = lines[i][0][0]
theta = lines[i][0][1]
a = math.cos(theta)
b = math.sin(theta)
x0, y0 = a*rho, b*rho
pt1 = ( int(x0+1000*(-b)), int(y0+1000*(a)) )
pt2 = ( int(x0-1000*(-b)), int(y0-1000*(a)) )
cv2.line(image1, pt1, pt2, (0, 0, 255), 2, cv2.LINE_AA)
cv2.imshow('image1',image1)
cv2.waitKey(0)
cv2.destoryAllWindows(0)
OUTPUT
The fix to this issue, was to switch from opencv 3.0 to 2.4. Now I get all the lines I want. Lesson learned... it's in beta for a reason! Here are the results:
I had the same issue with OpenCV 3.4. The culprit is in the numpy array lines:
[[[ 7.99000000e+02 1.57079637e+00]]
[[ 9.39000000e+02 1.57079637e+00]]
[[ 1.57100000e+03 1.57079637e+00]]
[[ 6.68000000e+02 1.57079637e+00]]
[[ 5.46000000e+02 1.57079637e+00]]
[[ 1.42700000e+03 1.57079637e+00]]
...
[[ 1.49100000e+03 1.57079637e+00]]]
Notice this is a 3D array, while the example code treats it as a 2D array. The fix is simply to extract rho and theta from the 3D array (only the first 2 lines are changed):
for line in lines:
rho, theta = line[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)
Related
There are some implementations of the Hough transform on the internet, only I don't understand a part:
When we find our couple (rho, theta), we have to go back to Cartesian.
To draw the lines here is what is used:
for i in range (len(Liste_p)):
a = cos(Liste_theta[i])
b = sin(Liste_theta[i])
x0 = a*Liste_p[i]
y0 = b*Liste_p[i]
x1 = int(x0 + 1000*(-b)) # x1 stores the rounded off value of (rcos(theta)-1000sin(theta))
y1 = int(y0 + 1000*(a)) # y1 stores the rounded off value of (rsin(theta)+1000cos(theta))
x2 = int(x0 - 1000*(-b)) # x2 stores the rounded off value of (rcos(theta)+1000sin(theta))
y2 = int(y0 - 1000*(a)) # y2 stores the rounded off value of (rsin(theta)-1000cos(theta))
plot([x1,x2],[y1,y2],color="r")
But what is multiplication by 1000?
In fact I do not understand the link with the line that we are supposed to draw
How to obtain pixel value of a gray scale image using the Bresenham line algorithm given a line at different angles as shown in this code fraction
I hope and you can help me
import cv2
import numpy as np
img= cv2.imread("0.L3Luzr_Esq.tif")
def bresenham(origin, dest):
# debug code
print origin
print dest
# end debug code
x0 = origin[0]; y0 = origin[1]
x1 = dest[0]; y1 = dest[1]
steep = abs(y1 - y0) > abs(x1 - x0)
backward = x0 > x1
if steep:
x0, y0 = y0, x0
x1, y1 = y1, x1
if backward:
x0, x1 = x1, x0
y0, y1 = y1, y0
dx = x1 - x0
dy = abs(y1 - y0)
error = dx / 2
y = y0
if y0 < y1: ystep = 1
else: ystep = -1
result = []
for x in range(x0, x1):
if steep: result.append((y, x))
else: result.append((x, y))
error -= dy
if error < 0:
y += ystep
error += dx
return result
if backward: return result.reverse()
else: return result
print result
return result
I am trying to implement Hough line transform by myself, but I just couldn't do the last step which is drawing high voted thetas/rhos values. I tried to do its math on my own but It remained to get wrong outputs. When I checked some implementations of others, they were always using this approach to transform from Polar to cartesian coordinates in order to find two points.
for r,theta in lines[0]:
# Stores the value of cos(theta) in a
a = np.cos(theta)
# Stores the value of sin(theta) in b
b = np.sin(theta)
# x0 stores the value rcos(theta)
x0 = a*r
# y0 stores the value rsin(theta)
y0 = b*r
# x1 stores the rounded off value of (rcos(theta)-1000sin(theta))
x1 = int(x0 + 1000*(-b))
# y1 stores the rounded off value of (rsin(theta)+1000cos(theta))
y1 = int(y0 + 1000*(a))
# x2 stores the rounded off value of (rcos(theta)+1000sin(theta))
x2 = int(x0 - 1000*(-b))
# y2 stores the rounded off value of (rsin(theta)-1000cos(theta))
y2 = int(y0 - 1000*(a))
# cv2.line draws a line in img from the point(x1,y1) to (x2,y2).
# (0,0,255) denotes the colour of the line to be
#drawn. In this case, it is red.
cv2.line(img,(x1,y1), (x2,y2), (0,0,255),2)
The previous code from GeeksForGeeks.
What I didn't get are those equations x1 = int(x0 + 1000*(-b)) & y2 = int(y0 - 1000*(a)). By translating these equations as a mathematic form : x1 = r cos(theta) + r (-sin(theta))||
y1 = r sin(theta) + r (cos(theta))
These two equations are just strange to me. 'r cos(theta)' is normal as we transfer from polar to cartesian. However, the next part isn't clear. Could anyone explain the original math behind it?
(r cos, r sin) is the point closest to the origin on the line. It is not a line equation. To draw a line, u need 2 points. Here, he just moved along line 1000 and -1000 to get two points that are guaranteed to be outside a medium sized image
There are many ways to get line equation. Easiest is:
r = x cos + y sin
If x1 = x - t sin
y1 = (1 / sin) (r - x cos + t sin cos)
= y + t cos
He used t=+/-1000 for image size
I want to detect lines and curves with OpenCV 3.1, Python 3.4 and Hough transformer. I found a lot of websites but I dont understand how can I programing the formulae. I have this code:
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)
for circle detection if found this:
x = a + r * cos0
y = b + r * sin0
its enough if i change only x0 and y0 to
x0 = a+rho*cos0
y0 = b+rho*sin0
?
Thank you in advance.
How do I implement bilinear interpolation for image data represented as a numpy array in python?
I found many questions on this topic and many answers, though none were efficient for the common case that the data consists of samples on a grid (i.e. a rectangular image) and represented as a numpy array. This function can take lists as both x and y coordinates and will perform the lookups and summations without need for loops.
def bilinear_interpolate(im, x, y):
x = np.asarray(x)
y = np.asarray(y)
x0 = np.floor(x).astype(int)
x1 = x0 + 1
y0 = np.floor(y).astype(int)
y1 = y0 + 1
x0 = np.clip(x0, 0, im.shape[1]-1);
x1 = np.clip(x1, 0, im.shape[1]-1);
y0 = np.clip(y0, 0, im.shape[0]-1);
y1 = np.clip(y1, 0, im.shape[0]-1);
Ia = im[ y0, x0 ]
Ib = im[ y1, x0 ]
Ic = im[ y0, x1 ]
Id = im[ y1, x1 ]
wa = (x1-x) * (y1-y)
wb = (x1-x) * (y-y0)
wc = (x-x0) * (y1-y)
wd = (x-x0) * (y-y0)
return wa*Ia + wb*Ib + wc*Ic + wd*Id