Hough transform with a different theta interval with matlab - matlab

The hough transform in matlab is called in the following way:
[H, theta, rho] = hough(BW)
If I want to specify the theta values, I can use
[H, theta, rho] = hough(BW, 'Theta', 'begin:step:end')
The theta parameter specify a vector of Hough transform theta values. My problem is the fact that the acceptable range of theta values in Matlab is between -90 and 90 degrees. I want to calculate the hough transform with theta values between 0 and 180 degrees. Should I re-implement hough transform in matlab? is there any other code that allows this range in hough transform?

Due to the definition of the hough-Transformation, the vale for r(roh,theta)=r(-roh,theta+180). You can flip the data you get for -90:0 horizontally and you will get the data for 90:180.
The following code uses the example from the documentation and completes the data to full 360 degree:
%example code
RGB = imread('gantrycrane.png');
% Convert to intensity.
I = rgb2gray(RGB);
% Extract edges.
BW = edge(I,'canny');
[H,T,R] = hough(BW,'RhoResolution',0.5,'Theta',-90:0.5:89.5);
% Display the original image.
subplot(3,1,1);
imshow(RGB);
title('Gantrycrane Image');
% Display the Hough matrix.
subplot(4,1,2);
imshow(imadjust(mat2gray(H)),'XData',T,'YData',R,...
'InitialMagnification','fit');
title('Hough Transform of Gantrycrane Image');
xlabel('\theta'), ylabel('\rho');
axis on, axis normal, hold on;
colormap(hot);
%Modifications begin
subplot(3,1,3);
%append another 180 degree to the axis
T2=[T T+180];
%append flipped data
H2=[H,H(end:-1:1,:)];
%plot the same way.
imshow(imadjust(mat2gray(H2)),'XData',T2,'YData',R,...
'InitialMagnification','fit');
title('Hough Transform of Gantrycrane Image');
xlabel('\theta'), ylabel('\rho');
axis on, axis normal, hold on;
colormap(hot);

Related

Remove Exponents from Matlab LOG-LOG plot

I am trying to plot several frequency response curves on a logx and logy plot. I also want the axes to show values without exponents.
I cannot figure out a way to plot the log scale AND remove exponents. Using the following, I can only either set my scale to log, OR remove exponents. Not both.
figure(3);clf;
hold on;
%set(gca,'YScale', 'log', 'XScale', 'log')); %This doesnt work with ax.XAxis.Exponent = 0;
plot(freq, Pxx,'r', 'LineWidth', 1.5, 'DisplayName', 'Single-Sided Spectral Density');
ax=gca;
ax.XAxis.Exponent = 0; %remove exponents
ax.YScale = 'log'; %Log Y
ax.XScale = 'log'; %Log X
xlabel('Frequency [Hz]');ylabel('[WU^2 / Hz]');
title('Average Single-Sided Spectral Density [G_x_x] vs. Frequency')
grid on;
xlim([0 max(freq)]);legend('FontSize',14);
hold off
Plot with log scale, AND Exponents in scale values
Plot without log scale, without exponents in scale values
Changing the tick labels can be done like this:
figure;loglog([12 123 1233],[12 144 1111]);
set(gca,'xticklabel',arrayfun(#(x) num2str(x),(get(gca,'xtick')),'un',0))
set(gca,'yticklabel',arrayfun(#(x) num2str(x),(get(gca,'ytick')),'un',0))

How to plot a histogram as a scatter plot in matlab?

The y axis should be frequency (which is the histogram part) while the x axis is the xdata used to plot the histogram. Essentially what I need is exactly a histogram but instead of bars, there should be points.
I'd do that using the histcounts command. It's like the histogram command, but instead of plotting the data, it returns the number in each bin and the bin edges. You can then plot that as points using the general plot command.
x = randn(1,1000); %Generate some data to plot
figure(1); clf;
subplot(2,1,1); hold on;
h = histogram(x,'normalization','probability');
title('Plotted as a histogram');
ylabel('Frequency');
subplot(2,1,2); hold on;
[N, edges] = histcounts(x,'normalization','probability');
centers = (edges(1:end-1) + edges(2:end))./2; %histcounts gives the bin edges, but we want to plot the bin centers
plot(centers,N,'ko');
title('Plotted as points');
ylabel('Frequency');

Hough Transform Equivalent in Octave

I have attached a Code of Hough Transform in MATLAB below:
%Hough Transform to find lines
%Load an Image and Convert to Grayscale to apply canny Filter
im = imread('lines.jpg');
im_gray = rgb2gray(im);
im_edge = edge(im_gray, 'canny');
figure, imshow(im), title('Original Image');
figure, imshow(im_gray), title('Grayscale Image');
figure, imshow(im_edge), title('Canny Filter Edge');
%Apply Hough Transform to Find the Candidate Lines
[accum theta rho] = hough(im_edge);
figure, imagesc(accum, 'xData', theta, 'ydata', rho), title('Hough Accumulator');
peaks = houghpeaks(accum, 100, 'Threshold', ceil(0.6 * max(accum(:))),'NHoodSize', [5,5]);
size(peaks);
%Finding the line segments in the image
line_segs = houghlines(edges, theta, rows, peaks, 'FillGap', 50,'MinLength', 100);
%Plotting
figure, imshow(im), title('Line Segments');
hold on;
for k=1:length(line_segs)
endpoints = [line_segs(k).point1; line_segs(k).point2];
plot(endpoints(:,1), endpoints(:,2), 'LineWidth', 2, 'Color','green');
end
hold off;
When I'm trying to implement the same in OCTAVE by changing the 'hough into houghtf', 'houghlines to hough_line' and 'houghpeaks into immaximas' in the following way:
%Hough Transform to find lines
pkg load image;
%Load an Image and Convert to Grayscale to apply canny Filter
im = imread('lines.jpg');
im_gray = rgb2gray(im);
im_edge = edge(im_gray, 'canny');
figure, imshow(im), title('Original Image');
figure, imshow(im_gray), title('Grayscale Image');
figure, imshow(im_edge), title('Canny Filter Edge');
%Apply Hough Transform to Find the Candidate Lines
[accum theta rho] = houghtf(im_edge); %In Octave and 'hough' in MATLAB
figure, imagesc(accum, 'xData', theta, 'ydata', rho), title('Hough Accumulator');
peaks = immaximas(accum, 100, 'Threshold', ceil(0.6 * max(accum(:))),'NHoodSize', [5,5]);
size(peaks);
%Finding the line segments in the image
line_segs = hough_line(edges, theta, rows, peaks, 'FillGap', 50, 'MinLength', 100);
%Plotting
figure, imshow(im), title('Line Segments');
hold on;
for k=1:length(line_segs)
endpoints = [line_segs(k).point1; line_segs(k).point2];
plot(endpoints(:,1), endpoints(:,2), 'LineWidth', 2, 'Color', 'green');
end
hold off;
I get the following error while executing it:
error: element number 3 undefined in return list
error: called from
HoughTransformLines at line 14 column 18
I am getting the error stating 'rho' is undefined.
I am completely new to MATLAB and Octave. Can anyone please help me implement the Hough-Transform in Octave?
I suggest the following updates for the original code:
%Hough Transform to find lines
pkg load image;
%Load an Image and Convert to Grayscale to apply canny Filter
im = imread('lines.jpg');
im_gray = rgb2gray(im);
im_edge = edge(im_gray, 'canny');
figure 1, imshow(im), title('Original Image');
figure 2, imshow(im_gray), title('Grayscale Image');
figure 3, imshow(im_edge), title('Canny Filter Edge');
%Apply Hough Transform to Find the Candidate Lines
accum = houghtf(im_edge);
theta = -90:90;
diag_length = (size(accum)(1) - 1) / 2;
rho = -diag_length:diag_length;
figure 4, imagesc(theta, rho, accum), title('Hough Accumulator');
peaks = houghpeaks(accum, 100, 'Threshold', ceil(0.6 * max(accum(:))), 'NHoodSize', [5,5]);
%Finding the line segments in the image
line_segs = houghlines(im_edge, theta, rho, peaks, 'FillGap', 50, 'MinLength', 100);
%Plotting
figure 5, imshow(im), title('Line Segments');
hold on;
for k=1:length(line_segs)
endpoints = [line_segs(k).point1; line_segs(k).point2];
plot(endpoints(:,1), endpoints(:,2), 'LineWidth', 2, 'Color', 'green');
end
hold off;
Let's walk through all updates and review them:
%Hough Transform to find lines
pkg load image;
%Load an Image and Convert to Grayscale to apply canny Filter
im = imread('lines.jpg');
im_gray = rgb2gray(im);
im_edge = edge(im_gray, 'canny');
figure 1, imshow(im), title('Original Image');
figure 2, imshow(im_gray), title('Grayscale Image');
figure 3, imshow(im_edge), title('Canny Filter Edge');
There are only very minor changes - the indices for the figures were added to divide them into consistent separate windows (see Multiple Plot Windows).
After that we are applying Hough transform and restoring "lost" theta and rho values in the Octave:
%Apply Hough Transform to Find the Candidate Lines
accum = houghtf(im_edge);
theta = -90:90;
diag_length = (size(accum)(1) - 1) / 2;
rho = -diag_length:diag_length;
figure 4, imagesc(theta, rho, accum), title('Hough Accumulator');
According to the houghtf function's docs, it returns only an accumulator with rows corresponding to indices of rho values, and columns - to indices of theta values. How can we restore the original rho and theta values? Well, the number of rho values (rows in the accum matrix variable) goes up to 2*diag_length - 1, where diag_length is the length of the diagonal of the input image. Knowing this, we should restore the diagonal length (it is a reversed action): diag_length = (size(accum)(1) - 1) / 2. Then we can restore rho values, which go from minus diagonal to diagonal: rho = -diag_length:diag_length. With thetas everything is easier - they are in the range of pi*(-90:90)/180, but we will use degrees instead: theta = -90:90. I've added the index for figure as did before and changed the call to imagesc according to its docs - it should be called as imagesc (x, y, img).
After that we use houghpeaks function to get the peaks:
peaks = houghpeaks(accum, 100, 'Threshold', ceil(0.6 * max(accum(:))), 'NHoodSize', [5,5]);
And we use houghlines to get the result line segments (guess there were some errata with variables' names):
line_segs = houghlines(im_edge, theta, rho, peaks, 'FillGap', 50, 'MinLength', 100);
And finally there goes plotting code - it wasn't changed at all, because it worked correctly.
The reason why Octave tells you that rho is undefined is because Matlab's hough function and Octave's houghtf function are not exact equivalents.
Here's the description of the output arguments returned by hough from the corresponding Mathwork's webpage:
The function returns rho, the distance from the origin to the line
along a vector perpendicular to the line, and theta, the angle in
degrees between the x-axis and this vector. The function also returns
the Standard Hough Transform, H, which is a parameter space matrix
whose rows and columns correspond to rho and theta values
respectively.
Octave's houghtf, on the other hand, only returns matrix H:
The result H is an N by M matrix containing the Hough transform. Here,
N is the number different values of r that has been attempted. This is
computed as 2*diag_length - 1, where diag_length is the length of the
diagonal of the input image. M is the number of different values of
theta. These can be set through the third input argument arg. This
must be a vector of real numbers, and is by default pi*(-90:90)/180.
Now, in your script, the only place where you call rho is on line 15, when trying to display the Hough accumulator.
I suggest you instead plot the accumulator this way:
figure, imagesc(H),xlabel('xData'),ylabel('ydata'),title('Hough accumulator')
Let me know if this works for you!
[H] = houghtf(edges);
You have to pass the argument in this manner since the octave returns only a matrix of values. you can't assign three different variables to a matrix.
So, assign a single variable to that and you will get the result.

Image Transformation - Cartesian to Polar, and back again (MATLAB)

I have been using Peter Kovesi's MatLab functions for machine vision (which are outstanding if you aren't aware of them).
I have been transforming images to polar co-ordinates using the polar transform. The function from Peter Kovesi is named 'PolarTrans' and can be found here -
http://www.peterkovesi.com/matlabfns/#syntheticimages
The function beautifully transforms an images into polar co-ordinates. However, I would like the reverse to happen also. Peter Kovesi uses interp2 to transform images, but I can't seem to figure out how to reverse this transform. A requirement of interp2 is that it needs a meshgrid as input.
In short - can you help me reverse the transformation: polar to cartesian. I would like it be accordance with Peter's function - i.e. using the same parameters for coherence.
Dear Swjm,
I am posting my reply here because I do not have space in the comments section.
Firstly, thank you very much indeed for your reply. You have shown me how to invert interp2 - something I thought was impossible. This is a huge step forwards. However your code only maps a small segment of the image. Please see the demo code below to understand what I mean.
clc; clear all; close all;
gauss = fspecial('gauss',64,15);
gauss = uint8(mat2gray(gauss).*255);
[H,W] = size(gauss);
pim = polartrans(gauss,64,360);
cim = carttrans(pim,64,64);
subplot(2,2,1);
imagesc(gauss); colormap(jet);
axis off;
title('Image to be Transformed');
subplot(2,2,2);
imagesc(pim); colormap(jet);
axis off;
title('Polar Representation');
subplot(2,2,3);
imagesc(cim); colormap(jet);
axis off;
title('Back to Cartesian');
subplot(2,2,4);
diff = uint8(gauss) - uint8(cim);
imagesc(diff); colormap(jet);
axis off;
title('Difference Image');
I've had a look at Kovesi's code and this code should perform the reverse transformation. It assumes you used the 'full' shape and 'linear' map parameters in polartrans. Note that polar transforms generally lose resolution at low radial values (and gain resolution at high values), so it won't be lossless even if your polar image has the same dimensions as your original image.
function im = carttrans(pim, nrows, ncols, cx, cy)
[rad, theta] = size(pim); % Dimensions of polar image.
if nargin==3
cx = ncols/2 + .5; % Polar coordinate center, should match
cy = nrows/2 + .5; % polartrans. Defaults to same.
end
[X,Y] = meshgrid(1:ncols, 1:nrows);
[TH,R] = cart2pol(X-cx,Y-cy); % Polar coordinate arrays.
TH(TH<0) = TH(TH<0)+2*pi; % Put angles in range [0, 2*pi].
rmax = max(R(:)); % Max radius.
xi = TH * (theta+1) / 2*pi; % Query array for angles.
yi = R * rad / (rmax-1) + 1; % Query array for radius.
pim = [pim pim(:,1)]; % Add first col to end of polar image.
[pX,pY] = meshgrid(1:theta+1, 1:rad);
im = interp2(pX, pY, pim, xi, yi);

How to change an image from Cartesian to Polar coordinates in Matlab?

I am trying to convert the pixels of an image from x-y coordinate to polar coordinate and I have problem with it, as I want to code the function by myself.
Here is the code I did so far:
function [ newImage ] = PolarCartRot
% read and show the image
image= imread('1.jpg');
%%imshow(image);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%change to polar coordinate
[x y z]= size(image);
r = sqrt(x*x+y*y);
theta = atan2(y,x);
for i =0:r
for j= 0:theta
newpixel = [i; j];
newImage(newpixel(1), newpixel(2),:) = image(i,j,:);
end
end
figure;
imshow (newImage);
It is not quite clear what you are trying to do, which is why I am making my own example...
So given an image, I am converting the pixel x/y coordinates from Cartesian to polar with CART2POL.
In the first figure, I am showing the locations of the points, and in the second, I plot both the original image and the one with polar coordinates.
Note that I am using the WARP function from the Image Processing Toolbox. Under the hood, it uses the SURF/SURFACE function to display a texture-mapped image.
% load image
load clown;
img = ind2rgb(X,map);
%img = imread(...); % or use any other image
% convert pixel coordinates from cartesian to polar
[h,w,~] = size(img);
[X,Y] = meshgrid(1:w,1:h);
[theta,rho] = cart2pol(X, Y);
Z = zeros(size(theta));
% show pixel locations (subsample to get less dense points)
XX = X(1:8:end,1:4:end);
YY = Y(1:8:end,1:4:end);
tt = theta(1:8:end,1:4:end);
rr = rho(1:8:end,1:4:end);
subplot(121), scatter(XX(:),YY(:),3,'filled'), axis ij image
subplot(122), scatter(tt(:),rr(:),3,'filled'), axis ij square tight
% show images
figure
subplot(121), imshow(img), axis on
subplot(122), warp(theta, rho, Z, img), view(2), axis square
EDIT
As I originally stated, the question is not clear. You have to describe the mapping you want in a well defined manner...
For one you need to think about where the origin is located before converting to polar coordinates. The previous example assume the origin to be the axes base at (0,0). Suppose you want to take the center of the image (w/2,h/2) as origin, then you would do this instead:
[X,Y] = meshgrid((1:w)-floor(w/2), (1:h)-floor(h/2));
with the rest of the code unchanged. To better illustrate the effect, consider a source image with concentric circles drawn in Cartesian coordinates, and notice how they map to straight lines in polar coordinates when using the center of the circles as origin:
EDIT
Here is another example of how to display an image in polar coordinates as requested in the comments. Note that we perform the mapping in the inverse direction pol2cart:
[h,w,~] = size(img);
s = min(h,w)/2;
[rho,theta] = meshgrid(linspace(0,s-1,s), linspace(0,2*pi));
[x,y] = pol2cart(theta, rho);
z = zeros(size(x));
subplot(121), imshow(img)
subplot(122), warp(x, y, z, img), view(2), axis square tight off
Again the effect is better show if you feed it an input image with straight lines, and see how they map in polar coordinates (vertical lines become circles, and horizontal lines become rays emanating from the origin):