Animation of Conformal Mappings - matlab

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

Related

Error plotting spherical harmonics in MATLAB: Grid arrays must have NDGRID structure

I am trying to use the spherical harmonics to represent a perturbation of a spherical object in an acoustic and fluid flow in 3D.
So far, I have been able to use a 2D perturbation on a 3D spherical object, however, I would like to extend that.
The current code represents a 3D sphere with a 2D perturbation, so the perturbation is only in x and y:
clearvars; clc; close all;
Nx = 128;
Ny = 128;
Nz = 128;
Lx =128;
Ly = 128;
Lz = 128;
xi = (0:Nx-1)/Nx*2*pi;
xi_x = 2*pi/Lx;
x = xi/xi_x;
yi = (0:Ny-1)/Ny*2*pi;
yi_y = 2*pi/Ly;
y = yi/yi_y;
zi = (0:Nz-1)/Nz*2*pi;
zi_z = 2*pi/Lz;
z = zi/zi_z;
[X,Y,Z] = meshgrid(x,y,z);
A = 2*pi / Lx;
B = 2*pi / Ly;
C = 2*pi / Lz;
x0 = 64;
y0 = 64;
z0 = 64;
rx0 = 20;
ry0 = 20;
rz0 = 20;
p = 3;
b = 0.1; % pert amplitude
c = 12;
d = 1;
a = 4;
theta = atan2(Y -y0, X-x0) - (pi/c);
p0 = ((X-x0) .* (X-x0)) /(rx0 * rx0) + ((Y-y0) .* (Y-y0))/(ry0 * ry0) + ((Z-z0) .* (Z-z0))/(rz0 * rz0);
Test =d + a * exp((-1. * p0 .* (1 - b .* cos(c * theta))).^p) ;
figure
isosurface(X,Y,Z,Test);
shading flat;
grid on;
Which returns the isosurface:
However, I would like to achieve something similar to this plot (perturbation in z as well):
This is my attempt using spherical harmonics to reproduce the above picture:
clearvars; clc; close all;
%in spherical coord
%calculate r
Nx = 128;
Ny = 128;
Nz = 128;
Lx =128;
Ly = 128;
Lz = 128;
xi = (0:Nx-1)/Nx*2*pi;
xi_x = 2*pi/Lx;
x = xi/xi_x;
yi = (0:Ny-1)/Ny*2*pi;
yi_y = 2*pi/Ly;
y = yi/yi_y;
zi = (0:Nz-1)/Nz*2*pi;
zi_z = 2*pi/Lz;
z = zi/zi_z;
r = sqrt(x.^2 + y.^2 + z.^2);
% Create the grid
delta = pi/127;
%Taking for instance l=1, m=-1 you can generate this harmonic on a (azimuth, elevation) grid like this:
azimuths = 0 : delta : pi;
elevations = 0 : 2*delta : 2*pi;
[R, A, E] = ndgrid(r, azimuths, elevations); %A is phi and E is theta
H = 0.25 * sqrt(3/(2*pi)) .* exp(-1j*A) .* sin(E) .* cos(E);
%transform the grid back to cartesian grid like this:
%can also add some radial distortion to make things look nicer:
%the radial part depends on your domain
X = r .* cos(A) .* sin(E);
Y = r .* sin(A) .* sin(E);
Z = r .* cos(E);
%parameters
x0 = 64;
y0 = 64;
z0 = 64;
rx0 = 20;
ry0 = 20;
rz0 = 20;
p = 3;
b = 0.1; % pert amplitude
%c = 12;
d = 1;
a = 4;
p0 = ((X-x0) .* (X-x0)) /(rx0 * rx0) + ((Y-y0) .* (Y-y0))/(ry0 * ry0) + ((Z-z0) .* (Z-z0))/(rz0 * rz0);
Test1 =d + a * exp((-1. * p0 .*H).^p) ;
figure
isosurface(X,Y,Z,real(Test1)); %ERROR
This gives me the following error:
Error using griddedInterpolant
Grid arrays must have NDGRID structure.
Is the issue in the way I am setting up the spherical harmonics? or the functional form of Test1?? Thanks
I think the problem is that you've created a NDGrid in the second code. In the first code that worked you created a meshgrid.
isosurface expects a grid in meshgrid format and transforms it later into an NDGrid format with permute just for the usage of the griddedInterpolant function. By the input of an NDGrid this operation will fail.
Why did you switch to creating a NDGrid? Did you get the same error when using meshgrid?
EDIT
OK, new theory: I think the problem is the grid itsself. Read the documentation on ndgrid for more information but for short: A NDGrid format is a completely rectangular grid where all nodes are exclusivly surrounded by 90° angles. By spanning up a grid with ndgrid(r, azimuths, elevations) or meshgrid(r, azimuths, elevations) you are getting this rectangular grid but of course this grid is meaningless because r, azimuths and elevations represent spherical coordinates. By later converting R, A and E into the carthesian coordinates X, Y and Z you get a propper spherical grid but the grid isn't a NDGrid structure anymore since it's not rectangular anymore.
So you have to find a workaround to calculate with your spherical grid.
Maybe you can use another function to visualize your data that dosn't take any grid format as input
Or maybe you can try working with a rectangular cartesian grid by setting all values outside the sphere to 0. (You have to refine your grid accordingly to achieve a good estimation of the sphere)

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

I want to make panorama image but it is showing the error message Undefined function 'imageSet' for input arguments of type 'char'

Undefined function 'imageSet' for input arguments of type 'char'.
Error in build (line 3)
buildingScene = imageSet(buildingDir);
% Load images.
buildingDir = fullfile(toolboxdir('vision'), 'visiondata', 'building');
buildingScene = imageSet(buildingDir);
% Display images to be stitched
montage(buildingScene.ImageLocation)
% Read the first image from the image set.
I = read(buildingScene, 1);
% Initialize features for I(1)
grayImage = rgb2gray(I);
points = detectSURFFeatures(grayImage);
[features, points] = extractFeatures(grayImage, points);
% Initialize all the transforms to the identity matrix. Note that the
% projective transform is used here because the building images are fairly
% close to the camera. Had the scene been captured from a further distance,
% an affine transform would suffice.
tforms(buildingScene.Count) = projective2d(eye(3));
% Iterate over remaining image pairs
for n = 2:buildingScene.Count
% Store points and features for I(n-1).
pointsPrevious = points;
featuresPrevious = features;
% Read I(n).
I = read(buildingScene, n);
% Detect and extract SURF features for I(n).
grayImage = rgb2gray(I);
points = detectSURFFeatures(grayImage);
[features, points] = extractFeatures(grayImage, points);
% Find correspondences between I(n) and I(n-1).
indexPairs = matchFeatures(features, featuresPrevious, 'Unique', true);
matchedPoints = points(indexPairs(:,1), :);
matchedPointsPrev = pointsPrevious(indexPairs(:,2), :);
% Estimate the transformation between I(n) and I(n-1).
tforms(n) = estimateGeometricTransform(matchedPoints, matchedPointsPrev,...
'projective', 'Confidence', 99.9, 'MaxNumTrials', 2000);
% Compute T(1) * ... * T(n-1) * T(n)
tforms(n).T = tforms(n-1).T * tforms(n).T;
end
avgXLim = mean(xlim, 2);
[~, idx] = sort(avgXLim);
centerIdx = floor((numel(tforms)+1)/2);
centerImageIdx = idx(centerIdx);
Tinv = invert(tforms(centerImageIdx));
for i = 1:numel(tforms)
tforms(i).T = Tinv.T * tforms(i).T;
end
for i = 1:numel(tforms)
[xlim(i,:), ylim(i,:)] = outputLimits(tforms(i), [1 imageSize(2)], [1 imageSize(1)]);
end
% Find the minimum and maximum output limits
xMin = min([1; xlim(:)]);
xMax = max([imageSize(2); xlim(:)]);
yMin = min([1; ylim(:)]);
yMax = max([imageSize(1); ylim(:)]);
% Width and height of panorama.
width = round(xMax - xMin);
height = round(yMax - yMin);
% Initialize the "empty" panorama.
panorama = zeros([height width 3], 'like', I);
Step 4 - Create the Panorama
Use imwarp to map images into the panorama and use vision.AlphaBlender to overlay the images together.
blender = vision.AlphaBlender('Operation', 'Binary mask', ...
'MaskSource', 'Input port');
% Create a 2-D spatial reference object defining the size of the panorama.
xLimits = [xMin xMax];
yLimits = [yMin yMax];
panoramaView = imref2d([height width], xLimits, yLimits);
% Create the panorama.
for i = 1:buildingScene.Count
I = read(buildingScene, i);
% Transform I into the panorama.
warpedImage = imwarp(I, tforms(i), 'OutputView', panoramaView);
% Create an mask for the overlay operation.
warpedMask = imwarp(ones(size(I(:,:,1))), tforms(i), 'OutputView', panoramaView);
% Clean up edge artifacts in the mask and convert to a binary image.
warpedMask = warpedMask >= 1;
% Overlay the warpedImage onto the panorama.
panorama = step(blender, panorama, warpedImage, warpedMask);
end
figure
imshow(panorama)
imageSet requires the Computer Vision Toolbox from MATLAB R2014b or higher. See the release notes from the Computer Vision Toolbox here: http://www.mathworks.com/help/vision/release-notes.html#R2014b
If you have R2014a or lower, imageSet does not come with your distribution. The only option you have is to upgrade your MATLAB distribution. Sorry if this isn't what you wanted to hear!

Motion vectors calculation

I am working on the following code:
filename = 'C:\li_walk.avi';
hVidReader = vision.VideoFileReader(filename, 'ImageColorSpace', 'RGB','VideoOutputDataType', 'single');
hOpticalFlow = vision.OpticalFlow('OutputValue', 'Horizontal and vertical components in complex form', 'ReferenceFrameDelay', 3);
hMean1 = vision.Mean;
hMean2 = vision.Mean('RunningMean', true);
hMedianFilt = vision.MedianFilter;
hclose = vision.MorphologicalClose('Neighborhood', strel('line',5,45));
hblob = vision.BlobAnalysis('CentroidOutputPort', false, 'AreaOutputPort', true, 'BoundingBoxOutputPort', true, 'OutputDataType', 'double','MinimumBlobArea', 250, 'MaximumBlobArea', 3600, 'MaximumCount', 80);
herode = vision.MorphologicalErode('Neighborhood', strel('square',2));
hshapeins1 = vision.ShapeInserter('BorderColor', 'Custom', 'CustomBorderColor', [0 1 0]);
hshapeins2 = vision.ShapeInserter( 'Shape','Lines', 'BorderColor', 'Custom','CustomBorderColor', [255 255 0]);
htextins = vision.TextInserter('Text', '%4d', 'Location', [1 1],'Color', [1 1 1], 'FontSize', 12);
sz = get(0,'ScreenSize');
pos = [20 sz(4)-300 200 200];
hVideo1 = vision.VideoPlayer('Name','Original Video','Position',pos);
pos(1) = pos(1)+220; % move the next viewer to the right
hVideo2 = vision.VideoPlayer('Name','Motion Vector','Position',pos);
pos(1) = pos(1)+220;
hVideo3 = vision.VideoPlayer('Name','Thresholded Video','Position',pos);
pos(1) = pos(1)+220;
hVideo4 = vision.VideoPlayer('Name','Results','Position',pos);
% Initialize variables used in plotting motion vectors.
lineRow = 22;
firstTime = true;
motionVecGain = 20;
borderOffset = 5;
decimFactorRow = 5;
decimFactorCol = 5;
while ~isDone(hVidReader) % Stop when end of file is reached
frame = step(hVidReader); % Read input video frame
grayFrame = rgb2gray(frame);
ofVectors = step(hOpticalFlow, grayFrame); % Estimate optical flow
% The optical flow vectors are stored as complex numbers. Compute their
% magnitude squared which will later be used for thresholding.
y1 = ofVectors .* conj(ofVectors);
% Compute the velocity threshold from the matrix of complex velocities.
vel_th = 0.5 * step(hMean2, step(hMean1, y1));
% Threshold the image and then filter it to remove speckle noise.
segmentedObjects = step(hMedianFilt, y1 >= vel_th);
% Thin-out the parts of the road and fill holes in the blobs.
segmentedObjects = step(hclose, step(herode, segmentedObjects));
% Estimate the area and bounding box of the blobs.
[area, bbox] = step(hblob, segmentedObjects);
% Select boxes inside ROI (below white line).
Idx = bbox(:,1) > lineRow;
% Based on blob sizes, filter out objects which can not be cars.
% When the ratio between the area of the blob and the area of the
% bounding box is above 0.4 (40%), classify it as a car.
ratio = zeros(length(Idx), 1);
ratio(Idx) = single(area(Idx,1))./single(bbox(Idx,3).*bbox(Idx,4));
ratiob = ratio > 0.4;
count = int32(sum(ratiob)); % Number of cars
bbox(~ratiob, :) = int32(-1);
% Draw bounding boxes around the tracked cars.
y2 = step(hshapeins1, frame, bbox);
% Display the number of cars tracked and a white line showing the ROI.
y2(22:23,:,:) = 1; % The white line.
y2(1:15,1:30,:) = 0; % Background for displaying count
result = step(htextins, y2, count);
% Generate coordinates for plotting motion vectors.
if firstTime
[R C] = size(ofVectors); % Height and width in pixels
RV = borderOffset:decimFactorRow:(R-borderOffset);
CV = borderOffset:decimFactorCol:(C-borderOffset);
[Y X] = meshgrid(CV,RV);
firstTime = false;
sumu=0;
sumv=0;
end
grayFrame = rgb2gray(frame);
[ra ca na] = size(grayFrame);
ofVectors = step(hOpticalFlow, grayFrame); % Estimate optical flow
ua = real(ofVectors);
ia = ofVectors - ua;
va = ia/complex(0,1);
sumu=ua+sumu;
sumv=va+sumv;
[xa ya]=meshgrid(1:1:ca,ra:-1:1);
% Calculate and draw the motion vectors.
tmp = ofVectors(RV,CV) .* motionVecGain;
lines = [Y(:), X(:), Y(:) + real(tmp(:)), X(:) + imag(tmp(:))];
motionVectors = step(hshapeins2, frame, lines);
% Display the results
step(hVideo1, frame); % Original video
step(hVideo2, motionVectors); % Video with motion vectors
step(hVideo3, segmentedObjects); % Thresholded video
step(hVideo4, result); % Video with bounding boxes
quiver(xa,ya,sumu,sumv)
end
release(hVidReader);
Please help me to understand the following statements of the above code:
ua = real(ofVectors);
ia = ofVectors - ua;
va = ia/complex(0,1);
these are the horizontal (ua) and vertical (va) components of the motion vectors. what real part of the (Ofvectors) will be? please help me in understanding this code segment
When the object hOpticalFlow is constructed in the third line of the code, the OutputValue property is set to 'Horizontal and vertical components in complex form' which has the effect that when you apply the step command to hOpticalFlow and the image (frame), you will not get just the magnitudes of the flowVectors, but complex numbers that represent these planar flow vectors. It is just a compact way for the command to return the information. Once you have the complex numbers in ofVectors, which is the output of the step command, the command
ua = real(ofVectors);
stores the horizontal component of each vector in ua. After the command
ia = ofVectors - ua;
is executed, ia contains the imaginary (i.e., vertical components of the flow vectors) because the real parts in ua are subtracted from the complex numbers in ofVectors. However, you need to get rid of the imaginary units in ia, so you divide by 0+1i. This is what the command
va = ia/complex(0,1);
does.

hough transform for lines

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.