How do the rho and theta values work in HoughLines?

I have found some source code that finds lines in an image like I want and it uses the following HoughLines:

HoughLines( edges, lines, 1, CV_PI/180, 50, 0, 0 );


What I want to do is add the top, left, right, and bottom borders into the lines vector after Houghlines. From what I read in the documentation:

lines – The output vector of lines. Each line is represented by a two-element vector (rho, theta) . rho is the distance from the coordinate origin (0,0) (top-left corner of the image) and theta is the line rotation angle in radians

lines uses the rho and theta values to represent lines. And that the 1, and CV_PI/180 arguments are called rho and theta. So I did some research on this algorithm and found this diagram:

This looks like a good explanation of what im trying to understand but I still cant wrap my head around how to add the borders using the appropriate rho and theta values. Can somone explain this a little more so that I can possibly understand it? I would really appreciate it! Thanks.

edit retag close merge delete

Sort by » oldest newest most voted

The resulting rho and theta are indeed one step away from the line(s) you are looking for in the image. They represent a line passing through the origin that is perpendicular to the line you want to find. This page has a great introduction to Hough transform concepts, and explains this point.

You might want to use cvHoughLines2 instead, which will allow finding segments instead of lines and a couple of other improvements.

In this example you find some code to draw the lines from rho and theta; the idea is simple: calculate a point of that line, namely x0 = rho cos(theta), y0 = rho sin(theta), and notice that the slope of the line is (-theta), cos(-theta)=cos(theta), sin(-theta)=-sin(theta), and the very large numbers are there to use integer arithmetic.

for( size_t i = 0; i < lines.size(); i++ )
{
float rho = lines[i][0];
float theta = lines[i][1];
double a = cos(theta), b = sin(theta);
double x0 = a*rho, y0 = b*rho;
Point pt1(cvRound(x0 + 1000*(-b)),
cvRound(y0 + 1000*(a)));
Point pt2(cvRound(x0 - 1000*(-b)),
cvRound(y0 - 1000*(a)));
line( color_dst, pt1, pt2, Scalar(0,0,255), 3, 8 );
}

more

( 2012-10-08 08:48:10 -0600 )edit
imgL = cv.imread('left_image_path',0)

stereo = cv.StereoBM_create(numDisparities=32, blockSize=15)
disparity = stereo.compute(imgL,imgR)

vdisp = np.zeros((disparity.shape[0],np.amax(disparity)))

for x in range(0, disparity.shape[0]):
for y in range(0, disparity.shape[1]):
if disparity[x, y] > 0:
vdisp[x, disparity[x,y]-1] += 1

edges = cv.Canny(vdisp.astype(np.uint8),0,10,apertureSize = 3)
lines = cv.HoughLines(edges, 10, np.pi/90, 100)

for rho,theta in lines[0]:
a = np.cos(theta)
b = np.sin(theta)
y1 = int(rho/b)
x1 = int(rho/a)
y2 = int((rho - (a*lines.shape[1]) )/b)
x2 = int((rho - (b*lines.shape[0]) )/a)
cv.line(lines,(x1,y1),(x2,y2),(255,0,0),1)


This seems to be working.

more

I hate this method for finding points it doesn't take in to account the size of the image. And makes obvious translations way harder.

Instead I recommend solving for X given Y or Y given X

Y = (rho - aX)/b

X= (rho - bX)/a

(Where a = cos(theta) and b = sin(theta)

Now just sub in the intersects you want to find

[fX(Y=0), fY(X=0) | fX(Y=image height), fY(X=image width)]

Better yet let's say you need to know where the line crosses in the middle of the screen. Now you have the formula.

more

Rho is the size of the 'bucket' or accumulator array for all incoming rho, or distance from origin. The longest possible distance in an image is from the top left to bottom right, so for maximum accuracy, plug that value into houghlines rho.

Theta is the size of the bucket for all incoming theta. For maximum accuracy you need a value of 180. To only detect even angles, theta should be 90. to only detect angles divisible by 30, theta should be 6

more