Cross-Correlation in Frequency and Spatial domain - Template Matching - matlab

So when I try to find a template B in a big image A, I can do it by finding the maximum of cross-correlation, like this in spatial domain:
% Finding maximum of correlation:
phi = normxcorr2(B,A);
[ymax, xmax] = find(phi == max(phi(:)));
% Find position in original image:
ypeak = ymax - size(B,1);
xpeak = xmax - size(B,2);
But when I want to do it in frequency domain, I get wrong results:
% Calculate correlation in frequency domain:
Af = fft2(A);
Bf = fft2(B, size(A,1), size(A,2));
phi2f = conj(Af)'*Bf;
% Inverse fft to get back to spatial domain:
phi2 = real(ifft(fftshift(phi2f)));
% Now we have correlation matrix, excatly the same as calculated in
% the spatial domain.
[ymax2, xmax2] = find(phi2 == max(phi2(:)));
I don't understand what I'm doing wrong in the frequency domain. I've tried it without fftshift, it gives a different result, albeit a wrong one still. How can I do this correctly?

This should do the trick:
t = imread('cameraman.tif');
a = imtranslate(t, [15, 25]);
% Determine padding size in x and y dimension
size_t = size(t);
size_a = size(a);
outsize = size_t + size_a - 1;
% Determine 2D cross correlation in Fourier domain
Ft = fft2(t, outsize(1), outsize(2));
Fa = fft2(a, outsize(1), outsize(2));
c = abs( fftshift( ifft2(Fa .* conj(Ft))) );
% Find peak
[max_c, imax] = max(abs(c(:)));
[ypeak, xpeak] = ind2sub(size(c), imax(1));
% Correct found peak location for image size
corr_offset = round([(ypeak-(size(c, 1)+1)/2) (xpeak-(size(c, 2)+1)/2)]);
% Write out offsets
y_offset = corr_offset(1)
x_offset = corr_offset(2)

Related

How can I rotate a plot in MATLAB?

I want to rotate the plot scatterplot(rxSig) (shown below) 8 degrees, for example.
(the group of the red dots in the photo)
it's not looks like a regular plot and I didn't found a relevant information for that.
Expected Result: (with rotation)
Plot without rotation:
R = 1000.0;
freq = 28*1e9;
T = 20.0;
lwd = 0.5;
F = fogpl(R,freq,T,lwd);
P = 101300.0;
W = 7.5;
G = gaspl(R,freq,T,P,W);
RR=[0.75,1.75,2.5,3];
for irr=1:length(RR)
R = rainpl(10000,freq,RR(irr));
L=R+F+G;
end
M = 64; % Modulation order
k = log2(M); % Bits per symbol
EbNoVec = (0:25)'; % Eb/No values (dB)
numSymPerFrame = 1000;
for n = 1:length(EbNoVec)
% Convert Eb/No to SNR
snrdB = EbNoVec(n) + 10*log10(k)-L(1);
% Reset the error and bit counters
numErrs = 0;
numBits = 0;
while numErrs < 200 && numBits < 1e8
% Generate binary data and convert to symbols
dataIn = randi([0 1],numSymPerFrame,k);
dataSym = bi2de(dataIn);
% QAM modulate using 'Gray' symbol mapping
txSig = qammod(dataSym,M);
% Pass through AWGN channel
rxSig = awgn(txSig,snrdB,'measured');
% Demodulate the noisy signal
rxSym = qamdemod(rxSig,M);
% Convert received symbols to bits
dataOut = de2bi(rxSym,k);
% Calculate the number of bit errors
nErrors = biterr(dataIn,dataOut);
% Increment the error and bit counters
numErrs = numErrs + nErrors;
numBits = numBits + numSymPerFrame*k;
end
% Estimate the BER
berEst(n) = numErrs/numBits;
end
berTheory = berawgn(EbNoVec,'qam',M);
semilogy(EbNoVec,berEst,'*')
hold on
semilogy(EbNoVec,berTheory)
grid
legend('Estimated BER with our attenuation function','Theoretical Matlab BER')
xlabel('Eb/No (dB)')
ylabel('Bit Error Rate')
scatterplot(rxSig)
I combined both my suggestions to create the following code.
% Extract data points from current figure
h = findobj(gca,'Type','line');
x_org=get(h,'Xdata');
y_org=get(h,'Ydata');
points = [x_org; y_org]';
% to rotate 8 degree counterclockwise
theta = 8;
% Rotation matrix
R = [cosd(theta) -sind(theta); sind(theta) cosd(theta)];
% Rotate points
points_rot = R*points';
figure(3)
plot(points_rot(1,:), points_rot(2,:), '.');
Adding this to the end of your code results in the following figure:

Unexpected result when calculating mean curvature in MatLab

I am running simulations of a protein/membrane system, and want to quantify the degree of membrane deformation. I have averaged the membrane surface on a grid during the simulation, which results in a text file with three columns, containing the x, y, and z points of the membrane. I then convert this information to a mesh surface in matlab, which I then use to calculate the gaussian and/or mean curvature. The problem is, I'm getting similar values at the very beginning of the simulation, when the surface (membrane) is very flat, and at the end, when it is completely deformed. Unless I'm misunderstanding what curvature is, this is not correct and I believe I am doing something wrong in the matlab portion of this process. Here's the script where I loop over many frames (each of which is a different file containing x,y,z coordinates of the averaged membrane) and convert it to a mesh:
https://pastebin.com/reqWAz01
for i = 0:37
file = strcat('cg-topmem_pos-', num2str(i), '.out');
A = load(file);
x = A(:,1);
y = A(:,2);
z = A(:,3);
xv = linspace(min(x), max(x), 20);
yv = linspace(min(y), max(y), 20);
[X,Y] = meshgrid(xv, yv);
Z = griddata(x,y,z,X,Y);
[K,H,Pmax,Pmin] = surfature(X,Y,Z);
M = max(max(H))
if i == 0
fileID = fopen('Average2-NoTMHS-5nmns.txt', 'a');
fprintf(fileID, '%f %f\n',M);
fclose(fileID);
else
fileID = fopen('Average2-NoTMHS-5nmns.txt', 'a');
fprintf(fileID, '\n%f %f\n',M);
fclose(fileID);
end
end
Then using the following calculates curvature:
https://pastebin.com/5D21PdBQ
function [K,H,Pmax,Pmin] = surfature(X,Y,Z),
% SURFATURE - COMPUTE GAUSSIAN AND MEAN CURVATURES OF A SURFACE
% [K,H] = SURFATURE(X,Y,Z), WHERE X,Y,Z ARE 2D ARRAYS OF POINTS ON THE
% SURFACE. K AND H ARE THE GAUSSIAN AND MEAN CURVATURES, RESPECTIVELY.
% SURFATURE RETURNS 2 ADDITIONAL ARGUMENTS,
% [K,H,Pmax,Pmin] = SURFATURE(...), WHERE Pmax AND Pmin ARE THE MINIMUM
% AND MAXIMUM CURVATURES AT EACH POINT, RESPECTIVELY.
% First Derivatives
[Xu,Xv] = gradient(X);
[Yu,Yv] = gradient(Y);
[Zu,Zv] = gradient(Z);
% Second Derivatives
[Xuu,Xuv] = gradient(Xu);
[Yuu,Yuv] = gradient(Yu);
[Zuu,Zuv] = gradient(Zu);
[Xuv,Xvv] = gradient(Xv);
[Yuv,Yvv] = gradient(Yv);
[Zuv,Zvv] = gradient(Zv);
% Reshape 2D Arrays into Vectors
Xu = Xu(:); Yu = Yu(:); Zu = Zu(:);
Xv = Xv(:); Yv = Yv(:); Zv = Zv(:);
Xuu = Xuu(:); Yuu = Yuu(:); Zuu = Zuu(:);
Xuv = Xuv(:); Yuv = Yuv(:); Zuv = Zuv(:);
Xvv = Xvv(:); Yvv = Yvv(:); Zvv = Zvv(:);
Xu = [Xu Yu Zu];
Xv = [Xv Yv Zv];
Xuu = [Xuu Yuu Zuu];
Xuv = [Xuv Yuv Zuv];
Xvv = [Xvv Yvv Zvv];
% First fundamental Coeffecients of the surface (E,F,G)
E = dot(Xu,Xu,2);
F = dot(Xu,Xv,2);
G = dot(Xv,Xv,2);
m = cross(Xu,Xv,2);
p = sqrt(dot(m,m,2));
n = m./[p p p];
% Second fundamental Coeffecients of the surface (L,M,N)
L = dot(Xuu,n,2);
M = dot(Xuv,n,2);
N = dot(Xvv,n,2);
[s,t] = size(Z);
% Gaussian Curvature
K = (L.*N - M.^2)./(E.*G - F.^2);
K = reshape(K,s,t);
% Mean Curvature
H = (E.*N + G.*L - 2.*F.*M)./(2*(E.*G - F.^2));
H = reshape(H,s,t);
% Principal Curvatures
Pmax = H + sqrt(H.^2 - K);
Pmin = H - sqrt(H.^2 - K);
Any help would be greatly appreciated. I'm afraid that there is some issue between how the mesh is created and how curvature is calculated, but I am not matlab literate and could use some help. Thanks very much.

(Fourier Transform) Simple DFT Result differs from FFT

I want to understand the discrete fourier transform by implementing it by myself.
While the result returned by my DFT is not correct the in matlab included version returns the correct frequencies of the original signal.
So the question is, where went I wrong. Is it a math or a implementation problem?
%% Initialisation
samples=2000;
nfft = 1024;
K = nfft / 2 + 1;
c = 264;
e = 330;
t = -1:1/samples:1-1/samples;
[~, N] = size(t);
f = (sin(2*c*pi*t)+cos(2*e*pi*t)).*exp(-pi*(2*t-1).^2);
X = zeros(nfft, 1);
%% Discrete Fourier Transform
if true
for k=1:nfft
for n=1:nfft
X(k) = X(k) + f(n)*exp(-j*2*pi*(k-1)*(n-1)/N);
end
end
else
X=fft(f, nfft);
end
R = abs(X(1:K));
[V,I] = sort(R,'descend');
F1 = samples*(I(1)-1)/nfft;
F2 = samples*(I(2)-1)/nfft;
disp(F1)
disp(F2)
plot(1:K, R, 1:K, real(X(1:K)), 1:K, imag(X(1:K)))
The issue lies in the number of samples for which the transform is done.
Xall = fft(f);
plot(abs(Xall(1:500)),'b');
hold on
plot(abs(X(1:500)),'r');
What you compute matches the result from the FFT done on all samples (i.e. with 4000 real samples in and 4000 complex values out).
Now, if you read the documentation of FFT with doc fft you will see that the signal is truncated if the output size is smaller than the input size. If you try:
Y = zeros(nfft, 1);
for k=1:nfft
for n=1:nfft
Y(k) = Y(k) + f(n)*exp(-1j*2*pi*(k-1)*(n-1)/nfft);
end
end
Y2 = fft(f(:),nfft); %make it a column
abs(sum(Y-Y2)) %6.0380e-12 , result within precision of the double float format

Plot the phase structure function of a phase screen by definition

I have already had a phase screen (a 2-D NxN matrix and LxL in size scale, ex: N = 256, L = 2 meters).
I would like to find phase structure function - D(r) defined by D(delta(r)) = <[x(r)-x(r+delta(r))]^2> (<.> is ensemble averaging, r is position in phase screen in meter, x is phase value at a point in phase screen, delta(r) is variable and not fix) in Matlab program. Do you have any suggestion for my purpose?
P/S: I tried to calculate D(r) via the autocorrelation (is defined as B(r)), but this calculation still remaining some approximations. Therefore, I want to calculate precisely the result of D(r). May you please see this image to better understand the definition of D(r) and B(r). Below is my function code to calculate B(r).
% Code copied from "Numerical Simulation of Optical Wave Propagation with Examples in Matlab",
% by Jason D. Schmidt, SPIE Press, SPIE Vol. No.: PM199
% listing 3.7, page 48.
% (Schmidt defines the ft2 and ift2 functions used in this code elswhere.)
function D = str_fcn2_ft(ph, mask, delta)
% function D = str_fcn2_ft(ph, mask, delta)
N = size(ph, 1);
ph = ph .* mask;
P = ft2(ph, delta);
S = ft2(ph.^2, delta);
W = ft2(mask, delta);
delta_f = 1/(N*delta);
w2 = ift2(W.*conj(W), delta_f);
D = 2 * ft2(real(S.*conj(W)) - abs(P).^2, delta) ./ w2 .*mask;`
%fire run
N = 256; %number of samples
L = 16; %grid size [m]
delta = L/N; %sample spacing [m]
F = 1/L; %frequency-domain grid spacing[1/m]
x = [-N/2 : N/2-1]*delta;
[x y] = meshgrid(x);
w = 2; %width of rectangle
%A = rect(x/2).*rect(y/w);
A = lambdaWrapped;
%A = phz;
mask = ones(N);
%perform digital structure function
C = str_fcn2_ft(A, mask, delta);
C = real(C);
One way of directly computing this function D(r) is through random sampling: you pick two random points on your screen, determine their distance and phase difference squared, and update an accumulator:
phi = rand(256,256)*(2*pi); % the data, phase
N = size(phi,1); % number of samples
L = 16; % grid size [m]
delta = L/N; % sample spacing [m]
D = zeros(1,sqrt(2)*N); % output function
count = D; % for computing mean
for n = 1:1e6 % find a good amount of points here, the more points the better the estimate
coords = randi(N,2,2);
r = round(norm(coords(1,:) - coords(2,:)));
if r<1
continue % skip if the two coordinates are the same
end
d = phi(coords(1,1),coords(1,2)) - phi(coords(2,1),coords(2,2));
d = mod(abs(d),pi); % you might not need this, depending on how A is constructed
D(r) = D(r) + d.^2;
count(r) = count(r) + 1;
end
I = count > 0;
D(I) = D(I) ./ count(I); % do not divide by 0, some bins might not have any samples
I = count < 100;
D(I) = 0; % ignore poor estimates
r = (1:length(D)) * delta;
plot(r,D)
If you need even more precision, consider interpolating. Compute random coordinates as floating-point values, and interpolate the phase to get the values in between samples. D then needs to be longer, indexed as round(r*10) or something like that. You will need many more random samples to fill up that much larger accumulator.

Harris Feature Detection is not accurate

I have implemented Harris feature detection algorithm and the results are not accurate as compared to using the inbuilt function of Matlab: corner(I,'Harris'). Any ideas why so? Or am i missing something in it?
Results of my code:
im=imread('D:\lena_256.pgm');
im=im2double(im);
% im = double(im(:,:,1));
sigma = 2;k = 0.04;
% derivative masks
s_D = 0.7*sigma;
x = -round(3*s_D):round(3*s_D);
dx = x .* exp(-x.*x/(2*s_D*s_D)) ./ (s_D*s_D*s_D*sqrt(2*pi));
dy = dx';
% image derivatives
Ix = conv2(im, dx, 'same');
Iy = conv2(im, dy, 'same');
% sum of the Auto-correlation matrix
s_I = sigma;
g = fspecial('gaussian',max(1,fix(6*s_I+1)), s_I);
Ix2 = conv2(Ix.^2, g, 'same'); % Smoothed squared image derivatives
Iy2 = conv2(Iy.^2, g, 'same');
Ixy = conv2(Ix.*Iy, g, 'same');
% interest point response
cim = (Ix2.*Iy2 - Ixy.^2) - k*(Ix2 + Iy2).^2; % Original Harris measure.
%cim=(Ix2.*Iy2 - Ixy.^2)./(Ix2 + Iy2); % harmonic mean
% find local maxima on 3x3 neighborgood
[r,c,max_local] = findLocalMaximum(cim,3*s_I);
% set threshold 1% of the maximum value
t = 0.005*max(max_local(:));
% find local maxima greater than threshold
[r,c] = find(max_local>=t);
% build interest points
points = [r,c];
figure, imshow(im),title('Harris Feature Points');
hold on
plot(points(:,1),points(:,2),'r*');
function [row,col,max_local] = findLocalMaximum(val,radius)
mask = fspecial('disk',radius)>0;
val2 = imdilate(val,mask);
index = val==val2;
[row,col] = find(index==1);
max_local = zeros(size(val));
max_local(index) = val(index);
end
Results using inbuilt corner() function: