This is maybe a bit of a noobish question - but say I want to find the distance between two pixels with coordinates (x1,y1) and (x2,y2). What would be the simplest way of doing this with MatLab?
pdist is an OK answer, but I would argue that it's slow (at least for a larger amount of points). Also, pdist requires the statistics toolbox, so if you don't have that toolbox, you can't use that answer.
I would suggest using bsxfun combined with permute and reshape instead for a toolbox independent solution. Assume that X is a 2 column matrix that is arranged in the following way:
X = [x y];
x and y are the X and Y coordinates of all of your points you want to find the distances to. Therefore, each row consists of a single query point:
X2 = permute(X, [3 2 1]);
out = sqrt(sum(bsxfun(#minus, X, X2).^2, 2));
out = reshape(out, size(X,1), []);
This should give you the same output as applying squareform to the output of pdist. Specifically, at element (i,j) of out, this will give you the distance between point i and point j and so the diagonal elements should give values of 0 as self-distances are 0.
Suggestion by Jonas
We can avoid reshape which may be costly by replacing it with another permute call if we slightly change the way we permute the dimensions before calculating the distances:
out = sqrt(sum(bsxfun(#minus, permute(X, [1 3 2]), permute(X, [3 1 2])).^2, 3));
X = [x1,y1;x2,y2];
d = pdist(X,'euclidean')
d is distance.
Related
So I have a mesh grid
x = linspace(0,1,250);
y=x;
[X,Y] = meshgrid(x,y) ;
At each point, I want a 2x2 matrix (that I will find eigenvalues for). But I cannot figure out the best way (short of looping through the whole 250x250 space).
Suppose my matrix for each X,Y was
M(1,1) = X
M(2,2) = Y
M(1,2) = sin(2*pi*X)
M(2,1) = X.*Y.^2;
What would be the best way to do this then get the eigenvalues for each X,Y?
Not sure by what you mean "best", fastest? here is a simple way to do that if I understood what you wanted (2 eigen-values per pixel):
Start with your definitions
x = linspace(0,1,250);
y=x;
[X,Y] = meshgrid(x,y) ;
S=sin(2*pi*X);
XY2=X.*Y.^2;
Then, we can use linear indexing:
for n=1:numel(X)
M(:,n)=eig([X(n), S(n); XY2(n) , Y(n)]);
end
That's it, all the information is in M...
This took ~3 seconds on my laptop. If you want faster implementation of the eig function for the case of 2x2 matrices you can use this. If you want to go back from linear indexing to the 2D (i,j) index, you can use this to get for pixel i,j the eigenvalues:
M(:, sub2ind(size(X),i,j))
I have two images which one of them is the Original image and the second one is Transformed image.
I have to find out how many degrees Transformed image was rotated using 3x3 transformation matrix. Plus, I need to find how far translated from origin.
Both images are grayscaled and held in matrix variables. Their sizes are same [350 500].
I have found a few lecture notes like this.
Lecture notes say that I should use the following matrix formula for rotation:
For translation matrix the formula is given:
Everything is good. But there are two problems:
I could not imagine how to implement the formulas using MATLAB.
The formulas are shaped to find x',y' values but I already have got x,x',y,y' values. I need to find rotation angle (theta) and tx and ty.
I want to know the equivailence of x, x', y, y' in the the matrix.
I have got the following code:
rotationMatrix = [ cos(theta) sin(theta) 0 ; ...
-sin(theta) cos(theta) 0 ; ...
0 0 1];
translationMatrix = [ 1 0 tx; ...
0 1 ty; ...
0 0 1];
But as you can see, tx, ty, theta variables are not defined before used. How can I calculate theta, tx and ty?
PS: It is forbidden to use Image Processing Toolbox functions.
This is essentially a homography recovery problem. What you are doing is given co-ordinates in one image and the corresponding co-ordinates in the other image, you are trying to recover the combined translation and rotation matrix that was used to warp the points from the one image to the other.
You can essentially combine the rotation and translation into a single matrix by multiplying the two matrices together. Multiplying is simply compositing the two operations together. You would this get:
H = [cos(theta) -sin(theta) tx]
[sin(theta) cos(theta) ty]
[ 0 0 1]
The idea behind this is to find the parameters by minimizing the error through least squares between each pair of points.
Basically, what you want to find is the following relationship:
xi_after = H*xi_before
H is the combined rotation and translation matrix required to map the co-ordinates from the one image to the other. H is also a 3 x 3 matrix, and knowing that the lower right entry (row 3, column 3) is 1, it makes things easier. Also, assuming that your points are in the augmented co-ordinate system, we essentially want to find this relationship for each pair of co-ordinates from the first image (x_i, y_i) to the other (x_i', y_i'):
[p_i*x_i'] [h11 h12 h13] [x_i]
[p_i*y_i'] = [h21 h22 h23] * [y_i]
[ p_i ] [h31 h32 1 ] [ 1 ]
The scale of p_i is to account for homography scaling and vanishing points. Let's perform a matrix-vector multiplication of this equation. We can ignore the 3rd element as it isn't useful to us (for now):
p_i*x_i' = h11*x_i + h12*y_i + h13
p_i*y_i' = h21*x_i + h22*y_i + h23
Now let's take a look at the 3rd element. We know that p_i = h31*x_i + h32*y_i + 1. As such, substituting p_i into each of the equations, and rearranging to solve for x_i' and y_i', we thus get:
x_i' = h11*x_i + h12*y_i + h13 - h31*x_i*x_i' - h32*y_i*x_i'
y_i' = h21*x_i + h22*y_i + h23 - h31*x_i*y_i' - h32*y_i*y_i'
What you have here now are two equations for each unique pair of points. What we can do now is build an over-determined system of equations. Take each pair and build two equations out of them. You will then put it into matrix form, i.e.:
Ah = b
A would be a matrix of coefficients that were built from each set of equations using the co-ordinates from the first image, b would be each pair of points for the second image and h would be the parameters you are solving for. Ultimately, you are finally solving this linear system of equations reformulated in matrix form:
You would solve for the vector h which can be performed through least squares. In MATLAB, you can do this via:
h = A \ b;
A sidenote for you: If the movement between images is truly just a rotation and translation, then h31 and h32 will both be zero after we solve for the parameters. However, I always like to be thorough and so I will solve for h31 and h32 anyway.
NB: This method will only work if you have at least 4 unique pairs of points. Because there are 8 parameters to solve for, and there are 2 equations per point, A must have at least a rank of 8 in order for the system to be consistent (if you want to throw in some linear algebra terminology in the loop). You will not be able to solve this problem if you have less than 4 points.
If you want some MATLAB code, let's assume that your points are stored in sourcePoints and targetPoints. sourcePoints are from the first image and targetPoints are for the second image. Obviously, there should be the same number of points between both images. It is assumed that both sourcePoints and targetPoints are stored as M x 2 matrices. The first columns contain your x co-ordinates while the second columns contain your y co-ordinates.
numPoints = size(sourcePoints, 1);
%// Cast data to double to be sure
sourcePoints = double(sourcePoints);
targetPoints = double(targetPoints);
%//Extract relevant data
xSource = sourcePoints(:,1);
ySource = sourcePoints(:,2);
xTarget = targetPoints(:,1);
yTarget = targetPoints(:,2);
%//Create helper vectors
vec0 = zeros(numPoints, 1);
vec1 = ones(numPoints, 1);
xSourcexTarget = -xSource.*xTarget;
ySourcexTarget = -ySource.*xTarget;
xSourceyTarget = -xSource.*yTarget;
ySourceyTarget = -ySource.*yTarget;
%//Build matrix
A = [xSource ySource vec1 vec0 vec0 vec0 xSourcexTarget ySourcexTarget; ...
vec0 vec0 vec0 xSource ySource vec1 xSourceyTarget ySourceyTarget];
%//Build RHS vector
b = [xTarget; yTarget];
%//Solve homography by least squares
h = A \ b;
%// Reshape to a 3 x 3 matrix (optional)
%// Must transpose as reshape is performed
%// in column major format
h(9) = 1; %// Add in that h33 is 1 before we reshape
hmatrix = reshape(h, 3, 3)';
Once you are finished, you have a combined rotation and translation matrix. If you want the x and y translations, simply pick off column 3, rows 1 and 2 in hmatrix. However, we can also work with the vector of h itself, and so h13 would be element 3, and h23 would be element number 6. If you want the angle of rotation, simply take the appropriate inverse trigonometric function to rows 1, 2 and columns 1, 2. For the h vector, this would be elements 1, 2, 4 and 5. There will be a bit of inconsistency depending on which elements you choose as this was solved by least squares. One way to get a good overall angle would perhaps be to find the angles of all 4 elements then do some sort of average. Either way, this is a good starting point.
References
I learned about homography a while ago through Leow Wee Kheng's Computer Vision course. What I have told you is based on his slides: http://www.comp.nus.edu.sg/~cs4243/lecture/camera.pdf. Take a look at slides 30-32 if you want to know where I pulled this material from. However, the MATLAB code I wrote myself :)
I have an equation like this
y = a*x+b;
I have sets of y and x
y = [1 2 3 4 5]
x = [6 7 8 9 10]
I want to find a and b, but not one solution; all solutions. I guess, I have to use polyfit, but I don't know how to do this and I don't understand why I have to use polyfit? Can you explain this to me?
From the polyfit documentation:
p = polyfit(x,y,n) finds the coefficients of a polynomial p(x) of
degree n that fits the data, p(x(i)) to y(i), in a least squares
sense. The result p is a row vector of length n+1 containing the
polynomial coefficients in descending powers:
So, you have data y at x-coordinates x, and you want to fit a first-degree polynomial to it. So use
p=polyfit(x,y,1);
and then p(1)=a and p(2)=b, or y=p(1)*x+p(2).
There are other ways to do this, but polyfit is very simple.
How can I calculate the norm of quaternion in matlab?
I tried this example
a = [1 4 4 -4];
norm = quatnorm(a)
My expected output is 7 but matlab returns 49.
What am I doing wrong?
As #Dan points out, using the native implementation, you are probably getting the square of the formal norm definition. For some reason quatnorm returns the square, after estimating the Euclidean norm (square root of sum of squares).
q = [1 4 4 -4];
MATLABquatnorm:
for index = size(q, 1):-1:1
qnorm(index,:) = norm(q(index,:), 2);
end
qout = qnorm.*qnorm;
Alternative (for vectors):
sqrt(q*q')
This is equivalent to getting sqrt(quatnorm(q)). As you will note above, quatnorm is also adapted to estimate norms for quaternions stored in successive matrix rows (estimates the norm of each row and then squares)
Alternative (for matrices N x 4):
Q = [q; 2*q]; % example
sqrt(diag(Q*Q'))
You can either take square root of the returned number, or you can use function quatmod(q) instead, which calculates the proper Euclidean norm (modulus) of the complex number by not taking square of it.
I've got matrices A and B
size(A) = [n x]; size(B) = [n y];
Now I need to compare euclidian distance of each column vector of A from each column vector of B. I'm using dist method right now
Q = dist([A B]); Q = Q(1:x, x:end);
But it does also lot of needless work (like calculating distances between vectors of A and B separately).
What is the best way to calculate this?
You are looking for pdist2.
% Compute the ordinary Euclidean distance
D = pdist2(A.',B.','euclidean'); % euclidean distance
You should take the transpose of the matrices since pdist2 assumes the observations are in rows, not in columns.
An alternative solution to pdist2, if you don't have the Statistics Toolbox, is to compute this manually. For example, one way to do it is:
[X, Y] = meshgrid(1:size(A, 2), 1:size(B, 2)); %// or meshgrid(1:x, 1:y)
Q = sqrt(sum((A(:, X(:)) - B(:, Y(:))) .^ 2, 1));
The indices of the columns from A and B for each value in vector Q can be obtained by computing:
[X(:), Y(:)]
where each row contains a pair of indices: the first is the column index in matrix A, and the second is the column index in matrix B.
Another solution if you don't have pdist2 and which may also be faster for very large matrices is to vectorize the following mathematical fact:
||x-y||^2 = ||x||^2 + ||y||^2 - 2*dot(x,y)
where ||a|| is the L2-norm (euclidean norm) of a.
Comments:
C=-2*A'*B (this is a x by y matrix) is the vectorization of the dot products.
||x-y||^2 is the square of the euclidean distance which you are looking for.
Is that enough or do you need the explicit code?
The reason this may be faster asymptotically is that you avoid doing the metric calculation for all x*y comparisons, since you are instead making the bottleneck a matrix multiplication (matrix multiplication is highly optimized in matlab). You are taking advantage of the fact that this is the euclidean distance and not just some unknown metric.