How to get full access to one dimension in OpenCV mat? - c++

Ok, My problem is not accessing one element from the mat, but I want to get the whole mat while one dimension is fixed. Let's say we have a three dimension matrix and I want to access the third dimension which should return a rows*cols mat.
In matlab, this is extremely easy, say A is a three dimension matrix(3*3*3), if we want to access the the third dimension, then just use A(:,:,1), A(:,:,2) A(:,:,3). But how should we do in OpenCV? It seems that OpenCV didn't provide this method?
I am asking this because I have a vector of Mat: Vector frames, each element in the vector is a two dimension gray image. I want to change the vector format into a three-dimensional Mat format. But I just don't know how to copy it. The ideal way should be:
for(int i=0; i<frames.size(); i++) {
A(:,:,i) = frames[i].clone();
}
How should I do this? Thanks!

To answer your specific question on how to combine 3 channels into one image, you would use merge like so:
merge(frames, A);
For the more general question of how to access 2D planes of a 3D Mat, hopefully this tutorial will give you some insight. Specifically how the B, G and R components of a Mat are interleaved on each row like so (they have a much better image in the tutorial):
| Col 1 | Col 2 | Col 3 | Col 4 |...
Row 1 |B G R | B G R | B G R | B G R |...
Row 2 |B G R | B G R | B G R | B G R |...
Row 3 |B G R | B G R | B G R | B G R |...
...

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...

3D Reconstruction: Solving Equations for 3D Points from Uncalibrated Images

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.

Merging linear chain of vertices in a Graph (in C++)

I have a large graph and it is represented in adjacency list. I would like to compress the graph by merging the linear chain of nodes. For example, if the edges are a-c, b-c, c-d, d-e, e-f, e-g:
a - c - d - e - f
| |
b g
Then c-d, d-e can be merged to a single node x and the new edge list should have a-x, b-x, x-g. I would like to implement it in C++, but I am wondering if there is any C++ graph library which handles this. Also, any suggestion for a efficient algorithm is appreciated.
I think you example might be broken so I am going to solve a slightly different one:
a - c - i - d - e - f
| |
b g
|
h
I think the solution looks like:
a - c - x - e - f
| |
b h
If you agree, then consider counting the number of times each vertex appears in the adjacency list, and storing the first two neighbors for each:
a b c d e f g h i
1 1 3 2 3 1 2 1 2
c c a i d e e g c
b e g h d
The places where it is 2, we can consider collapsing: at d, g, and i:
d g i # candidates
2 2 2
i e c
e h d
Now you can see g has two neighbors not in the candidates, so simply delete g because it is a singleton "chain." This leaves d, whose neighbor i is in the candidates, so collapse d and i into a new vertex x and you're done.
You simply need to remove all nodes with degree 2, merging their two neighbors into a single node.
Repeat the process till no such nodes are left.
The Boost Graph library is usually a good way to store and work with graphs. See here how to merge vertices and contract the edge.

Eigen Library:: How do I create a block diagonal sparse matrix out of existing sparse matrices?

I have a bunch of (n*n) sized sparse matrices called M1, M2... , Mj.
I want to create a large block-diagonal sparse matrix that looks like this:
|M1 0 0 . . . |
|0 M2 0 . . . |
|. . . . . . |
|. . . Mj-1 0|
|0 0 0 ... Mj|
I tried the following:
Eigen::SparseMatrix<double> MatBLK(j*n,j*n);
MatBLK.reserve(Eigen::VectorXd::Constant(j*n,3);
//I know that there are at most 3 nonzero elements per row
MatBLK.topLeftCorner(n,n) = M1.topLeftCorner(n,n);
MatBLK.block(n,n,n,n) = M2.topLeftCorner(n,n);
.
.
MatBLK(bottomRightCorner(n,n)) = Mj.topLeftCorner(n,n);
MatBLK.makeCompressed();
This method is not working. The values in the smaller matrices aren't getting copied to the larger Block Matrix. The function:
MatBLK.nonZeros()
returns 0.
I am new to this library. Any help would be greatly appreciated.
Unfortunately it looks like you can't assign sparse matrices in that way due to how inefficient the resulting code would be. This forum post is almost 2 years old but it seems things are still the same (https://forum.kde.org/viewtopic.php?f=74&t=112018)
You have to assign entries one by one, either with direct assignment or triplets.
A.block(i,j,m,n) = B;
becomes
for (int ii = i; ii < i+m; ++ii) {
for (int jj = j; jj < j+n; ++jj) {
// direct assignment
A.insert(ii, jj) = B(ii - i, jj - j);
// triplets
triplets.push_back(Triplet(ii, jj, B(ii-i,jj-j)));
}
}

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.