The Image Processing Toolbox does not contain a hough routine, and although the Hough transform can be obtained by other means, it is a pleasant programming exercise to write our own. Following the procedure outlined above, we will:
1. decide on a discrete set of values of and to use,
2. for each foreground pixel in the image calculate the values of &
for all of our chosen values of ,
3. create an accumulator array whose sizes are the numbers of angles and values in our chosen discretizations from step 1,
4. step through all of our values updating the accumulator array as we go. We shall consider each step in turn:
Discretizing and . We observe that even though a particular pair corresponds to only one line, a given line can be parameterized in different ways. For example, the line
can be parameterized using #
and as shown in figure 10.7(a). However, the same line can be parameterized using
and
. So we have a choice: we may restrict the values of , say to the range
, and let have both positive and negative values, or we may let take any value chosen from the range
# and restrict to non-negative values. Since we are going to use the values of and as indices into the accumulator array, it is simplest to take the second option. However, consider figure 10.7(a) slightly redrawn to take into account the directions of and as column and row indices of a matrix, as shown in (b). Since our image, for which both and will be positive, will sit in the bottom right quadrant, we will only have positive values for
. For if is outside that range, the perpendicular will point into the second (upper left) quadrant, which would require a negative value of if the line was to intersect the image.
We can choose any discrete set of values we like, but let us take all the integer degree values in the given range, but convert them to radians for the purposes of calculation:
10.2. IMPLEMENTING THE HOUGH TRANSFORM IN MATLAB 175 #
(a) Using ordinary Cartesian axes
Image #
(b) Using matrix axes
Figure 10.7: A line parameterized with and
>> angles=[-90:180]*pi/180;
Calculating the values. Suppose that the image is binary, then we can find the positions of all the foreground pixels with a simple application of the find function:
>> [x,y]=find(im);
If the image is not binary, we can create a binary edge image by use of the edge function. Now we can calculate all the values with one simple command:
>> r=floor(x*cos(angles)+y*sin(angles)); where we use floor so as to obtain only integer values.
Forming the accumulator array. If the image is of size pixels, then supposing the origin to be at the upper left corner, the maximum value of will be
. So the size of the accumulator array can be set at
. However, we are only interested in positive values of : given our choice of range of , negative values can be discarded. So we can first find the largest positive value of , and use that as one dimension of the array:
>> rmax=max(r(find(r>0))); >> acc=zeros(rmax+1,270);
The rmax+1 allows us to have values of .
Updating the accumulator array. We now have to step through the array of values, and for each value , increase the corresponding accumulator value by one. First notice that the array
176 CHAPTER 10. THE HOUGH AND DISTANCE TRANSFORMS r, as define above, has size , where is the number of foreground pixels. Hence the second index of both r and acc corresponds to the angle.
This can be done with nested loops, at the heart of which will be the command if r(i,j)>=0, acc(r(i,j)+1,i)=acc(r(i,j)+1,i)+1;
Note that this is not a very efficient method of creating the accumulator array, but it does have the advantage of following the theory very closely. The entire program is shown in figure 10.8.
function res=hough(image) %
% HOUGH(IMAGE) creates the Hough transform corresponding to the image IMAGE % if ~isbw(image) edges=edge(image,’canny’); else edges=image; end; [x,y]=find(edges); angles=[-90:180]*pi/180; r=floor(x*cos(angles)+y*sin(angles)); rmax=max(r(find(r>0))); acc=zeros(rmax+1,270); for i=1:length(x), for j=1:270, if r(i,j)>=0 acc(r(i,j)+1,j)=acc(r(i,j)+1,j)+1; end; end; end; res=acc;
Figure 10.8: A simple Matlab function for implementing the Hough transform
An example
Let us take the cameraman image, and apply our Hough transform procedure to it: >> c=imread(’cameraman.tif’);
>> hc=hough(c);
This last command may take some time, because of the inefficient nested loops. The first thing we may do is to view the result:
>> imshow(mat2gray(hc)*1.5)
where the extra 1.5 at the end is just to brighten up the image. The result is shown in figure 10.9. What we are viewing here is the accumulator array. And it is what we should expect: a series of curves, with some bright points indicating places of maximum intersection. Because of the use of
10.2. IMPLEMENTING THE HOUGH TRANSFORM IN MATLAB 177
Figure 10.9: The result of a Hough transform
sines and cosines in the construction of the transform, we can expect the curves to be of a sinusoidal nature.
What now? Let us find the maximum value of the transform: >> max(hc(:))
ans = 91
We can now find the and values corresponding to the maximum: >> [r,theta]=find(hc==91)
r = 138
theta = 181
However, since we are using the pixel coordinates as cartesian coordinates, our and axes have been rotated counter-clockwise by . Thus we are measuring in a clockwise direction from the left vertical edge of our image. Figure 10.10 shows how this works:
We have also got the problem that We can easily create a small function to draw lines for us, given their perpendicular distance from the origin, and the angle of the perpendicular from the axis. The tool for this will be the line function, which in the form
178 CHAPTER 10. THE HOUGH AND DISTANCE TRANSFORMS
Figure 10.10: A line from the Hough transform
draws a line between coordinates and over the current image. The only difficulty here is that line takes the axis to be on the top, and the axis going down on the left. This is easily dealt with by replacing with
, and a simple function for drawing lines is shown in figure 10.11.
The only thing to notice is the expression 181-theta in the line angle=pi*(181-theta)/180;
This can be interpreted as
; the initial
swaps between cartesian and matrix coordinates, and the extra 1 counters the accumulation of r+1 in the function hough.m.
We can use this as follows:
>> c2=imadd(imdivide(cm,4),192); >> imshow(c2)
>> houghline(c2,r,theta)
The idea of using c2 is simply to lighten the image so as to show the line more clearly. The result is shown on the left in figure 10.12. To draw other lines, we can extract some more points from the transform: >> [r,theta]=find(hc>80) r = 148 138 131
10.2. IMPLEMENTING THE HOUGH TRANSFORM IN MATLAB 179
function houghline(image,r,theta) %
% Draws a line at perpendicular distance R from the upper left corner of the % current figure, with perpendicular angle THETA to the left vertical axis. % THETA is assumed to be in degrees.
% [x,y]=size(image); angle=pi*(181-theta)/180; X=[1:x]; if sin(angle)==0 line([r r],[0,y],’Color’,’black’) else line([0,y],[r/sin(angle),(r-y*cos(angle))/sin(angle)],’Color’,’black’) end;
Figure 10.11: A simple Matlab function for drawing lines on an image
180 CHAPTER 10. THE HOUGH AND DISTANCE TRANSFORMS 85 90 theta = 169 181 182 204 204
Then the command
>> houghline(c,r(1),theta(1))
will place the line as shown on the right in figure 10.12. Clearly we can use these functions to find any lines we like.