How to vectorize calculation of homogenous transformation matrix/tensor? - for-loop

For my simulation I need to calculate many transformation matrices therefore I would like to vectorize a for-loop that I'm using right now.
Is there a way to vectorize the existing for-loop or do I probably need another approach in calculating the vectors and matrices before?
I prepared a little working example:
n_dim = 1e5;
p1_3 = zeros(3,n_dim); % translationvector (no trans.) [3x100000]
tx = ones(1,n_dim)*15./180*pi; % turn angle around x-axis (fixed) [1x100000]
ty = zeros(1,n_dim); % turn angle around y-axis (no turn) [1x100000]
tz = randi([-180 180], 1, n_dim)./180*pi; % turn angle around z-axis (different turn) [1x100000]
hom = [0 0 0 1].*ones(n_dim,4); % vector needed for homogenous transformation [100000x4]
% calculate sin/cosin values for rotation [100000x1 each]
cx = cos(tx)';
sx = sin(tx)';
cy = cos(ty)';
sy = sin(ty)';
cz = cos(tz)';
sz = sin(tz)';
% calculate rotation matrix [300000x3]
R_full = [ cy.*cz, -cy.*sz, sy; ...
cx.*sz+sx.*sy.*cz, cx.*cz-sx.*sy.*sz, -sx.*cy; ...
sx.*sz-cx.*sy.*cz, cz.*sx+cx.*sy.*sz, cx.*cy];
% prealocate transformation tensor
T = zeros(4,4,n_dim);
% create transformation tensor here
% T = [R11 R12 R13 p1;
% R21 R22 R23 p2;
% R31 R32 R33 p3;
% 0 0 0 1]
tic
for i = 1:n_dim
T(:,:,i) = [[R_full(i,1), R_full(i,2), R_full(i,3); ...
R_full(n_dim+i,1), R_full(n_dim+i,2), R_full(n_dim+i,3); ...
R_full(2*n_dim+i,1), R_full(2*n_dim+i,2), R_full(2*n_dim+i,3)], p1_3(:,i);
hom(i,:)];
end
toc

Try this:
T = permute(reshape(R_full,n_dim,3,3),[2,3,1]);
T(4,4,:) = 1;
Your method:
Elapsed time is 0.839315 seconds.
This method:
Elapsed time is 0.015389 seconds.

EDIT
I included Florian's answer, and of course he wins.
Are you ready for some crazy indexing foo? Here we go:
clear all;
close all;
clc;
n_dim_max = 200;
t_loop = zeros(n_dim_max, 1);
t_indexing = t_loop;
t_permute = t_loop;
fprintf("---------------------------------------------------------------\n");
for n_dim = 1:n_dim_max
p1_3 = zeros(3,n_dim); % translationvector (no trans.) [3x100000]
tx = ones(1,n_dim)*15./180*pi; % turn angle around x-axis (fixed) [1x100000]
ty = zeros(1,n_dim); % turn angle around y-axis (no turn) [1x100000]
tz = randi([-180 180], 1, n_dim)./180*pi; % turn angle around z-axis (different turn) [1x100000]
hom = [0 0 0 1].*ones(n_dim,4); % vector needed for homogenous transformation [100000x4]
% calculate sin/cosin values for rotation [100000x1 each]
cx = cos(tx)';
sx = sin(tx)';
cy = cos(ty)';
sy = sin(ty)';
cz = cos(tz)';
sz = sin(tz)';
% calculate rotation matrix [300000x3]
R_full = [ cy.*cz, -cy.*sz, sy; ...
cx.*sz+sx.*sy.*cz, cx.*cz-sx.*sy.*sz, -sx.*cy; ...
sx.*sz-cx.*sy.*cz, cz.*sx+cx.*sy.*sz, cx.*cy];
% prealocate transformation tensor
T = zeros(4,4,n_dim);
% create transformation tensor here
% T = [R11 R12 R13 p1;
% R21 R22 R23 p2;
% R31 R32 R33 p3;
% 0 0 0 1]
tic
for i = 1:n_dim
T(:,:,i) = [[R_full(i,1), R_full(i,2), R_full(i,3); ...
R_full(n_dim+i,1), R_full(n_dim+i,2), R_full(n_dim+i,3); ...
R_full(2*n_dim+i,1), R_full(2*n_dim+i,2), R_full(2*n_dim+i,3)], p1_3(:,i);
hom(i,:)];
end
t_loop(n_dim) = toc;
tic
% prealocate transformation tensor
TT = zeros(4, 4);
TT(end) = 1;
TT = repmat(TT, 1, 1, n_dim);
% Crazy index finding.
temp = repmat(1:(3*n_dim):(3*3*n_dim), 3, 1) + n_dim .* ((0:2).' * ones(1, 3));
temp = repmat(temp, 1, 1, n_dim);
t = zeros(1, 1, n_dim);
t(:) = 0:(n_dim-1);
temp = temp + ones(3, 3, n_dim) .* t;
% Direct assignment using crazily found indices.
TT(1:3, 1:3, :) = R_full(temp);
t_indexing(n_dim) = toc;
tic
% prealocate transformation tensor
TTT = zeros(4, 4);
TTT(end) = 1;
TTT = repmat(TTT, 1, 1, n_dim);
TTT(1:3, 1:3, :) = permute(reshape(R_full, n_dim, 3, 3), [2, 3, 1]);
t_permute(n_dim) = toc;
% Check
fprintf("n_dim: %d\n", n_dim);
fprintf("T equals TT: %d\n", (sum(T(:) == TT(:))) == (4 * 4 * n_dim));
fprintf("T equals TTT: %d\n", (sum(T(:) == TTT(:))) == (4 * 4 * n_dim));
fprintf("---------------------------------------------------------------\n");
end
figure(1);
plot(1:n_dim_max, t_loop, 1:n_dim_max, t_indexing, 1:n_dim_max, t_permute);
legend({'Loop', 'Indexing', 'Permute'});
xlabel('Dimension');
ylabel('Elapsed time [s]');
Sorry, the script got lengthy, because it's your initial solution, my solution, (and Florian's solution) and testing script all-in-one. Lazy friday was the reason for me not to split things properly...
How did I get there? Simple "reverse engineering". I took your solution for n_dim = [2, 3, 4] and determined [~, ii] = ismember(T(1:3, 1:3, :), R_full), i.e. the mapping of R_full to T(1:3, 1:3, :). Then, I analyzed the indexing scheme, and found the proper solution to mimic that mapping for arbitrary n_dim. Done! ;-) Yes, I like crazy indexing stuff.

Related

Kaczmarz animation

i am asking for help.. I want to animate the Kaczmarz method on Matlab. It's method allows to find solution of system of equations by the serial projecting solution vector on hyperplanes, which which is given by the eqations of system.
And i want make animation of this vector moving (like the point is going on the projected vectors).
%% System of equations
% 2x + 3y = 4;
% x - y = 2;
% 6x + y = 15;
%%
A = [2 3;1 -1; 6 1];
f = [4; 2; 15];
resh = pinv(A)*f
x = -10:0.1:10;
e1 = (1 - 2*x)/3;
e2 = (x - 2);
e3 = 15 - 6*x;
plot(x,e1)
grid on
%
axis([0 4 -2 2])
hold on
plot(x,e2)
hold on
plot(x,e3)
hold on
precision = 0.001; % точность
iteration = 100; % количество итераций
lambda = 0.75; % лямбда
[m,n] = size(A);
x = zeros(n,1);
%count of norms
for i = 1:m
nrm(i) = norm(A(i,:));
end
for i = 1:1:iteration
j = mod(i-1,m) + 1;
if (nrm(j) <= 0), continue, end;
predx = x;
x = x + ((f(j) - A(j,:)*x)*A(j,:)')/(nrm(j))^2;
p = plot(x);
set(p)
%pause 0.04;
hold on;
if(norm(predx - x) <= precision), break, end
end
I wrote the code for this method, by don't imagine how make the animation, how I can use the set function.
In your code there are a lot of redundant and random pieces. Do not call hold on more than once, it does nothing. Also set(p) does nothing, you want to set some ps properties to something, then you use set.
Also, you are plotting the result, but not the "change". The change is a line between the previous and current, and that is the only reason you'd want to have a variable such as predx, to plot. SO USE IT!
Anyway, this following code plots your algorithm. I added a repeated line to plot in green and then delete, so you can see what the last step does. I also changed the plots in the begging to just plot in red so its more clear what is each of the things.
Change your loop for:
for i = 1:1:iteration
j = mod(i-1,m) + 1;
if (nrm(j) <= 0), continue, end;
predx = x;
x = x + ((f(j) - A(j,:)*x)*A(j,:)')/(nrm(j))^2;
plot([predx(1) x(1)],[predx(2) x(2)],'b'); %plot line
c=plot([predx(1) x(1)],[predx(2) x(2)],'g'); %plot it in green
pause(0.1)
children = get(gca, 'children'); %delete the green line
delete(children(1));
drawnow
% hold on;
if(norm(predx - x) <= precision), break, end
end
This will show:

K-means for color quantization - Code not vectorized

I'm doing this exercise by Andrew NG about using k-means to reduce the number of colors in an image. It worked correctly but I'm afraid it's a little slow because of all the for loops in the code, so I'd like to vectorize them. But there are those loops that I just can't seem to vectorize effectively. Please help me, thank you very much!
Also if possible please give some feedback on my coding style :)
Here is the link of the exercise, and here is the dataset.
The correct result is given in the link of the exercise.
And here is my code:
function [] = KMeans()
Image = double(imread('bird_small.tiff'));
[rows,cols, RGB] = size(Image);
Points = reshape(Image,rows * cols, RGB);
K = 16;
Centroids = zeros(K,RGB);
s = RandStream('mt19937ar','Seed',0);
% Initialization :
% Pick out K random colours and make sure they are all different
% from each other! This prevents the situation where two of the means
% are assigned to the exact same colour, therefore we don't have to
% worry about division by zero in the E-step
% However, if K = 16 for example, and there are only 15 colours in the
% image, then this while loop will never exit!!! This needs to be
% addressed in the future :(
% TODO : Vectorize this part!
done = false;
while done == false
RowIndex = randperm(s,rows);
ColIndex = randperm(s,cols);
RowIndex = RowIndex(1:K);
ColIndex = ColIndex(1:K);
for i = 1 : K
for j = 1 : RGB
Centroids(i,j) = Image(RowIndex(i),ColIndex(i),j);
end
end
Centroids = sort(Centroids,2);
Centroids = unique(Centroids,'rows');
if size(Centroids,1) == K
done = true;
end
end;
% imshow(imread('bird_small.tiff'))
%
% for i = 1 : K
% hold on;
% plot(RowIndex(i),ColIndex(i),'r+','MarkerSize',50)
% end
eps = 0.01; % Epsilon
IterNum = 0;
while 1
% E-step: Estimate membership given parameters
% Membership: The centroid that each colour is assigned to
% Parameters: Location of centroids
Dist = pdist2(Points,Centroids,'euclidean');
[~, WhichCentroid] = min(Dist,[],2);
% M-step: Estimate parameters given membership
% Membership: The centroid that each colour is assigned to
% Parameters: Location of centroids
% TODO: Vectorize this part!
OldCentroids = Centroids;
for i = 1 : K
PointsInCentroid = Points((find(WhichCentroid == i))',:);
NumOfPoints = size(PointsInCentroid,1);
% Note that NumOfPoints is never equal to 0, as a result of
% the initialization. Or .... ???????
if NumOfPoints ~= 0
Centroids(i,:) = sum(PointsInCentroid , 1) / NumOfPoints ;
end
end
% Check for convergence: Here we use the L2 distance
IterNum = IterNum + 1;
Margins = sqrt(sum((Centroids - OldCentroids).^2, 2));
if sum(Margins > eps) == 0
break;
end
end
IterNum;
Centroids ;
% Load the larger image
[LargerImage,ColorMap] = imread('bird_large.tiff');
LargerImage = double(LargerImage);
[largeRows,largeCols,NewRGB] = size(LargerImage); % RGB is always 3
% TODO: Vectorize this part!
largeRows
largeCols
NewRGB
% Replace each of the pixel with the nearest centroid
NewPoints = reshape(LargerImage,largeRows * largeCols, NewRGB);
Dist = pdist2(NewPoints,Centroids,'euclidean');
[~,WhichCentroid] = min(Dist,[],2);
NewPoints = Centroids(WhichCentroid,:);
LargerImage = reshape(NewPoints,largeRows,largeCols,NewRGB);
% for i = 1 : largeRows
% for j = 1 : largeCols
% Dist = pdist2(Centroids,reshape(LargerImage(i,j,:),1,RGB),'euclidean');
% [~,WhichCentroid] = min(Dist);
% LargerImage(i,j,:) = Centroids(WhichCentroid,:);
% end
% end
% Display new image
imshow(uint8(round(LargerImage)),ColorMap)
UPDATE: Replaced
for i = 1 : K
for j = 1 : RGB
Centroids(i,j) = Image(RowIndex(i),ColIndex(i),j);
end
end
with
for i = 1 : K
Centroids(i,:) = Image(RowIndex(i),ColIndex(i),:);
end
I think this may be vectorized further by using linear indexing, but for now I should just focus on the while loop since it takes most of the time.
Also when I tried #Dev-iL's suggestion and replaced
for i = 1 : K
PointsInCentroid = Points((find(WhichCentroid == i))',:);
NumOfPoints = size(PointsInCentroid,1);
% Note that NumOfPoints is never equal to 0, as a result of
% the initialization. Or .... ???????
if NumOfPoints ~= 0
Centroids(i,:) = sum(PointsInCentroid , 1) / NumOfPoints ;
end
end
with
E = sparse(1:size(WhichCentroid), WhichCentroid' , 1, Num, K, Num);
Centroids = (E * spdiags(1./sum(E,1)',0,K,K))' * Points ;
the results were always worse: With K = 16, the first takes 2,414s , the second takes 2,455s ; K = 32, the first takes 4,529s , the second takes 5,022s. Seems like vectorization does not help, but maybe there's something wrong with my code :( .
Replaced
for i = 1 : K
for j = 1 : RGB
Centroids(i,j) = Image(RowIndex(i),ColIndex(i),j);
end
end
with
for i = 1 : K
Centroids(i,:) = Image(RowIndex(i),ColIndex(i),:);
end
I think this may be vectorized further by using linear indexing, but for now I should just focus on the while loop since it takes most of the time.
Also when I tried #Dev-iL's suggestion and replaced
for i = 1 : K
PointsInCentroid = Points((find(WhichCentroid == i))',:);
NumOfPoints = size(PointsInCentroid,1);
% Note that NumOfPoints is never equal to 0, as a result of
% the initialization. Or .... ???????
if NumOfPoints ~= 0
Centroids(i,:) = sum(PointsInCentroid , 1) / NumOfPoints ;
end
end
with
E = sparse(1:size(WhichCentroid), WhichCentroid' , 1, Num, K, Num);
Centroids = (E * spdiags(1./sum(E,1)',0,K,K))' * Points ;
the results were always worse: With K = 16, the first takes 2,414s , the second takes 2,455s ; K = 32, the first took 4,529s , the second took 5,022s. Seems like vectorization did not help in this case.
However, when I replaced
Dist = pdist2(Points,Centroids,'euclidean');
[~, WhichCentroid] = min(Dist,[],2);
(in the while loop) with
Dist = bsxfun(#minus,dot(Centroids',Centroids',1)' / 2 , Centroids * Points' );
[~, WhichCentroid] = min(Dist,[],1);
WhichCentroid = WhichCentroid';
the code ran much faster, especially when K is large (K=32)
Thank you everyone!

MatLab code speed and optimization. How to improve?

Could someone please run this for me and tell me how long it takes for you? It took my laptop 60s. I can't tell if it's my laptop that's crappy or my code. Probably both.
I just started learning MatLab, so I'm not yet familiar with which functions are better than others for specific tasks. If you have any suggestions on how I could improve this code, it would be greatly appreciated.
function gbp
clear; clc;
zi = 0; % initial position
zf = 100; % final position
Ei = 1; % initial electric field
c = 3*10^8; % speed of light
epsilon = 8.86*10^-12; % permittivity of free space
lambda = 1064*10^-9; % wavelength
k = 2*pi/lambda; % wave number
wi = 1.78*10^-3; % initial waist width (minimum spot size)
zr = (pi*wi^2)/lambda; % Rayleigh range
Ri = zi + zr^2/zi; % initial radius of curvature
qi = 1/(1/Ri-1i*lambda/(pi*wi^2)); % initial complex beam parameter
Psii = atan(real(qi)/imag(qi)); % Gouy phase
mat = [1 zf; 0 1]; % transformation matrix
A = mat(1,1); B = mat(1,2); C = mat(2,1); D = mat(2,2);
qf = (A*qi + B)/(C*qi + D); % final complex beam parameter
wf = sqrt(-lambda/pi*(1/imag(1/qf))); % final spot size
Rf = 1/real(1/qf); % final radius of curvature
Psif = atan(real(qf)/imag(qf)); % final Gouy phase
% Hermite - Gaussian modes function
u = #(z, x, n, w, R, Psi) (2/pi)^(1/4)*sqrt(exp(1i*(2*n+1)*Psi)/(2^n*factorial(n)*w))*...
hermiteH(n,sqrt(2)*x/w).*exp(-x.^2*(1/w^2+1i*k/(2*R))-1i*k*z);
% Complex amplitude coefficients function
a = #(n) exp(1i*k*zi)*integral(#(x) Ei.*conj(u(zi, x, n, wi, Ri, Psii)),-2*wi,2*wi);
%----------------------------------------------------------------------------
xlisti = -0.1:1/10000:0.1; % initial x-axis range
xlistf = -0.1:1/10000:0.1; % final x-axis range
nlist = 0:2:20; % modes range
function Eiplot
Efieldi = zeros(size(xlisti));
for nr = nlist
Efieldi = Efieldi + a(nr).*u(zi, xlisti, nr, wi, Ri, Psii)*exp(-1i*k*zi);
end
Ii = 1/2*c*epsilon*arrayfun(#(x)x.*conj(x),Efieldi);
end
function Efplot
Efieldf = zeros(size(xlistf));
for nr = nlist
Efieldf = Efieldf + a(nr).*u(zf, xlistf, nr, wf, Rf, Psif)*exp(-1i*k*zf);
end
If = 1/2*c*epsilon*arrayfun(#(x)x.*conj(x),Efieldf);
end
Eiplot
Efplot
plot(xlisti,real(Ii),xlistf,real(If))
xlabel('x(m)') % x-axis label
ylabel('I(W/m^2)') % y-axis label
end
The cost is coming from the calls to hermiteH -- for every call, this creates a new function using symbolic variables, then evaluates the function at your input. The key to speeding this up is to pre-compute the hermite polynomial functions then evaluate those rather than create them from scratch each time (speedup from ~26 seconds to around 0.75 secs on my computer).
With the changes:
function gbp
x = sym('x');
zi = 0; % initial position
zf = 100; % final position
Ei = 1; % initial electric field
c = 3*10^8; % speed of light
epsilon = 8.86*10^-12; % permittivity of free space
lambda = 1064*10^-9; % wavelength
k = 2*pi/lambda; % wave number
wi = 1.78*10^-3; % initial waist width (minimum spot size)
zr = (pi*wi^2)/lambda; % Rayleigh range
Ri = zi + zr^2/zi; % initial radius of curvature
qi = 1/(1/Ri-1i*lambda/(pi*wi^2)); % initial complex beam parameter
Psii = atan(real(qi)/imag(qi)); % Gouy phase
mat = [1 zf; 0 1]; % transformation matrix
A = mat(1,1); B = mat(1,2); C = mat(2,1); D = mat(2,2);
qf = (A*qi + B)/(C*qi + D); % final complex beam parameter
wf = sqrt(-lambda/pi*(1/imag(1/qf))); % final spot size
Rf = 1/real(1/qf); % final radius of curvature
Psif = atan(real(qf)/imag(qf)); % final Gouy phase
% Hermite - Gaussian modes function
nlist = 0:2:20; % modes range
% precompute hermite polynomials for nlist
hermites = {};
for n = nlist
if n == 0
hermites{n + 1} = #(x)1.0;
else
hermites{n + 1} = matlabFunction(hermiteH(n, x));
end
end
u = #(z, x, n, w, R, Psi) (2/pi)^(1/4)*sqrt(exp(1i*(2*n+1)*Psi)/(2^n*factorial(n)*w))*...
hermites{n + 1}(sqrt(2)*x/w).*exp(-x.^2*(1/w^2+1i*k/(2*R))-1i*k*z);
% Complex amplitude coefficients function
a = #(n) exp(1i*k*zi)*integral(#(x) Ei.*conj(u(zi, x, n, wi, Ri, Psii)),-2*wi,2*wi);
%----------------------------------------------------------------------------
xlisti = -0.1:1/10000:0.1; % initial x-axis range
xlistf = -0.1:1/10000:0.1; % final x-axis range
function Eiplot
Efieldi = zeros(size(xlisti));
for nr = nlist
Efieldi = Efieldi + a(nr).*u(zi, xlisti, nr, wi, Ri, Psii)*exp(-1i*k*zi);
end
Ii = 1/2*c*epsilon*arrayfun(#(x)x.*conj(x),Efieldi);
end
function Efplot
Efieldf = zeros(size(xlistf));
for nr = nlist
Efieldf = Efieldf + a(nr).*u(zf, xlistf, nr, wf, Rf, Psif)*exp(-1i*k*zf);
end
If = 1/2*c*epsilon*arrayfun(#(x)x.*conj(x),Efieldf);
end
Eiplot
Efplot
plot(xlisti,real(Ii),xlistf,real(If))
xlabel('x(m)') % x-axis label
ylabel('I(W/m^2)') % y-axis label
end

Matlab error in Backpropagation algorithm

Here is a matalab program for backpropagation algorithm-
% XOR input for x1 and x2
input = [0 0; 0 1; 1 0; 1 1];
% Desired output of XOR
output = [0;1;1;0];
% Initialize the bias
bias = [-1 -1 -1];
% Learning coefficient
coeff = 0.7;
% Number of learning iterations
iterations = 10000;
% Calculate weights randomly using seed.
rand('state',sum(100.*clock));
weights = -1 +2.*rand(3,3);
for i = 1:iterations
out = zeros(4,1);
numIn = length (input(:,1));
for j = 1:numIn
% Hidden layer
H1 = bias(1,1).*weights(1,1) + input(j,1).*weights(1,2)+ input(j,2).*weights(1,3);
% Send data through sigmoid function 1/1+e^-x
% Note that sigma is a different m file
% that I created to run this operation
x2(1) = sigma(H1);
H2 = bias(1,2).*weights(2,1)+ input(j,1).*weights(2,2)+ input(j,2).*weights(2,3);
x2(2) = sigma(H2);
% Output layer
x3_1 = bias(1,3).*weights(3,1)+ x2(1).*weights(3,2)+ x2(2).*weights(3,3);
out(j) = sigma(x3_1);
% Adjust delta values of weights
% For output layer:
% delta(wi) = xi*delta,
% delta = (1-actual output)*(desired output - actual output)
delta3_1 = out(j).*(1-out(j)).*(output(j)-out(j));
% Propagate the delta backwards into hidden layers
delta2_1 = x2(1).*(1-x2(1)).*weights(3,2).*delta3_1;
delta2_2 = x2(2).*(1-x2(2)).*weights(3,3).*delta3_1;
% Add weight changes to original weights
% And use the new weights to repeat process.
% delta weight = coeff*x*delta
for k = 1:3
if k == 1 % Bias cases
weights(1,k) = weights(1,k) + coeff.*bias(1,1).*delta2_1;
weights(2,k) = weights(2,k) + coeff.*bias(1,2).*delta2_2;
weights(3,k) = weights(3,k) + coeff.*bias(1,3).*delta3_1;
else % When k=2 or 3 input cases to neurons
weights(1,k) = weights(1,k) + coeff.*input(j,1).*delta2_1;
weights(2,k) = weights(2,k) + coeff.*input(j,2).*delta2_2;
weights(3,k) = weights(3,k) + coeff.*x2(k-1).*delta3_1;
end
end
end
end
But its showing error like -
??? Index exceeds matrix dimensions.
Error in ==> sigma at 95
a=varargin{1}; b=varargin{2}; c=varargin{3}; d=varargin{4};
Error in ==> back at 25
x2(1) = sigma(H1);
Please help me out. I am not able to understand the problem. Why there is an error saying index exceeds matrix dimension? Help is needed.

How can i convert image velocity to object velocity in matlab?

I am using for my project the "LucasKanade" code in matlab. It gives me as output 2 matrices (u and v). These are(i believe so) the velocities of the image in the x and y axes respectively. Now how can i convert these velocities to object velocities(eg in meters/second)?
Thanks in advance
"LucasKanade" code:
function [u, v] = LucasKanade(im1, im2, windowSize);
%LucasKanade lucas kanade algorithm, without pyramids (only 1 level);
%REVISION: NaN vals are replaced by zeros
[fx, fy, ft] = ComputeDerivatives(im1, im2);
u = zeros(size(im1));
v = zeros(size(im2));
halfWindow = floor(windowSize/2);
for i = halfWindow+1:size(fx,1)-halfWindow
for j = halfWindow+1:size(fx,2)-halfWindow
curFx = fx(i-halfWindow:i+halfWindow, j-halfWindow:j+halfWindow);
curFy = fy(i-halfWindow:i+halfWindow, j-halfWindow:j+halfWindow);
curFt = ft(i-halfWindow:i+halfWindow, j-halfWindow:j+halfWindow);
curFx = curFx';
curFy = curFy';
curFt = curFt';
curFx = curFx(:);
curFy = curFy(:);
curFt = -curFt(:);
A = [curFx curFy];
U = pinv(A'*A)*A'*curFt;
u(i,j)=U(1);
v(i,j)=U(2);
end;
end;
u(isnan(u))=0;
v(isnan(v))=0;
%u=u(2:size(u,1), 2:size(u,2));
%v=v(2:size(v,1), 2:size(v,2));
%%
function [fx, fy, ft] = ComputeDerivatives(im1, im2);
%ComputeDerivatives Compute horizontal, vertical and time derivative
% between two gray-level images.
if (size(im1,1) ~= size(im2,1)) | (size(im1,2) ~= size(im2,2))
error('input images are not the same size');
end;
if (size(im1,3)~=1) | (size(im2,3)~=1)
error('method only works for gray-level images');
end;
fx = conv2(im1,0.25* [-1 1; -1 1]) + conv2(im2, 0.25*[-1 1; -1 1]);
fy = conv2(im1, 0.25*[-1 -1; 1 1]) + conv2(im2, 0.25*[-1 -1; 1 1]);
ft = conv2(im1, 0.25*ones(2)) + conv2(im2, -0.25*ones(2));
% make same size as input
fx=fx(1:size(fx,1)-1, 1:size(fx,2)-1);
fy=fy(1:size(fy,1)-1, 1:size(fy,2)-1);
ft=ft(1:size(ft,1)-1, 1:size(ft,2)-1);

Resources