RMSE for sift algorithm - matlab

I work with the vl_sift algorithm. How can I calculate RMSE to match two images? second image is projective transform to the first image.
I1 = imread('filename');
T = projective2d([0.89 1.24 0.002;
-0.95 1 0.0025;
0 0 1]);
I2 = imwarp(I1(400:800,400:800),T);

Related

How to derive the translation matrix from Essential matrix?

I have to reconstruct the 3D position of some visible features, which are visible on two images taken from a car. The photos have different positions and angles. I was able to derive the matrix K from the first image because the requirement of the project asked for the camera calibration matrix of that specific image.
For the 3D reconstruction, I have to follow these steps:
Find the matching point, and estimate the fundamental matrix F.
Since I don't have any information about the P2 (projection matrix of the second image), I have to use the Essential matrix to be able to retrieve the matrix R and T for the second camera.
Executing triangulation and building the 3D position.
%% finding fundomental metrix
matched_points_image1 = [x_i_1, y_i_1];
matched_points_image2 = [x_i_2, y_i_2];
[F, inliers] = estimateFundamentalMatrix(matched_points_image1,matched_points_image2,'NumTrials',2000);
F = [-0.0000 -0.0000 0.0028;
0.0001 -0.0000 -0.0038;
-0.0050 -0.0060 1.0000];
%% Finding the essential metrix
fprintf("Finding the essential metrics because we don't know the R and T between two cameras whose took the pictures...\n")
K1 = [ 1.1137 0 1.2254;
0 1.6541 0.0428;
0 0 0.0001];
E = K1'*F*K1;
%putting the first camera as world reference
P1 = K1*eye(3,4);
%Estimation of P2 based on svd decomposition of E
[U,S,V] = svd(E);
W = [0 1 0;-1 0 0;0 0 1];
R_2_positive = U*W'*V';
R_2_negative = U*W*V';
%since there are two rotation matrices, for each of them there are two
%possible translation matrice. [t]×= ±E12R
t_2_1_positive = E*(R_2_positive)';
t_2_2_positive = E'*(R_2_positive)';
t_2_1_negative = E*(R_2_negative)';
t_2_2_negative = E'*(R_2_negative)';
The problem is for the matrices t which are derived from [t]×= ±E12R, I should have a 3x1 matrix but the answers are 3x3 matrices.
after searching i figured out for matrix t i have to do such so:
t = reshape(U(:, 3) / max(abs(U(:, 3))), [3, 1]);
P2_1(:, :, 1) = cat(2, U*W*V', t);
P2_2(:, :, 2) = cat(2, U*W*V', -t);
P2_3(:, :, 3) = cat(2, U*W'*V', t);
P2_4(:, :, 4) = cat(2, U*W'*V', -t);

How to apply a function for each of the various entries from different matrices as index?

I'm writing a function in matlab which mimics the built-in 'imwarp' function (applying geometric transformation) without using any kind of loops. i'm in the final step when i have to call my function for bi-linear interpolation for every index in final 2D image.
I have 3 arrays here , 'pts' have homogenized vectors (x,y,1) for which i interpolate and 'row' and 'cols' have x and y coordinates respectively for resultant image where interpolated intensity value would be placed.
finalImage (rows(1,:),cols(1,:))=bilinear(pts(:,:),im);
Kindly correct my syntax here to do it properly. thanks in advance.
The following is a simple implementation of applying an affine transformation to an image. Some of the matrices may be reversed because I did this from memory. I don't know exactly how you are formatting your pts array so I figure a working example is the best I can do. The interp2 function applies bilinear interpolation, the bilinear function performs the bilinear transform which describes analog filters as digital filters. This is not what you want.
P.S. You have to make sure to use the inverse transform when applying image warping (that is, define the point you want to sample in the input image for each point in the output image). If you perform the forward transform (i.e. define the point in the output image that each point in the input image maps to) then you will end up with some serious aliasing effects and potentially holes in the output image.
Hope this helps. Let me know if you have questions.
img = double(imread('rice.png'))/255;
theta = 30; % rotate 30 degrees
R = [cosd(theta) -sind(theta) 0; ...
sind(theta) cosd(theta) 0; ...
0 0 1];
sx = 15; % skew by 15 degrees in x
Skx = [1 tand(sx) 0; ...
0 1 0; ...
0 0 1];
% Translate by 1/2 size of image
tx = -size(img, 2)/2;
ty = -size(img, 1)/2;
T = [1 0 tx; ...
0 1 ty; ...
0 0 1];
% Scale image down by 1/2
sx = 0.5;
sy = 0.5;
S = [sx 0 0; ...
0 sy 0; ...
0 0 1];
% translate, scale, rotate, skew, then translate back
A = inv(T)*Skx*R*S*T;
% create meshgrid points
[x, y] = meshgrid(1:size(img,2), 1:size(img,1));
% reshape so we can apply matrix op
V = [reshape(x, 1, []); reshape(y, 1, []); ones(1, numel(x))];
Vq = inv(A)*V;
% probably not necessary for these transformations but project back to the z=1 plane
Vq(1,:) = Vq(1,:) ./ V(3,:);
Vq(2,:) = Vq(2,:) ./ V(3,:);
% reshape back into a meshgrid
xq = reshape(Vq(1,:), size(img));
yq = reshape(Vq(2,:), size(img));
% use interp2 to perform bilinear interpolation
imgnew = interp2(x, y, img, xq, yq);
% show the resulting image
imshow(imgnew);

How to code frequency response of convolution kernel in matlab

given a convolution kernel computed from sigma using the function fspecial('gaussian',,)
how can I plot the frequency response in Matlab?
I would like to do this on a gaussian function, and importantly would like to derive the 1D frequency response (coz I understand them better) of the horizontal convolution kernel with size N.
Thanks for the help!!!
kernel2 = fspecial('gaussian', [1 5], 1.3)
spike = [1 0 0 0 0];
[h, w] = freqz(kernel2, spike, 1024);
m = abs(h)
p = angle(h);
plot(w,m);
hat tip to https://courseware.ee.calpoly.edu/~fdepiero/curr/dsp/dsp11.htm

Gradient histograms in matlab

I am trying to figure out how to create an array of histogram to compare the magnitude and direction of gradient vectors of an image in matlab. I am to use sobel masks to find the gradients, so far I have:
sobel_x = [-1 -2 -1;0 0 0;1 2 1];
sobel_y = [-1 0 1;-2 0 2;-1 0 1];
gx = filter2(sobel_x,im,'same');
gy = filter2(sobel_y,im,'same');
Now I need to figure out how to create a histogram to compare it with other images.
You can take the computed gx and gy matrices and treat them as long vectors, then group them into a gradient vector that is size: 2 x (# number of elements in gx or gy)
% create the gradient vectors
grad_vector(1,:) = gx(:);
grad_vector(2,:) = gy(:);
then you can find the magnitude and direction of each gradient vector in a variety of ways, for example:
%find magnitude and direction of each gradient vector
for i=1:size(grad_vector,2);
magn(i) = norm(grad_vector(:,i));
dir(i) = atand(grad_vector(2,i)/grad_vector(1,i));
end
the histogram can then be created by deciding how to divide up the results into a number of bins. For example, you may choose to divide the direction into 4 bins and the magnitude into 3, then:
% find histograms, dividing into appropriate bins
histdir = hist(dir,4);
histmag = hist(magn,3);

3d grayscale volume projection onto 2D plane

I have a 3-D grayscale volume corresponding to ultrasound data. In Matlab this 3-D volume is simply a 3-D matrix of MxNxP. The structure I'm interested in is not oriented along the z axis, but along a local coordinate system already known (x'y'z'). What I have up to this point is something like the figure shown below, depicting the original (xyz) and the local coordinate systems (x'y'z'):
I want to obtain the 2-D projection of this volume (i.e. an image) through a specific plane on the local coordinate system, say at z' = z0. How can I do this?
If the volume was oriented along the z axis this projection could be readily achieved. i.e. if the volume, in Matlab, is V, then:
projection = sum(V,3);
thus, the projection can be computed just as the sum along the 3rd dimension of the array. However with a change of orientation the problem becomes more complicated.
I've been looking at radon transform (2D, that applies only to 2-D images and not volumes) and also been considering ortographic projections, but at this point I'm clueless as to what to do!
Thanks for any advice!
New attempt at solution:
Following the tutorial http://blogs.mathworks.com/steve/2006/08/17/spatial-transformations-three-dimensional-rotation/ and making some small changes, I might have something which could help you. Bear in mind, I have little or no experience with volumetric data in MATLAB, so the implementation is quite hacky.
In the below code I use tformarray() to rotate the structure in space. First, the data is centered, then rotated using rotationmat3D to produce the spacial transformation, before the data is moved back to its original position.
As I have never used tformarray before, I handeled datapoints falling outside the defined region after rotation by simply padding the data matrix (NxMxP) with zeros all around. If anyone know a better way, please let us know :)
The code:
%Synthetic dataset, 25x50x25
blob = flow();
%Pad to allow for rotations in space. Bad solution,
%something better might be possible to better understanding
%of tformarray()
blob = padarray(blob,size(blob));
f1 = figure(1);clf;
s1=subplot(1,2,1);
p = patch(isosurface(blob,1));
set(p, 'FaceColor', 'red', 'EdgeColor', 'none');
daspect([1 1 1]);
view([1 1 1])
camlight
lighting gouraud
%Calculate center
blob_center = (size(blob) + 1) / 2;
%Translate to origin transformation
T1 = [1 0 0 0
0 1 0 0
0 0 1 0
-blob_center 1];
%Rotation around [0 0 1]
rot = -pi/3;
Rot = rotationmat3D(rot,[0 1 1]);
T2 = [ 1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1];
T2(1:3,1:3) = Rot;
%Translation back
T3 = [1 0 0 0
0 1 0 0
0 0 1 0
blob_center 1];
%Total transform
T = T1 * T2 * T3;
%See http://blogs.mathworks.com/steve/2006/08/17/spatial-transformations-three-dimensional-rotation/
tform = maketform('affine', T);
R = makeresampler('linear', 'fill');
TDIMS_A = [1 2 3];
TDIMS_B = [1 2 3];
TSIZE_B = size(blob);
TMAP_B = [];
F = 0;
blob2 = ...
tformarray(blob, tform, R, TDIMS_A, TDIMS_B, TSIZE_B, TMAP_B, F);
s2=subplot(1,2,2);
p2 = patch(isosurface(blob2,1));
set(p2, 'FaceColor', 'red', 'EdgeColor', 'none');
daspect([1 1 1]);
view([1 1 1])
camlight
lighting gouraud
The arbitrary visualization below is just to confirm that the data is rotated as expected, plotting a closed surface when the data passed the value '1'. With blob2, you should know be able to project by using simple sums.
figure(2)
subplot(1,2,1);imagesc(sum(blob,3));
subplot(1,2,2);imagesc(sum(blob2,3));
Assuming you have access to the coordinate basis R=[x' y' z'], and that those vectors are orthonormal, you can simply extract the representation in this basis by multiplying your data with the the 3x3 matrix R, where x',y',z' are column vectors.
With the data stored in D (Nx3), you can get the representation with R, by multiplying by it:
Dmarked = D*R;
and now D = Dmarked*inv(R), so going back and forth is stragihtforward.
The following code might provide help to see the transformation. Here I create a synthetic dataset, rotate it, and then rotate it back. Doing sum(DR(:,3)) would then be your sum along z'
%#Create synthetic dataset
N1 = 250;
r1 = 1;
dr1 = 0.1;
dz1 = 0;
mu1 = [0;0];
Sigma1 = eye(2);
theta1 = 0 + (2*pi).*rand(N1,1);
rRand1 = normrnd(r1,dr1,1,N1);
rZ1 = rand(N1,1)*dz1+1;
D = [([rZ1*0 rZ1*0] + repmat(rRand1',1,2)).*[sin(theta1) cos(theta1)] rZ1];
%Create roation matrix
rot = pi/8;
R = rotationmat3D(rot,[0 1 0]);
% R = 0.9239 0 0.3827
% 0 1.0000 0
% -0.3827 0 0.9239
Rinv = inv(R);
%Rotate data
DR = D*R;
%#Visaulize data
f1 = figure(1);clf
subplot(1,3,1);
plot3(DR(:,1),DR(:,2),DR(:,3),'.');title('Your data')
subplot(1,3,2);
plot3(DR*Rinv(:,1),DR*Rinv(:,2),DR*Rinv(:,3),'.r');
view([0.5 0.5 0.2]);title('Representation using your [xmarked ymarked zmarked]');
subplot(1,3,3);
plot3(D(:,1),D(:,2),D(:,3),'.');
view([0.5 0.5 0.2]);title('Original data before rotation');
If you have two normalized 3x1 vectors x2 and y2 corresponding to your local coordinate system (x' and y').
Then, for a position P, its local coordinate will be xP=P'x2 and yP=P'*y2.
So you can try to project your volume using accumarray:
[x y z]=ndgrid(1:M,1:N,1:P);
posP=[x(:) y(:) z(:)];
xP=round(posP*x2);
yP=round(posP*y2);
xP=xP+min(xP(:))+1;
yP=yP+min(yP(:))+1;
V2=accumarray([xP(:),yP(:)],V(:));
If you provide your data, I will test it.