OpenCV -SolvePNP how to compute guess from world coords - c++

For cv::SolvePNP, I would like to provide an initial guess for translation and rotation.
For the guess, I have the translation in world space and the rotation as up and direction vector (or Euler angles).
How do we transform the world space translation and up/direction vector to the correct format so cv:: SolvePNP can use it as as proper guess in the correct coordinate system?
I use useExtrinsicGuess=true, and provide tvec and rvec.
I computed a rotation matrix from the up and direction vectors, though there seems to be different conventions.
And then convert the rotation matrix with Rodrigues to rvec.
We use
Tvec=-R*worldspace_tvec.
However, the results are clearly not right as the guess places the resulting tvec and rvec in a different place once converting it back to Euler/world space translation.
Is there a fast way to go from up/direction vectors and world space translations to the correct tvec and rvec inputs for SolvePNP?
Thanks in advance.

Related

How to flip only one axis of transformation matrix?

I have a 4x4 transformation matrix. However, after trying out the transformation I noticed that movement and rotation of the Y axis is going the opposite way. The rest is correct.
I got this matrix from some other API so probably it is the difference of coordinate system. So, how can I flip an axis of transformation matrix?
If only translation I can add minus sign on the Y translation, but I have no idea about opposite rotation of only one axis since all the rotation is being represented in the same 3x3 area. I thought there might be some way that even affect both translation and rotation at the same time. (truly flipping the axis)
Edit: I'm pretty sure the operation you're looking for is changing coordinate systems while maintaining Z-up or Y-up. In this case, try setting all the elements of the second column (or row) of your matrix to their inverse.
This question would be better for the Math StackExchange. First, a really helpful read on rotation matrices.
The first problem is the matter of rotation order. I will be assuming the XYZ rotation order. We know the rotation matrices for each axis is as follows:
Given a matrix derived from the same rotation order, the resulting matrix would be as follows, where alpha is the X angle, beta is the Y angle, and gamma is the Z angle:
You can derive the individual components of each axis angle from this matrix. For example, you can derive the Y angle from -sin(beta) using some inverse trig. Given beta, you can derive alpha from cos(beta)sin(alpha). You can also derive gamma from cos(beta)sin(gamma). Note that the same number in the matrix can represent multiple values (e.g. sin(0)=0 and sin(180)=0).
Now that you know alpha, beta, and gamma, you can reverse beta and remake the rotation matrix.
There's a good chance that there's a better way to do this using quaternions, but you should ask the Math StackExchange these kinds of language-agnostic questions.
Much shorter answer: if you are not careful with your frame orientation many things down your pipeline are likely to have a bad hair day. The reason is "parity", a.k.a. "frame orientation", a.k.a. "right-handedness" (or rarely left-handedness). Most 3D geometry tools and libraries that work together normally assume implicitly that all coordinate systems in play are right-handed (or at least consistently-handed). Inverting the orientation of just one axis in a coordinate system changes its orientation from right to left handed or viceversa.
So, suggestion for things to check & try in your problem:
Check that the frame you get from your API is right-handed. You do so
by computing the determinant of the 3x3 rotation part of your 4x4 transform matrix: it must be +1 or very close to it.
If it is -1, then flip one if its axis, i.e. change the sign of one of the columns of the 3x3 rotation.
Note carefully: I said "columns" because I assume that you apply a transform Q to a point x by multiplying as Q * x, x being a 4x1 column vector with the last component equal to one. If you use row vectors left-multiplied by Q you need flip a row.
If that determinant is +1, you have a bug someplace else.

use SolvePnP Rotation and translation vector in OpenGL

I'm working on an AR program. I have done this steps:
Detect corners of a chess board with OpenCV
Use SolvePNP to find rvec and tvec
Apply Rodrigues on rvec to get R_mat
Use hconcat(R_mat, tvec, P); to concatenate R_mat and tvec to get Projection matrix
Apply decomposeProjectionMatrix on P to get new translation,T2, vector and eulerAngles
now my problem is in translation vectors just tvec[2] or translation over Z-axis is correct
and in rotations again in Euler Angles (from decomposeProjectionMatrix) just eulerAngles[2] or rotation around z-axis is correct.
I don't know hoa can I get Translation and Rotation related to X-axis and Y-axis correctly.
I'm gonna use these in OpenGL to Augment a cube on the pattern.
In my code, result of translation over X and Y axis is very larger than windows size; and rotaion around X and Y axis are very small and always near the zero (less than 0.0001)
Any Idea how to get correct meaningful T and R?
P.S : I'm using an Identity matrix as camera matrix and zero matrix for dist coeff matrix.

Matrix multiplication to mirror translation and rotation of only 1 axis?

I'm using OpenGL with some other library. This library will provide Projection Matrix and I cannot modify it. I have to provide only ModelViewMatrix.
However, strange things happen. Only y-axis translation and rotation are inverted.
For example if I increase x translation in the ModelViewMatrix then the object will go to the right just fine. (positive x direction) but in y-axis it is reversed. I want it to go the other way.
Rotation in y-axis also got reversed. It is rotation opposite of the way it should be.
I cannot fix it on ProjectionMatrix, so I think I might have to multiply my ModelViewMatrix with something that can reverse one axis before send it to the library. Do you know that something? A matrix that can reverse 1 axis?
it's just a matrix with elements [1,0,0,0][0,-1,0,0][0,0,1,0][0,0,0,1]
in other words an identity matrix with the second diagonal element negated.

OpenGL camera direction

So I was reading this tutorial's "Inverting the Camera Orientation Matrix" section and I don't understand why, when calculating the camera's up direction, I need to multiply the inverse of orientation by the up direction vector, and not just orientation.
I drew the following image to illustrate my insight of the tutorial I read.
What did I get wrong?
Well, that tutorial explicitely states:
The way we calculate the up direction of the camera is by taking the
"directly upwards" unit vector (0,1,0) and "unrotate" it by using the
inverse of the camera's orientation matrix. Or, to explain it
differently, the up direction is always (0,1,0) after the camera
rotation has been applied, so we multiply (0,1,0) by the inverse
rotation, which gives us the up direction before the camera rotation
was applied.
The up direction which is calculated here is the up direction in world space. In eye space, the up vector is (0,1,0) (by convention, one could define it differently). As the view matrix will transform coordinates from world space to eye space, we need to use the inverse to transform that up vector from eye space to the world space. Your image is wrong as it does not correctly relate to eye and world space.

How to know that object has been rotated only in 15 degree chunks in 3D?

I have an 3D object in 3D space oriented in some orientation. How can I know it has been rotated from its initial rotation q (in euler angles: 0, 0, 0) only in arbitrary number of 15 degree rotations in any axis. E.g, rotated in X-axis 4*15 degrees, and in Y-axis 7*15 degrees and in Z-axis 13*15 degrees. How can I detect this?
I have tried to take euler angles from the object's rotation matrix but it seems to detect the situation correctly only if I rotate only in one axis. If I start to mix X,Y and Z axis 15 degree rotations, the euler angles gets messed up.
I am 100% sure that the object has been rotated only in 15 degree chunks.
Rotation matrices can only be decomposed into quaternions, I believe, and cannot be decomposed into per-axis rotations.
I am not sure what math library you are using, but, if provided, you could use quaternions, which will quite straightforward the functionality you want. They can be translated to rotation matrices afterwards.
Rotations are not commutative, therefore describing them with Euler angles is problematic if you don't know the right order. If you know the order, you can set up an equation system with a multiplication of three rotation matrices (parameterized by the rotation angle) on one side and the final rotation matrix on the other side. Gives you three equations and three unknowns. But watch out for singularities in Euler angle representation!
If you can, the dead simplest way is to store both the components (float3 m_Translation, m_Rotation, m_Scale) and a matrix that is updated whenever they change (float4x4 m_Matrix). To get the data out, simply grab the vector for that part and return it. The memory use is small (12-16 floats) and computational overhead is minimal (recalculate the matrix when a part is updated).
However, if that can't be done, Google suggests you can decompose rotation matrices with a bit of work like so. It does take a chunk of math.
As noted in that page, the D3DX libraries also have a function to decompose matrices: D3DXMatrixDecompose.