%% Lab: Hough Transforms
%
% CSC 262

%% Overview
% In this lab, we demonstrate what the Hough transform looks like when
% applied to an image and how to use it to detect lines in an image.
% We find the reliability highly sensitive to the edge map quality.


%% A. Hough Transform and Peaks
% The figure below shows the original image and its corresponding edge
% image, calculated using the built-in Matlab Canny edge detector.

% Load and display the source image
img = imread('~weinman/courses/CSC262/images/left.jpg');


% Calculate a simple edge detection on the grayscale image
edges = edge(rgb2gray(img),'canny');

% Show the results
figure;

subplot(1,2,1);
imshow(img);
title('Original Image');

subplot(1,2,2);
imshow(edges);
title('Edge Image');


%%
% Predictably, the shelves and book tops appear in the edge map, though
% often broken. Some of the boundaries between different books appear in
% the edge map, as we might expect. A significant amount of "noise" edges
% for the logos and other decorations within the book spines also appear.

%%
% We run the standard Hough transform on the resulting edge map using the
% default parameters.

[houghCount, theta, rho] = hough(edges);

figure;
imshow(imadjust(mat2gray(houghCount)),[],'XData',theta,'YData',rho, ...
    'InitialMagnification','fit');
title('Hough Transform');
xlabel('\it\theta'); % The backslash indicates to use the TeX interpreter
ylabel('\it\rho');   % Since these are variables, we use italics.
colormap(hot);       % Make the plot of counts more visible
axis on normal       % Show ticks and use xy, not ij orientation
% Note: Display method adapted from MathWorks' documentation for hough and
% ("doc hough", Examples, 
% http://www.mathworks.com/help/images/ref/hough.html#br74esi- 1) and 
% houghpeaks ("doc houghpeaks", Examples, 
% http://www.mathworks.com/help/images/ref/houghpeaks.html#f2-317965 )

hold on; % We're going to add more to the graph

% Calculate the location of the four highest peaks, using built-in method
peaks = houghpeaks(houghCount, 4);

% Plot cyan squares at the theta/rho peaks
plot(theta(peaks(:,2)), rho(peaks(:,1)), 'cs'); 
legend('Peaks');

%%
% Next we investigate the local maxima of the votes for particular line
% parameters in the image. Cyan squares in the figure above indicate the
% locations of the four highest peaks in hough space.

%% B. Hough Lines
% In this section we find and plot all the line segments identified by the
% Hough transform.

% Use built-in command to find lines
lines = houghlines(edges,theta,rho,peaks,'FillGap',10,'MinLength',10);

% Show the original image
figure; 
imshow(img);
hold on; % Enable further writes to the plot

% We use a for loop rather than vectorized options for the somewhat
% imperative plotting that needs to be done.

% Note: The following code is adapted from the MathWorks' documentation for
% houghlines ("doc houghlines", Examples, 
% http://www.mathworks.com/help/images/ref/houghlines.html#f2-317900 )
for seg = lines(:)'
    % NB: "line" is a built-in function name, and "ln" looks like natural
    % log. seg (short for "segment", also a built-in) seemed safest.
   xy = [seg.point1; seg.point2]; % Get line end points
   plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','green'); % Plot line segment

   % Plot beginnings and ends of lines
   plot(xy(1,1),xy(1,2),'x','LineWidth',2,'Color','yellow');
   plot(xy(2,1),xy(2,2),'x','LineWidth',2,'Color','red');
end

% Determine lengths of line segments
lengths = arrayfun(@(seg) norm(seg.point1-seg.point2),lines);
[~,longest] = max(lengths); % Get the index of the longest

% Highlight the longest line segment in magenta
xy = [lines(longest).point1; lines(longest).point2]; % Get line end points
plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','magenta');

%%
% The figure above confirms our interpretation of the edge map. Shelve
% edges are dominant in the image; the longest being the strong vertical
% edge separating shelves. The book edges could be likely found by allowing more
% peaks to be counted.

%% Conclusion
% Hough transforms transforms are a powerful and easy-to-understand method
% for identifying low-dimensional shapes in an image. Their performance
% relies on the quality of the edge map, however. Automatically thresholding
% the peaks to generate line candidates may not always be straightforward.

%% Acknowledgments
% Beyond the libraries themselves, some of the code for hough analysis was
% taken from the MathWorks' documentation for |hough|, |houghpeaks|, and
% |houghlines|. The original image, taken by Jerod Weinman, is in the public
% domain.