Interpolating coordinates for a specific time - matlab

I am trying to interpolate values for X and Y coordinates across time. I am getting NaN's when i try to interpolate for a specific coordinate (X,Y value).
data_to_be_interpolated = final_plot_matrix(:,[1 24:25]);
data_to_be_interpolated(isnan(data_to_be_interpolated)) = 0;
X_coordinate = data_to_be_interpolated(2:end,2);
Y_coordinate = data_to_be_interpolated(2:end,3);
time = data_to_be_interpolated(2:end,1);
coordinates_together = [X_coordinate Y_coordinate];
missing_part = fillmissing(data_to_be_interpolated(2:end,2:3),'linear','SamplePoints',data_to_be_interpolated(2:end,1))
The picture of the matix data to be interpolated is shown below
When i give value 5.6366e+04 (time value) to get the interpolated value for X and Y coordinates, now am getting [0, 0], instead of the X and Y value. Any help will be appreciated.

Try this,
Z = fillmissing(X_coordinate,'linear','SamplePoints',time);
This will interpolate the missing values.
Remember to convert all zeros to NaN.
zt = 1:1:5;
za = [100 50 0 0 20];
za(za == 0) = NaN;
zb = fillmissing(za,'linear','SamplePoints',zt);
zb =
100 50 40 30 20

Related

How to write a code that finds difference between adjacent, nonNaN values in a 3d array

Essentially,I have 4 arrays in a data file. They are: theta (276 x 626 x 2677 double); dates (1 x 2677 date time); latitude (276 x 626 double); and longitude (276 x 626 double). I am basically trying to find d(theta)/dt.
I'm working in MATLAB and currently have:
data = load("data.mat");
[numLat, numLon, numDay] = size(data.theta);
%loop through the latitude and longitude
for ilat = 1:numLat
for ilong = 1:numLon
X = squeeze(data.theta(ilat,ilong,:)); %[numDay x 1]
ix = find(~isnan(X)); %finds the nonNaNs
XX = X(ix); %creates vector of nonNan thetas
dd = days(ix); %creates vector of nonNan days
XXdd = XX(2:end) - XX(1:end-1); %difference between adjacent thetas
end
end
However, this creates a 2677 x 1 vector X that is full of NaNs, and XX and dd are just [ ]. Am I doing something wrong??

Image Rotation in Three Dimensions (Matlab)

I am trying to rotate a 2D image in Matlab xyz 3-D space. I want to rotate the image I by an angle θ=i about the x-axis. I am doing this by means of multiplication with the rotation matrix (as defined here):
This is my code:
x = linspace(-1,1,size(I,1));
[x0,y0,z0] = meshgrid(x,x,1);
R = [1 0 0; 0 cosd(-i) -sind(-i); 0 sind(-i) cosd(-i)];
xy = [x0(:),y0(:), z0(:)]*R';
X = reshape(xy(:,1),size(x0));
Y = reshape(xy(:,2),size(y0));
Z = reshape(xy(:,3),size(z0));
rotatedI = interp3(x0,y0,z0,I,X,Y,Z, 'nearest');
rotatedI(isnan(rotatedI)) = 0;
The error that I am getting is in the interpolation line:
Error using griddedInterpolant
Interpolation requires at least two sample points in each
dimension.
So what exactly is the problem here and how can I fix it?
I am confused because this code works fine when specialized to two dimensions. Any explanation is much appreciated.
the problem is that your input z grid z0 contains a single value (1), while your desired z grid Z contains multiple values. therefore there is no way to interpolate this single value into multiple ones.
you can assign the input z grid with multiple values so that it will be possible to interpolate.
I = im2double(imread('cameraman.tif'));
I = cat(3,I,I,I);
i = 10;
x = linspace(-1,1,size(I,1));
[x0,y0,z0] = meshgrid(x,x,-1:1); % 3 z values
R = [1 0 0; 0 cosd(-i) -sind(-i); 0 sind(-i) cosd(-i)];
xy = [x0(:),y0(:), z0(:)]*R;
X = reshape(xy(:,1),size(x0));
Y = reshape(xy(:,2),size(y0));
Z = reshape(xy(:,3),size(z0));
rotatedI = interp3(x0,y0,z0,I,X,Y,Z, 'nearest');
rotatedI(isnan(rotatedI)) = 0;
imshow(rotatedI);
in addition, you can use rotx, roty, and rotz to generate rotation matrices easily.
UPDATE
if you want to rotate the image 2D plane in the 3D space you don't need to use interpolation and can do something like:
I = im2double(imread('cameraman.tif'));
i = 10;
x = linspace(-1,1,size(I,1));
[x0,y0,z0] = meshgrid(x,x,-1:1); % 3 z values
[x0,y0,z0] = meshgrid(x,x,1); % 3 z values
R = [1 0 0; 0 cosd(-i) -sind(-i); 0 sind(-i) cosd(-i)];
xy = [x0(:),y0(:), z0(:)]*R;
X = reshape(xy(:,1),size(x0));
Y = reshape(xy(:,2),size(y0));
Z = reshape(xy(:,3),size(z0));
warp(X,Y,Z,I);
grid on

find nearest point to a fitting line and the neighborhood of it in Matlab

Supposed I have two random double array, which means that one x coordinate might have multiple y value.
X = randi([-10 10],1,1000);
Y = randi([-10 10],1,1000);
Then I give a line equation: y=ax+b.
I want to find the nearest point to the nearest point to the line based on every x point. And when I find this point, I will find it's neighborhood points within specific range. Please forgive my poor English, maybe following picture can help more.
Because I have a lot of data points, I hope there is an efficient way to deal with this problem.
if your X's are discrete you can try something like:
xrng = [-10 10];
yrng = [-10 10];
a = rand;
b = rand;
f = #(x) a*x + b;
X = randi(xrng,1,1000);
Y = randi(yrng,1,1000);
ezplot(f,xrng);
hold on;
plot(X,Y,'.');
xx = xrng(1):xrng(2);
nbrSz = 2;
nx = diff(xrng);
nearestIdx = zeros(nx,1);
nbrIdxs = cell(nx,1);
for ii = 1:nx
x = xx(ii);
y = f(x);
idx = find(X == x);
[~,idxidx] = min(abs(y - Y(idx)));
nearestIdx(ii) = idx(idxidx);
nbrIdxIdxs = abs(Y(nearestIdx(ii)) - Y(idx)) <= nbrSz;
nbrIdxs{ii} = idx(nbrIdxIdxs);
plot(X(nearestIdx(ii)),Y(nearestIdx(ii)),'og');
plot(X(nearestIdx(ii)) + [0 0],Y(nearestIdx(ii)) + [-nbrSz nbrSz],'g')
plot(X(nbrIdxs{ii}),Y(nbrIdxs{ii}),'sy')
end

Matlab Dissecting Extracting Camera Projection Matrix to position and rotation

I have 6 points in space with known coordinates in mm and corresponding 2D pixel coordinates in the image (image size is 640x320 pixels and points coordinates have been measured from upper left of the image. also I have the focal length of the camera as 43.456mm. trying to find the camera position and orientation.
My matlab code here will give me the camera location as -572.8052
-676.7060 548.7718 and seems correct but I am having a hard time finding the orientation values (yaw pitch roll of the camera in degrees)
I know that the rotation values should be 60.3,5.6,-45.1
the last 4 lines in my code needs to be updated to output the orientation of the camera.
I would really really appreciate your help on this.
Thanks.
Here is my matlab code:
Points_2D= [135 183 ; 188 129 ; 298 256 ; 301 43 ; 497 245; 464 110];
Points_3D= [-22.987 417.601 -126.543 ; -132.474 37.67 140.702 ; ...
388.445 518.635 -574.784 ; 250.015 259.803 67.137 ; ...
405.915 -25.566 -311.834 ; 568.859 164.809 -162.604 ];
M = [0;0;0;0;0;0;0;0;0;0;0];
A = [];
for i = 1:size(Points_2D,1)
u_i = Points_2D(i,1);
v_i = Points_2D(i,2);
x_i = Points_3D(i,1);
y_i = Points_3D(i,2);
z_i = Points_3D(i,3);
A_vec_1 = [x_i y_i z_i 1 0 0 0 0 -u_i*x_i -u_i*y_i -u_i*z_i -u_i]; %
A_vec_2 = [ 0 0 0 0 x_i y_i z_i 1 -v_i*x_i -v_i*y_i -v_i*z_i -v_i]; %
A(end+1,:) = A_vec_1;
A(end+1,:) = A_vec_2;
end
[U,S,V] = svd(A);
M = V(:,end);
M = transpose(reshape(M,[],3));
Q = M(:,1:3);
m_4 = M(:,4);
Center = (-Q^-1)*m_4
k=[43.456/640 0 320 ;0 43.456/320 160;0 0 1 ];
Rotation= (Q^-1)*k;
CC=Rotation'
eul=rotm2eul(CC)
First thing first: 6 points are enough but it is likely that you have some error. To get a better performance, it is recommended to have more than 6 points, like 10-15 preferably.
Your code seems correct until:
Q = M(:,1:3);
m_4 = M(:,4);
So you are looking for extrinsic and intrinsic parameters of the camera, i.e. rotation, translation, alpha(skew in x direction), ro, beta(skew in x direction), u0, v0 (translation of camera center). So a total of 5 intrinsics, 6 extrinsic parameters.
Here is a link which explains the details how to calculate those parameters. I had a code which I didn't test thoroughly, may be some errors but it was working in my case.
Continuing from M which is the 3x4 matrix you found:
a1 = M(1, 1:3);
a2 = M(2, 1:3);
a3 = M(3, 1:3);
b = M(1:3,4);
% Decomposition of the parameters
eps = 1; %this can be -1 or +1, based on the value you choose, you will have two different results.
ro = eps/sqrt(sumsqr(a3));
r3 = ro*a3;
u0 = ro.^2*(dot(a1,a3))
v0 = ro.^2*(dot(a2,a3))
cos_theta = -dot(cross(a1,a3),cross(a2,a3))/ ...
dist_cross(a1,a3)/(dist_cross(a2,a3));
theta = acos(cos_theta);
alpha = ro^2*dist_cross(a1,a3)*sin(theta)
beta = ro^2*dist_cross(a2,a3)*sin(theta)
theta_deg = theta*180/pi
r1 = 1/dist_cross(a2,a3)*cross(a2,a3);
r2 = cross(r3,r1);
R = [r1;r2;r3] % Rotation matrix 3x3
% ro*A.inv(R) = K
K = [alpha -alpha*cot(theta) u0;
0 beta/sin(theta) v0;
0 0 1 ];
T = ro*(inv(K)*b) % Translation matrix, 1x3
where
function [dis] = dist_cross(mi,mj)
dis = sqrt(sumsqr(cross(mi,mj)));
end
I don't guarantee it is totally correct but it should help.

Not sure what this 'histogram code' is doing in MATLAB

I have following code that was given to me, but I am not sure at all as to what the logic here is. The idea, I believe, is that this will histogram/quantize my data. Here is the code:
The input:
x = 180.*rand(1,1000); %1000 points from 0 to 180 degrees.
binWidth = 20; %I want the binWidth to be 20 degrees.
The main function:
% -------------------------------------------------------------------------
% Compute the closest bin center x1 that is less than or equal to x
% -------------------------------------------------------------------------
function [x1, b1] = computeLowerHistBin(x, binWidth)
% Bin index
bin = floor(x./binWidth - 0.5);
% Bin center x1
x1 = binWidth * (bin + 0.5);
% add 2 to get to 1-based indexing
b1 = bin + 2;
end
Finally, the final 'quantized' data:
w = 1 - (x - x1)./binWidth
Here is what I do not get: I do not understand - at all - just why exactly x1 is computed the way it is, and also why/how w is computed the way it is. In fact, of all the things, w confuses me the most. I literally cannot understand the logic here, or what is really intended. Would appreciate a detailed elucidation of this logic. Thanks.
He is binning with lb <= x < up and splitting the interval [0,180] in [-10,10), [10, 30), [30,40) ..., [150,170), [170,190).
Suppose x = 180, then:
bin = floor(180/20-0.5) = floor(9-0.5) = floor(8.5) = 8;
while if x = 0:
bin = floor(`0/20-0.5) = floor(-0.5) = floor(-1) = -1;
which respectively translate into x1 = 20 * (8+0.5) = 170 and x1 = -10 which seems like what the function suggests lowerHistBin().
In the end, w simply measures how far the point x is from the corresponding lower bin x1. Notice that w is in (0,1], with w being 1 when x = x1 and approaching 0 when x -> x1+binWidth. So, if x say approaches 170, then w will approach 1 - (170-150)/20 = 0.