hough transform for lines - matlab

I'm trying to get a Hough transform to work in MATLAB, but I'm having problems. I have a really bad way of detecting peaks that needs to be fixed, but before that I need to be able to reverse the hough transform to create the lines again properly. This is the type of stuff I'm getting right now:
looks like its rotated by 90 degrees, but I'm not sure why. I'm not sure if it's my hough space that's wrong, or if it's the way I dehough and draw the lines. Also could someone help improve my peak detection?
the images used in the code are here
Thank you
%% load a sample image; convert to grayscale; convert to binary
%create 'x' image (works well)
a = eye(255);
b = flipud(eye(255));
x = a + b;
x(128,128) = 1;
%image = rgb2gray(imread('up.png')) < 255;
%image = rgb2gray(imread('hexagon.png')) < 255;
%image = rgb2gray(imread('traingle.png')) < 255;
%%% these work
%image = x;
%image = a;
image = b;
%% set up variables for hough transform
theta_sample_frequency = 0.01;
[x, y] = size(image);
rho_limit = norm([x y]);
rho = (-rho_limit:1:rho_limit);
theta = (0:theta_sample_frequency:pi);
num_thetas = numel(theta);
num_rhos = numel(rho);
hough_space = zeros(num_rhos, num_thetas);
%% perform hough transform
for xi = 1:x
for yj = 1:y
if image(xi, yj) == 1
for theta_index = 1:num_thetas
th = theta(theta_index);
r = xi * cos(th) + yj * sin(th);
rho_index = round(r + num_rhos/2);
hough_space(rho_index, theta_index) = ...
hough_space(rho_index, theta_index) + 1;
end
end
end
end
%% show hough transform
subplot(1,2,1);
imagesc(theta, rho, hough_space);
title('Hough Transform');
xlabel('Theta (radians)');
ylabel('Rho (pixels)');
colormap('gray');
%% detect peaks in hough transform
r = [];
c = [];
[max_in_col, row_number] = max(hough_space);
[rows, cols] = size(image);
difference = 25;
thresh = max(max(hough_space)) - difference;
for i = 1:size(max_in_col, 2)
if max_in_col(i) > thresh
c(end + 1) = i;
r(end + 1) = row_number(i);
end
end
%% plot all the detected peaks on hough transform image
hold on;
plot(theta(c), rho(r),'rx');
hold off;
%% plot the detected line superimposed on the original image
subplot(1,2,2)
imagesc(image);
colormap(gray);
hold on;
for i = 1:size(c,2)
th = theta(c(i));
rh = rho(r(i));
m = -(cos(th)/sin(th));
b = rh/sin(th);
x = 1:cols;
plot(x, m*x+b);
hold on;
end
Cross Posted:
https://dsp.stackexchange.com/questions/1958/help-understanding-hough-transform

If your regenerated image looks rotated by 90 degrees or otherwise flipped, it's likely because the plotting isn't happening as you expect. You can try axis ij; to move the origin of the plot and/or you can reverse your plot command:
plot(m*x+b, x);
As for peak detection, you might want to look at imregionalmax.

Related

gif of sphere with changing radius in Matlab

I wish to generate a .gif file of a sphere that grows in size(radius) over time based on a specified function relating radius and time. I'm having some trouble with how to formulate the animation.
Here is what I have so far:
%% Parameters
dt = 0.05;
time = 0:dt:1;
radius = 1
%% generate sphere
[X, Y, Z] = sphere(25);
X=X*radius;
Y=Y*radius;
Z=Z*radius;
mySphere = surf(X,Y,Z, 'FaceLighting','gouraud');
axis equal
shading interp
mySphere.FaceAlpha = 0.3
view([61 15])
colormap bone
hold on
%% generate gif
filename = 'Sizechange.gif';
for n = 1:20
radius = 1 + time(n)
im = frame2im(getframe(1));
[imind,cm] = rgb2ind(im,256);
if n == 1;
imwrite(imind,cm,filename,'gif', 'Loopcount',inf,'DelayTime',dt);
else
imwrite(imind,cm,filename,'gif','WriteMode','append','DelayTime',dt);
end
end
Here I am trying to get it to go from radius 1 to radius 2 in steps of 0.05.
When I run this however, the gif stays still at 1 and there is no animation.
Any help would be greatly appreciated.
As #cris-luengo said, you should redraw your sphere for each iteration on the radius.
%% Parameters
dt = 0.05;
time = 0:dt:1;
radius = 1 ;
%% generate sphere
[X, Y, Z] = sphere(25);
X=X*radius;
Y=Y*radius;
Z=Z*radius;
%figure;
%mySphere = surf(X,Y,Z, 'FaceLighting','gouraud');
% axis equal
% shading interp
% mySphere.FaceAlpha = 0.3;
% view([61 15])
% colormap bone
% hold on
%% generate gif
filename = 'Sizechange.gif';
figure;
for n = 1:20
radius = 1+ time(n);
%====================================================
X=X*radius;
Y=Y*radius;
Z=Z*radius;
mySphere = surf(X,Y,Z, 'FaceLighting','gouraud');
axis equal
shading interp
mySphere.FaceAlpha = 0.3;
view([61 15])
colormap bone
%====================================================
im = frame2im(getframe(1));
[imind,cm] = rgb2ind(im,256);
if n == 1
imwrite(imind,cm,filename,'gif', 'Loopcount',inf,'DelayTime',dt);
else
imwrite(imind,cm,filename,'gif','WriteMode','append','DelayTime',dt);
end
end

Animation of Conformal Mappings

In this movie the conformal mapping fz = -1/z is visualized as a continuous transformation of an image to the distorted result. How was this made? I am working with conformal mappings in Matlab and I would like to know a method to generate the intermediate steps of an arbitrary conformal transformation in analogy to this movie.
One old trick is to use surface with FaceColor = texturemap with Z=0. A texturemapped surface with Z=0 is basically an image, but it lets you mess with the X&Y coordinates of the underlying grid to do this sort of warping.
You'd want 2D arrays for your XData & YData. Those are the ones you'll manipulate with the mapping. Your ZData would be an array of the same size which was all zeros. Then the CData array would be an image. If you wanted to use a 20x20 grid, it might look something like this:
m = 20;
n = 20;
[x,y] = meshgrid(m,n);
img = imread('myimage.png');
h = surf(x,y,zeros(m,n),img,'FaceColor','texturemap');
Then you can manipulate h.XData and h.YData to animate changing the mapping.
for t = 0:.05:1
[newx, newy] = mymapping(x,y,t);
h.XData = newx;
h.YData = newy;
drawnow
end
With the following code I can generate a sequence of images that could be considered as a transformation or animation using the linear equation (1-t) * 1 + t * (1./(a.*(x+1i.*y))); But it is in no way that what is seen in CH56_Clip4.mov. Additionally t = 0.00 delivers a monochrome result.
[h_i, w_i, ~] = size(img);
% INITIALIZE IN-MESHGRID & NORMALIZE [0 1]
[xi,yi] = meshgrid(linspace(0,w_i+1,w_i),linspace(0,h_i+1,h_i));
xi = (xi/w_i); yi = (yi/h_i);
% INITIALIZE OUT-MESHGRID & NORMALIZE [-1 1]
[xo,yo] = meshgrid(1:w_i, 1:h_i);
xo = (xo/w_i)*2 - 1; yo = (yo/h_i)*2 - 1;
% GENERATE SURFACE
h = surf(xo, yo, zeros(w_i, h_i), img, 'FaceColor', 'texturemap');
% INITIALIZE OUT-IMAGE
img_out_t = zeros(h_i, w_i, 3);
for t = 0.00:0.1:1.0
% DISTORTION, SEPARATE & NORMALIZE [0 1]
fxiy = (1-t) * 1 + t * (1./(1.2.*(xo+1i.*yo)));
h.XData = real(fxiy); xo1 = h.XData;
h.YData = imag(fxiy); yo1 = h.YData;
xo1 = (xo1+1)/2; yo1 = (yo1+1)/2;
% INTERPOLATION
for k = 1:3; img_out_t(:,:,k) = uint8(interp2(xi, yi, img(:,:,k), xo1, yo1, interpol_meth)); end; imwrite(uint8(img_out_t), ['img_out_t_', num2str(t), '.jpg'], 'jpg', 'Quality', 98);
end

How can I make a cylindrical 3D contour plot in Matlab?

I have an axisymmetric flow with m x n grid points in r and z direction and I want to plot the temperature that is stored in a matrix with size mxn in a 3D cylindrical plot as visualized in the link below (My reputation is not high enough to include it as a picture).
I have managed to plot it in 2D (r,z plane) using contour but I would like to add the theta plane for visualization. How can I do this?
You can roll your own with multiple calls to surface().
Key idea is: for each surface: (1) theta=theta1, (2) theta=theta2, (3) z=zmax, (4) z=0, (5) r=rmax, generate a 3D mesh (xx,yy,zz) and the temperature map on that mesh. So you have to think about how to construct each surface mesh.
Edit: completed code is now provided. All magic number and fake data are put at (almost) the top of the code so it's easy to convert it into a general purpose Matlab function. Good luck!
% I have adjusted the range values to show the curved cylinder wall
% display a variable temperature
r = 0:0.1:2.6; % you can also try r = 0:0.1:3.0
z = 0:0.1:10; % you can also try z = 0:0.1:15;
[rr, zz] = meshgrid(r,z);
% fake temperature data
temp = 100 + (10* (3-rr).^0.6) .* (1-((zz - 7.5)/7.5).^6) ;
% visualize in 2D
figure(1);
clf;
imagesc(r,z,temp);
colorbar;
% set cut planes angles
theta1 = 0;
theta2 = pi*135/180;
nt = 40; % angle resolution
figure(2);
clf;
xx1 = rr * cos(theta1);
yy1 = rr * sin(theta1);
h1 = surface(xx1,yy1,zz,temp,'EdgeColor', 'none');
xx2 = rr * cos(theta2);
yy2 = rr * sin(theta2);
h2 = surface(xx2,yy2,zz,temp,'EdgeColor', 'none');
% polar meshgrid for the top end-cap
t3 = linspace(theta1, (theta2 - 2*pi), nt);
[rr3, tt3] = meshgrid(r,t3);
xx3 = rr3 .* cos(tt3);
yy3 = rr3 .* sin(tt3);
zz3 = ones(size(rr3)) * max(z);
temp3 = zeros(size(rr3));
for k = 1:length(r)
temp3(:,k) = temp(end,k);
end
h3 = surface(xx3,yy3,zz3,temp3,'EdgeColor', 'none');
% polar meshgrid for the bottom end-cap
zz4 = ones(size(rr3)) * min(z);
temp4 = zeros(size(rr3));
for k = 1:length(r)
temp4(:,k) = temp(1,k);
end
h4 = surface(xx3,yy3,zz4,temp4,'EdgeColor', 'none');
% generate a curved meshgrid
[tt5, zz5] = meshgrid(t3,z);
xx5 = r(end) * cos(tt5);
yy5 = r(end) * sin(tt5);
temp5 = zeros(size(xx5));
for k = 1:length(z)
temp5(k,:) = temp(k,end);
end
h5 = surface(xx5, yy5, zz5,temp5,'EdgeColor', 'none');
axis equal
colorbar
view(125,25); % viewing angles

Insert random noise in a V slope DEM

With the following code I am generating a V plane with 2 different slopes, 10° and 20° respectively.
% /*
% Assumptions
% */
% resolution [m]
res = 1;
% inclination [deg]
i1 = 10; i2 = 20;
% /*
% DEM -> V shape
% */
% pre-allocate output
testDEM = zeros(513);
% required elevation step [m]
hstep = res*tan(i1*(pi/180));
% elevation start right [m]
k = 513*(2/3)*tan(i1*(pi/180));
% coordinates
q = length(1:513*(2/3));
% initialize
nStep = 0;
for jj = 1:q
testDEM(:,jj) = k-nStep;
nStep = nStep + hstep;
end
% change elevation step
step = res*tan(i2*(pi/180));
% update nStep
nStep = step;
% elevation start left [m]
start = testDEM(end,q);
for jj = q+1:513
testDEM(:,jj) = start + nStep;
nStep = nStep + step;
end
testDEM = testDEM(1:507,1:507);
%//Plot test DEM
f_tSlope = figure();
set(gca,'PlotBoxAspectRatio',[1 1 1]);
surf(testDEM, 'EdgeColor', 'none')
colormap jet;
hb = colorbar('location','eastoutside');
hb.Label.String = '[m]';
hb.Label.Rotation = 0;
hb.Label.HorizontalAlignment = 'Left';
With the following I'm adding noise in every location
sigma = 1;
testDEM = testDEM + sigma*randn(size(testDEM));
But what I'd like instead is to add random noise in random location, not everywhere. How can I do it?
Thanks in advance
How about this:
N_locations = 100; % no. of locations to add random noise
% randomize 'N_locations' linear indecies in 'testDEM':
noise_location = randi(numel(testDEM),N_locations,1);
% add the noise:
testDEM(noise_location) = testDEM(noise_location)+sigma*randn(N_locations,1);
This will randomize N_locations random locations on the map, and apply different random noise to each of them.
If you prefer to add the same noise to all random locations, just write sigma*randn, without the parenthesis after it.
For small N_locations this should suffice. However, if you want to make sure you don't pick the same location twice, or N_locations is large, you can set noise_location like this:
noise_location = randperm(numel(testDEM),N_locations);
so you'll have only non-repeating values of indices in testDEM.
This code adds noise with 0.5 probability
testDEM = testDEM + sigma*randn(size(testDEM)) .* (rand(size(testDEM)) > 0.5);

How to plot a graph of a custom surface in Matlab?

I would like to plot the surface of this function in Matlab:
w=(m*(1-p))/(h-1+m*(1-p))
Where
h=0.98;
P=[0.05:0.001:0.98];
M=[0:0.001:1];
The graph should look like this:
I tried to implement the graphing function as:
h=0.98;
P=[0.05:0.001:0.98];
M=[0:0.001:1];
W=[];
for i=1:size(P, 2)
for j=1:size(M, 2)
p=P(i);
m=M(j);
w=(m*(1-p))/(h-1+m*(1-p));
if w>1000
w=1000;
end
if w<0
w=0;
end
W(i, j) = w;
end
end
mesh(M, P, W);
But since the function changes rapidly around the boundary condition, my graph ended up looking like this:
How can I smooth out the curve and give it a nice, uniform grid like in the first picture?
Here's a way to do what you want. See comments in the code for more information.
%% //Definitions
w = #(h,m,p)(m.*(1-p))./(h-1+m.*(1-p)); %// w as a function handle
w_min = 0; w_max = 10; %// For plots
cMap = hot(200); cMap = cMap(floor(0.5*length(cMap)):ceil(0.7*length(cMap)),:);
h = 0.98;
m_start = 0; m_end = 1; m_step = [0.02 0.01 0.001];
p_start = 0.05; p_end = 0.98; p_step = [0.1 0.01 0.001];
%// Definitions of the mesh used in plotting (same for all charts)
mesh_m_step = 0.05; mesh_p_step = 0.05;
[meshM,meshP] = meshgrid(m_start:mesh_m_step:m_end,p_start:mesh_p_step:p_end);
meshW = w(h,meshM,meshP);
%% //Evaluation and plotting:
figure(); set(gcf,'Position',[240,500,1391,376]); subplot(1,3,1);
for ind1 = 1:3
%% // Evaluate equation
[MM,PP] = meshgrid(m_start:m_step(ind1):m_end,p_start:p_step(ind1):p_end);
WW = w(h,MM,PP);
%% // Plot
subplot(1,3,ind1);
surf(MM,PP,WW,'EdgeColor','none'); view([45,45]);
hold on; mesh(meshM,meshP,meshW,'EdgeColor','k','FaceColor','none');
colormap(cMap); %// Fix the colormap
zlim([w_min,w_max]); caxis(zlim) %// Modify zlim
end
Which results in: