Both opencv and matlab have the function decomposeHomographyMatrix. This requires the homography matrix, H, and the camera intrinsic, K. I dont understand why it needs K?
Each of these function implementations reference "Malis" (https://hal.archives-ouvertes.fr/inria-00174036/document). On page 7 it talks about the intrinsic matrix K but then never uses it. It doesn't seem like it is necessary?
Here is how I understand the document you linked ("Deeper understanding of the homography decomposition for vision-based control"). If I am wrong, please correct me.
DecomposeHomographyMat needs K to compute euclidean homography H from projective homography G.
H = K_inv * G * K (Formula2)
R, t and n will be computed from euclidean homography matrix (Formula 3).
Opencv function decomposeHomographyMat assumes to get a projective homography matrix as an input (not euclidean)!
Notice that in the document you linked, the projective homography matrix is called G (not H!), while an euclidean homography matrix is called H.
Projective homography matrix is computed based on the vectors p - image coordinates of the points. (pixels)
alfa_p * p_c = G * p_star
Euclidean homography matrix is computed based on the vectors m "normalized projective coordinates of the points viewed from the camera pose" (e.g. meters).
alfa_m * m_c = H * m_star
Where: -c - current frame; _d - desired frame; alfa - just scale factors
The relationship between image and projective coordinates is:
m = K_inv * p
K - matrix of the camera intrinsic parameters; K_inv - inverse of the matrix K
To be even more clear:
p_c = G * p_star
-> K * K_inv * p_c = G * K * K_inv * p_star
-> K * m_c = G * K * m_star
-> m_c = K_inv * G * K * m_star
-> m_c = H * m_star
Remember that:
K_inv * K = I - identity matrix
Well, you must know K in order to find R,T. Formula (1) in your reference shows this clearly (the homography G is given in your case and you are looking for the camera pose R,T). There is no way to solve for R,T without knowing K.
Whether K is used later depends on what you are going to do with the pose. If you are going to project 3D landmarks to images, you must know K for that too.
Not sure if I am telling you anything new...
Related
All,
Suppose I have two vectors U and V with 2 units and 1 unit length, respectively as shown in the sketch. The vector U is rotated by angle theta.
There are, at least two possible cases whereby vector U can go "up" or "down" as shown in the sketch.
My question is, having the above dataset is it possible to have a generic formula that can be transferred into Matlab to get the coordinate of point M?
the length of the vector U and V and angle theta are arbitrary.
Thank you!
There is a more efficient solution.
The coordinates of the endpoints of U are given by:
(U * cos(theta), U * sin(theta))
For any vector (x, y) the clockwise perpendicular direction (i.e. the second diagram "down") is (y, -x), and those of the anti-clockwise direction are minus these. Therefore the coordinates of M are given by:
Anti-clockwise ("up"): (U * cos(theta) - M * sin(theta), U * sin(theta) + M * cos(theta))
Clockwise ("down"): (U * cos(theta) + M * sin(theta), U * sin(theta) - M * cos(theta))
No need for calls to arctan or sqrt which are both very costly. Also you can compute sin/cos just once and use the results for both components.
From Pythogoras we know that
M = sqrt(U^2 + V^2)
angle between M and U is
alpha = arctan(V/U)
So then you know that the x- and y-coordinates for M are:
the "up" case:
M = (sqrt(U^2 + V^2)*cos(theta + sign(cosd(theta))*arctan(V/U)), sqrt(U^2 + V^2)*sin(theta + sign(cosd(theta))*arctan(V/U)))
the "down" case:
M = (sqrt(U^2 + V^2)*cos(theta - sign(cosd(theta))*arctan(V/U)), sqrt(U^2 + V^2)*sin(theta - sign(cosd(theta))*arctan(V/U)))
A second way to calculate this is to look add the length of U and V in the x and y direction, and sum them.
The coordinates of U are:
(Ucos(theta), Usin(theta))
To this coordinates we must add/substract the x-and y-coordinates of V. The length of V along x and y is:
(abs(sin(theta)), abs(cos(theta))
Whether one should add or substract these from U is dependent on theta. In general we can write Vup and Vdown as
Vup = (V*sign(-cos(theta))sin(theta), Vsign(cos(theta))*cos(theta))
Vdown = (V*sign(cos(theta))sin(theta), Vsign(-cos(theta))*cos(theta))
then we can alway add U to Vup and Vdown. Finally
Mup = U + Vup
Mdown = U + Vdown
Just another compact solution
theta = 30;
L = 2; % norm of U vector
U = L*[cosd(theta) ; sind(theta)];
Vup = [-U(2) ; U(1)] / L; % Normal vectors, unit length
Vdown = [U(2) ; -U(1)] / L;
Mup = U + Vup; % Two possible values of M
Mdown = U + Vdown;
% Bonus plot
figure
plot([0 U(1)] , [0 U(2)] , 'k-')
hold on; axis equal;
plot([0 Vup(1)]+U(1) , [0 Vup(2)]+U(2) , 'r-')
plot([0 Vdown(1)]+U(1) , [0 Vdown(2)]+U(2) , 'r-')
text(Mup(1),Mup(2),'M_u_p')
text(Mdown(1),Mdown(2),'M_d_o_w_n')
You can exploit the properties of the cross product of Uinit and Urot. The sign of the product will inform you on the orientation of the resulting vector.
Supposing that the origin is O(0,0), your initial vector is Uinit(x1,y1) and your final vector is Urot(x2,y2). Also M(x,y) can be calculated easily.
If you want to filter the rotated vectors Urot that ended up 'above' or 'below' M compared to the previous orientation of your triangle, you can take the following cross products:
M cross Uinit and M cross Urot.
If their sign is the same then the resulting rotated vector didn't cross the line OM and the opposite if the sign is different.
I have a Matlab code from my class in which the professor does the step of assigning each data point to the nearest cluster using this code where c is the centroids matrix and x is the data matrix.
% norm squared of the centroids;
c2 = sum(c.^2, 1);
% For each data point x, computer min_j -2 * x' * c_j + c_j^2;
% Note that here is implemented as max, so the difference is negated.
tmpdiff = bsxfun(#minus, 2*x'*c, c2);
[val, labels] = max(tmpdiff, [], 2);
I am not sure how this is equivalent to the algorithm definition of this step in which the cluster assignment is done through
% For every centroid j and for every data point x_i
labels(i) = `argmin||x_i - c_j||^2`
Can anyone please explain to me how this works, essentially how computing
min_j -2 * x' * c_j + c_j^2
is equivalent to
argmin||x_i - c_j||^2
If we have a triangle such that the length of its sides is a, b, c, then
we know that (from the law of cosines)
a^2=c^2+b^2-2bc*cos(alpha)
where alpha is the angle between the side with size b and the size with size c.
Now, consider the triangle made of the three vertices x, c_j and O (the origin of R^n). Writing theta the angle between x and c, we have
argmin_j||x-c_j||^2
=argmin_j (||x||^2+||c_j||^2 - 2*||x||* ||c_j|| * cos(theta) )
which is equal to
argmin_j(||x||^2 + ||c||^2 - 2x^t c_j)
Now, remember that x is constant in this minimization, so the last equation is just equal to
argmin_j(||c_j||^2 - 2 x^t c_j)
which is the equation you minimize in your code.
I have obtained fundamental matrix between two cameras. I also, have their internal parameters in a 3 X 3 matrix which I had obtained earlier through chess board. Using the fundamental matrix, I have obtained P1 and P2 by
P1 = [I | 0] and P2 = [ [e']x * F | e']
These projection matrices are not really useful in getting the exact 3D location.
Since, I have the internal parameters K1 and K2, I changed P1 and P2 as
P1 = K1 * [I | 0] and P2 = K2 * [ [e']x * F | e']
Is this the right way to get the real projection matrices which gives the actual relation between the 3D world and the image?
If not, please help me understand the right way and where I have gone wrong.
If this is the right approach, how do I verify these matrices?
A good reference book is "Multiple View Geometry in Computer Vision" from Hartley and Zisserman.
First, your formula for P is wrong. If you want the formula with K inside, it is rather
P = K * [R | t]
or
P = [ [e']x * F | e']
but not a mix of both.
If you computed F from the 8 points algorithm, then you can recover only projective geometry up to a 3D homography (i.e. a 4x4 transformation).
To upgrade to euclidian space, there are 2 possibilities, both starting by computing the essential matrix.
First possibility is to compute the essential matrix from F: E = transpose(K2)*F*K1.
Second possibility, is to estimate directly the essential matrix for these 2 views:
Normalize your 2D points by pre multiplying with inverse of K for each image ("normalized image coordinates")
Apply the (same than for F) 8 points algorithm on these normalized points
Enforce the fact that the essential matrix has its 2 singular values equal to 1 and last is 0, by SVD decomposition and forcing the diagonal values.
Once you have the essential matrix, we can compute the projection matrix in the form
P = K * [R | t]
R and t can be found thanks to the elements of the SVD of E (cf the previously mentioned book).
However, you will have 4 possibilities. Only one of them projects points in front of both cameras, so you shall test a point (if you are sure of it) to remove the ambiguity among the 4.
And in this case you will be able to place the camera and its orientation (with R and t of the projection) in your 3D scene.
Not so obvious, indeed...
Just came across this question and want to give a more direct answer to the question.
When P1 = [I, 0] is your first projection matrix but it should be P1 = K1 * [I, 0], then your "world" is distorted by the 4x4 matrix M = [K1, 0; 0, 1]. Any point X in the world projects to x1 = P1 * X = (P1 * M) * (M^-1 * X) = P1' * X' where X' is now the point in the "undistorted world" (note that X = M * X' is again the point in the "distorted world") and P1' = P1 * M = [I, 0] * [K1, 0; 0, 1] = K1 * [I, 0] is the projection matrix in the undistorted world.
Analoguously, P2' = P1 * M is the projection matrix in the undistorted world and has the form P2' = [ [e']x * F | e'] * [K1, 0; 0, 1] = [ [e']x * F * K1 | e'].
Note that P2 = [ [e']x * F | e'] is just one possible projection matrix but in general has the form P2 = [ [e']x * F + e' * v^T | s * e'] for some real s and a 3-vector v. Note further, that if you want to find a projection matrix of the form P2' ~ K2 * [R, t] for some rotation matrix R, you might be better off using the algorithm based on the essential matrix outlined by Damien and described in Hartley&Zisserman(2.Ed) Sec. 9.6.2.
I have an ellipse in 2 dimensions, defined by a positive definite matrix X as follows: a point x is in the ellipse if x'*X*x <= 1. How can I plot this ellipse in matlab? I've done a bit of searching while finding surprisingly little.
Figured out the answer actually: I'd post this as an answer, but it won't let me (new user):
Figured it out after a bit of tinkering. Basically, we express the points on the ellipse border (x'*X*x = 1) as a weighted combination of the eigenvectors of X, which makes some of the math to find the points easier. We can just write (au+bv)'X(au+bv)=1 and work out the relationship between a,b. Matlab code follows (sorry it's messy, just used the same notation that I was using with pen/paper):
function plot_ellipse(X, varargin)
% Plots an ellipse of the form x'*X*x <= 1
% plot vectors of the form a*u + b*v where u,v are eigenvectors of X
[V,D] = eig(X);
u = V(:,1);
v = V(:,2);
l1 = D(1,1);
l2 = D(2,2);
pts = [];
delta = .1;
for alpha = -1/sqrt(l1)-delta:delta:1/sqrt(l1)+delta
beta = sqrt((1 - alpha^2 * l1)/l2);
pts(:,end+1) = alpha*u + beta*v;
end
for alpha = 1/sqrt(l1)+delta:-delta:-1/sqrt(l1)-delta
beta = -sqrt((1 - alpha^2 * l1)/l2);
pts(:,end+1) = alpha*u + beta*v;
end
plot(pts(1,:), pts(2,:), varargin{:})
I stumbled across this post while searching for this topic, and even though it's settled, I thought I might provide another simpler solution, if the matrix is symmetric.
Another way of doing this is to use the Cholesky decomposition of the semi-definite positive matrix E implemented in Matlab as the chol function. It computes an upper triangular matrix R such that X = R' * R. Using this, x'*X*x = (R*x)'*(R*x) = z'*z, if we define z as R*x.
The curve to plot thus becomes such that z'*z=1, and that's a circle. A simple solution is thus z = (cos(t), sin(t)), for 0<=t<=2 pi. You then multiply by the inverse of R to get the ellipse.
This is pretty straightforward to translate into the following code:
function plot_ellipse(E)
% plots an ellipse of the form xEx = 1
R = chol(E);
t = linspace(0, 2*pi, 100); % or any high number to make curve smooth
z = [cos(t); sin(t)];
ellipse = inv(R) * z;
plot(ellipse(1,:), ellipse(2,:))
end
Hope this might help!
The following diagram is a schematic of a lake, and the equation illustrates how to calculate the effective heat flux of a lake.
where S is a vector of surface fluxes, q is short wave radiation, h is depth of the mixed layer, and z is the depth of the lake. For example:
q0 = 400+(1-400).*rand(100,1); % This is the short wave radiation
kd = 0.8; % extinction coefficient
h = 10; % depth of the surface mixed layer
for i = 1:length(q0); % loop for calculating short wave radiation at depth h
qh(i) = q0(i).*exp(-kd*h); % here, qh is calculated according to the Lambert Beer law
end
given
dz = 0.5
and z varies from 0 (surface) to depth h in increments of dz i.e.
z = 0:dz:h
how would I calculate the last portion of this equation in matlab i.e. how to calculate q at depth z between the surface and h? which is expressed here as an integral?
Apologies if this should be on another one of the stack overflow forums but it seems more related to programming than pure physics or maths questions.
To integrate this correctly, you will need compute all values of q(z) in the range [0, h]. If q0 and qh are N-by-1 column vectors, this means that q should be an N-by-M matrix, where M is the number of sample points in the range [0, h].
First, lets define z properly:
z = linspace(0, h, 200); %// M=200, but it's an arbitrary number to your choosing
The computation of q can be reduced to:
q = q0 * exp(-kd * z);
and qh actually equals to the final column of q, i.e q(:, end).
The integral itself can be approximated to a sum and computed using sum:
dz = z(2) - z(1);
I = sum(q, 2) * dz;
P.S.
Since q(z) = e(-kd ·z), it's simple enough for you to compute the integral analytically:
I = q0 * (1 - exp(-kd * h)) / kd;