3D Reconstruction: Solving Equations for 3D Points from Uncalibrated Images - computer-vision

This is a pretty straightforward question (I hope). The following is from 3D reconstruction from Multiple Images, Moons et al (Fig 2-13, p. 348):
Projective 3D reconstruction from two uncalibrated images
Given: A set of point correspondences m1 in I1 and m2 in I2 between two uncalibrated images I1 and I2 of a static scene.
Aim: A projective 3D reconstruction ^M of the scene.
Algorithm:
Compute an estimate ^F for the fundamental matrix
Compute the epipole e2 from ^F
Compute the 3x3-matrix
^A = −(1/||e2||2) [e2]x ^F
For each pair of corresponding image points m1 and m2, solve the following system of linear equations for ^M :
^p1 m1 = ^M and ^p2 m2 = ^A ^M + e2
( ^p1 and ^p2 are non-zero scalars )
[I apologize for the formatting. I don't know how to put hats over characters.]
I'm pretty much OK up until step 4. But it's been 30+ years since my last linear algebra class, and even then I'm not sure I knew how to solve something like this. Any help or references would be greatly appreciated.
By the way, this is sort of a follow-on to another post of mine:
Detecting/correcting Photo Warping via Point Correspondences
This is just another way to try to solve the problem.

Given a pair of matching image points m1 and m2, the two corresponding rays from the optical centers are unlikely to intersect perfectly due to noise in the measurements. Consequently a solution to the provided system should instead be found in the (linear) least square sense i.e. find x = argmin_x | C x - d |^2 with (for instance):
/ 0 \ / \
| I -m1 0 | | M |
C x = | 0 | | |
| 0 | | p1 |
| A 0 -m2 | \ p2 /
\ 0 /
and
/ 0 \
| 0 |
d = | 0 |
| |
| -e2 |
\ /
The problem has 5 unknowns for 6 equations.
A possible alternative formulation exploits the fact that m1 and m2 are collinear with M so m1 x M = 0 and m2 x (A M + e2) = 0 yielding the linear least squares problem x = argmin_x | C x - d |^2 with:
/ [m1]x \ / \
C = | | | M |
\ [m2]x A / \ /
and
/ 0 \
d = | |
\ -m2 x e2 /
where [v]x is the 3 x 3 matrix of the cross product with v. The problem has 3 unknowns for 6 equations which can be reduced to 4 only by keeping non-linearly dependent ones.

Related

Eigen3/C++: Tile a MatrixXd with a Vector3d

What is the most elegant way in 'Eigen3/C++' to construct a MatrixXd
from a repeated Vector3d. That is, given a row vector
Eigen::Vector3d V(v00, v01, v02);
the goal is to find an operation op such that
Eigen::MatrixXd M = op(V, N);
delivers a matrix M consisting of N rows which are equal to V, i.e.
/ v00 v01 v02 \
| v00 v01 v02 |
M = | ... |
| |
\ v00 v01 v02 /
similar to what can be achieved by tile in numpy.
vectorwise and dense expressions can replicate:
V.rowwise().replicate(N).transpose() // or
V.transpose().colwise().replicate(N) // or
V.transpose().replicate(N,1) // or ...
of which there are also corresponding versions when N and/or the direction is known at compile time...

C++ Rotating Cube in Coordinates (non-draw)

I've been looking for this for quite a long time without any results, been trying to figure out the math for this myself for about a week+.
My goal is to set my cursor position(s) so in the way that it forms a rotating cube much in the way like an OpenGL rotating cube border box would.
Since OpenGL has a rotate function built it, it's not really something I can adapt to.
I just wonder if anyone has any ideas how I'd go about this.
If you're wondering what the point of this is, on each created frame(cube rotating point) it has a function to erase anything drawn in MsPaint and then the next positions begin drawing, basically to create a spinning cube being drawn.
If you try to rotate cube in C without help of any specialized library you should use Matrix operations to transform coordinates.
You sohuld get roatation matrix (Let's call it M)
You should multiply M to your coordinates vector - result is new
coordinates.
for 2D rotation, example (f - rotation angle, +- is rotation direction):
|cos f +-sin f| |x| |x'|
| | | | = | |
|+-sin f cos f| |y| |y'|
for 3D rotation, you should use 3x3 marix. Alsoo you should rotation axis, depending on it you should choose matrix M:
Mx (rotate around x axis):
|1 0 0 ||x| |x'|
|0 cos f -sin f||y| = |y'|
|0 sin f cos f||z| |z'|
My (rotate around y axis):
|cos f 0 sin f ||x| |x'|
| 0 1 0 ||y| = |y'|
|-sin f 0 cos f ||z| |z'|
Mz (rotate around z axis):
| cos f -sin f 0 ||x| |x'|
| sin f cos f 0 ||y| = |y'|
| 0 0 1 ||z| |z'|

Solve set of modular equations in C++

I am working on Quadratic Sieve algorithm in c++. And after Gaussian elimination I need to solve set of modular equations such as, for example :
(1) b + c = 0 mod 2
(2) a + c = 0 mod 2
Here the symbol = is used to mean "is congruent to". I am processing matrix as shown here:https://math.stackexchange.com/questions/289348/matrix-processing-in-the-quadratic-sieve?rq=1. If anyone has any ideas how to implement such a function that will solve these equations I would appreciate it.
You can rewrite this system in matrix notation:
M . X = S
|0 1 1|.|a| = |0|
|1 0 1| |b| |0|
|c|
Then you solve it as usual using Gaussian elimination. The small difference is that you only work with the values 0 and 1 and that substracting a row is the same as adding the row (in Z/2Z, -a = a)

Explanation of the Perspective Projection Matrix (Second row)

I try to figure out how the Perspective Projection Matrix works.
According to this: https://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml
f = cotangent(fovy/2)
Logically I understand how it works (x- and y-Values moving further away from the bounding box or vice versa), but I need an mathematical explanation why this works. Maybe because of the theorem of intersecting lines???
I found an explanation here: http://www.songho.ca/opengl/gl_projectionmatrix.html
But I don't understand the relevent part of it.
As for me, an explanation of the perspective projection matrix at songho.ca is the best one.
I'll try to retell the main idea, without going into details. But, first of all, let's clarify why the cotangent is used in OpenGL docs.
What is cotangent? Accordingly to wikipedia:
The cotangent of an angle is the ratio of the length of the adjacent side to the length of the opposite side.
Look at the picture below, the near is the length of the adjacent side and the top is the length of the opposite side .
The fov/2 is the angle we are interested in.
The angle fov is the angle between the top plane and bottom plane, respectively the angle fov/2 is the angle between top(or botton) plane and the symmetry axis.
So, the [1,1] element of projection matrix that is defined as cotangent(fovy/2) in opengl docs is equivalent to the ratio near/top.
Let's have a look at the point A specified at the picture. Let's find the y' coordinate of the point A' that is a projection of the point A on the near plane.
Using the ratio of similar triangles, the following relation can be inferred:
y' / near = y / -z
Or:
y' = near * y / -z
The y coordinate in normalized device coordinates can be obtained by dividing by the value top (the range (-top, top) is mapped to the range (-1.0,1.0)), so:
yndc = near / top * y / -z
The coefficient near / top is a constant, but what about z? There is one very important detail about normalized device coordinates.
The output of the vertex shader is a four component vector, that is transformed to three component vector in the interpolator by dividing first three component by the fourth component:
,
So, we can assign to the fourth component the value of -z. It can be done by assigning to the element [2,3] of the projection matrix the value -1.
Similar reasoning can be done for the x coordinate.
We have found the following elements of projection matrix:
| near / right 0 0 0 |
| 0 near / top 0 0 |
| 0 0 ? ? |
| 0 0 -1 0 |
There are two elements that we didn't found, they are marked with '?'.
To make things clear, let's project an arbitary point (x,y,z) to normalized device coordinates:
| near / right 0 0 0 | | x |
| 0 near / top 0 0 | X | y | =
| 0 0 ? ? | | z |
| 0 0 -1 0 | | 1 |
| near / right * x |
= | near / top * y |
| ? |
| -z |
And finally, after dividing by the w component we will get:
| - near / right * x / z |
| - near / top * y / z |
| ? |
Note, that the result matches the equation inferred earlier.
As for the third component that marked with '?'. More complex reasoning is needed to find out how to calculate it. Refer to the songho.ca for more information.
I hope that my explanations make things a bit more clear.

How to convert a Eigen::Quaternion<float> to a Matrix4f?

As the title says, i have a problem to convert a Quaternion to a Matrix4f. Eigen has the method Quaternion.toRotationMatrix() which gives me a Matrix3f.
Now i need a Matrix4f ( because our program is designed to take only Matrix4f), is there an easy way to achieve this?
#Zacharias' answer contains the necessary theory. I just reiterate my earlier comment I made there with the actual Eigen C++ code.
Eigen::Matrix3f mat3 = Eigen::Quaternionf(W, X, Y, Z).toRotationMatrix();
Eigen::Matrix4f mat4 = Eigen::Matrix4f::Identity();
mat4.block(0,0,3,3) = mat3;
Eigen::Matrix4f::Identity() takes care of initializing the ones and zeros of the 4th and last row and column. mat4.block(0,0,3,3) = mat3 then overwrites the values obtained from the rotation matrix.
M3 to M4
The answere is already there, given by Rob and Najzero.
In most cases, it will be sufficient to construct the matrix as follows:
m3:
|a00|a01|a02|
|a10|a11|a12|
|a20|a21|a22|
to m4:
|a00|a01|a02| 0 |
|a10|a11|a12| 0 |
|a20|a21|a22| 0 |
| 0 | 0 | 0 | 1 |
The 4x4 matrix does not only allow to rotate a vector, but also to shift(translate) and scale (in all 3 directions) any vector. So basically you got a full transformation matrix - thats why it is often used in computer graphics, describing the transformation of an object. Depending on row-column order, we might identify the matrix as:
|rot|rot|rot| sx |
|rot|rot|rot| sy |
|rot|rot|rot| sz |
| x | y | z | 1 |
with sx,sy,sz as scaling coefficients, and x,y,z as translation coefficients.
PS: of course, if you want to rotate a vector with m4, you will than have to use a 4-dimensional vector, e.g. (x,y,z,w) with w=1 (in most cases).
The direct approach
Convert Quaternion rotation to rotation matrix?
And my personal recommendation:
http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToMatrix/
There you will find also other transformations, backtrafos and so on.