cv::remap (in opencv) and interp2 (matlab) - c++

I am trying to look for an equivalent opencv function for interp2 and I understand that
cv::remap is a good way of doing this.
However, if I have the following:
f2 = interp2( x, y, f, x2, y2, 'bicubic' );
where x, y, x2 and y2 are all (say m x n) matrices, I am not sure how to use cv::remap for this.
How would I use remap for this? I know I have to convert it to a map ... but I'm unable to do so.
And,is there anything else that could do interp2 the way the matlab function does it?

In case you didn't find your answer yet, this is how you should use it.
remap(f,f2,x2,y2,CV_INTER_CUBIC);
The function remap supposes that you're working on exactly the grid where f is defined so no need to pass the x,y monotonic coordinates. I'm almost sure that the matrices cannot be CV_64F (double) so, take that into account.

interp2 is interpolator - if you get x,y and f values for some mesh it gives you the value f2 for x2 and y2.
remap - wraps your mesh by moving x and y coordinates acording to the deformation maps.
if you want interpolate regular mesh then use scaling (cv::resize for example).
If data is scattered then you can use Delaunay triangulation and then barycentric interpolation as variant or inverse distance weighting.

Related

Get two vector rotations to obtain one vector direction

I do not know how to approach this math problem. Any hint would be much appreciated. Before I could solve such problem using Atan2 method to get two vector angles, when axes c and a are orthogonal.
Problem: there are two non orthogonal to each other vectors c and a. I need to rotate one time around vector c then around vector a to obtain vector v orientation.
Question: how can I get c and a vector rotations, when I only know vector v orientation?
In the image below, c and a vector rotations are both 0.
I was using atan2 for orthogonal system to get two rotations, but in this cases axis A is not perpendicular to C.
double RotationC = Math.Atan2(V_.X, V_.Y);
double RotationA = Math.Atan2(Math.Sqrt(V_.X * V_.X + V_.Y * V_.Y), V_.Z);

Sort points in vector to form conture

I got a vector with n rows with xy coordinates of points. These points form a conture of an given CAD model. Now I want to restore the conture of the model. So I tried to sort the point with the atan2 function.
This is the code I use to sort the points.
std::sort(matrix.begin(), matrix.end(), sort1);
matrix.erase(std::unique(matrix.begin(), matrix.end(), compare2),matrix.end());
matrix.push_back(std::vector<double>(3, 0));
So first I sort the points in the vector matrix. As compare function i use this code
bool sort1(vector<double> const& s1, vector<double> const& s2)
{
return atan2(s1[1],s1[0])<atan2(s2[1],s2[0]);
}
After the vector has been sorted, I just delete duplicates to reduce the size of the vector. The last step is to push back the first point to the end of the vector to close the conture.
For standard models like a cube, or a ball this works fine, but for more complicate models the atan2 function is note working fine.
So this image show the unsorted points.
When I sort the vector I get this conture as result
My first approach was to check the atan2 function but it's working fine. The problem seem to be the result of the atan2 function. So this list shows the actual coordinates and the result of the atan2 function
x y z atan2
-5.44283 -1.94995 0 -2.79758
-5.36969 -1.93228 0 -2.79617
-5.33637 -1.92454 0 -2.79547
-13.15 -4.76500 0 -2.79395
-5.26308 -1.90750 0 -2.79389
-5.22970 -1.90005 0 -2.7931
-5.15626 -1.88364 0 -2.79134
As you can see while the x and y coordinate change the atan2 stays in the same range as the other values. For me that's the problem, why my conture isn't correct. Do I have to add something to my sort function to get the correct results?
One idea i had was to sort the coordinates not just by the atan2, but also by the length of the vector between the point, with the lowest atan2, and all other points. But here's my problem. I would first sort by atan2, and then sort again by the length. But the second sort process would destroy the hole result of the first sort function.
atan2 obviously won't help in generic case. It is mostly good for convex figures. Consider a narrow rectangle with (0,0) inside and an adjacent rectangle and try to sort their points by their atan2.
Have you tried painting a point in the set and then looking for the closest not yet painted point as an iteration step?
If you're dealing with curves only then I'd suggest to use following algorithm:
Define angle range R
Take initial point A, mark it as visited
Find closest to A point B, mark it as visited
Calculate the direction formed by vector [A, B]
Find closest to B unvisited point C in angle range R and mark it visited
Go to step 4 with B as A and C as B
This is not an ultimate solution but it should be able to find basic curves and some polygons. With wider angle range R you can approximate more curved lines.

Floating-point error when checking for coplanar 3D points

I am looking for an algorithm to check if a point is coplanar with a given 3D plane, defined out of three vertices, while minimizing floating point errors.
I would like to minimize the amount of multiplications and division to mitigate floating point errors.
My implementation uses floats, I cannot go double.
I cannot use an external library.
My current method suffers from these errors:
I have code defining a plane using the general form of the plane equation:
ax + by + cz + d = 0
I compute these coefficients using three 3D vertices v0, v1 and v2 as follow:
// Pseudo-code to define a plane (with class Vector3 defining a vector in 3D)
Vector3 A = v1 - v0;
Vector3 B = v2 - v0;
Vector3 N = cross_product(A,B); // Normal vector
N.Normalize(); // Unit normal vector storing coefs. a, b, c
float d = dot_product(N,v0);
To check if another vertex p is coplanar, I plug the point into the plane equation and check if the result is 0:
// Pseudo-code for coplanar test:
bool is_coplanar()
{
float res = N.x()*p.x() + N.y()*p.y() + N.z()*p.z() - d;
return true if res is "almost" null; // "almost" is: abs(res)<EPSILON
}
My code fails in this case:
v0 = [-8.50001907, 0, 323]
v1 = [8.49998093, 0, 323]
v2 = [-8.50001907, 1.49999976, 322.598083]
Then the plane coefficients are:
N = [-0, 0.258814692, 0.965926945]
d = 311.994415
And when I plug the point v2, I find a result "far" from 0 (although v2 was used to define the plane):
res = -3.05175781e-05
My EPSILON is currently 1e-5.
Tested on compiler qcc 4.4.2 (QNX Momentics, similar to gcc). With no optimization -O0.
Such geometric predicates suffer in a lot of ways from floating point errors. The only industrial strength solution is to use adaptable arithmetic filtering (provided that a robust implementation of the coplanar test is not covering you).
Luckily such implementations (that would take quite some time to write) are already available. In the previous link the orient3d predicate does what you need: Given 3 plane forming points, decide whether a 4th one lies above,below or on the plane
If such an implementation is an overkill, check the simple one. It offers 4 in total:
orient3dfast() Approximate 3D orientation test. Nonrobust.
orient3dexact() Exact 3D orientation test. Robust.
orient3dslow() Another exact 3D orientation test. Robust.
orient3d() Adaptive exact 3D orientation test. Robust.
Disclaimer: The code listing is provided as a tutorial of the mathematical concepts and programming techniques needed to reach a robust solution. I'm neither suggesting nor implying copy-pasting anything.

How to get the vector direction between two (p1, p2)?

I have been working on Unigine and been trying to code a flight program for weeks, I need to find the direction between two dummy nodes so I can use this direction to rotate the wings of the aircraft. Any explanation would be appreciated.
First you have to calculate the length of the distance between P1 and P2.
distance = abs(P2(y) - P1(y))
Then you can use the angular functions to calculate the angle.
a = sin(distance / length(P12))
As already stated in the comments, the vector from P1 to P2 is given by P = P2 - P1.
The direction can be attained in two ways.
1. Directly compute angle = tan_inverse( P.y() / P.x() ).
In this method however, 1st quadrant and 3rd quadrant are treated in the same way as the signs cancel out.
2.You can normalize this vector to get a unit vector. This is the preferred way since it alleviates the quadrant issues.
P(normalized) = P / (mod(p))
Now you can get the projection of any vector in this direction by just calculating the dot-product by this unit vector.
I just randomly came across this question and therefore it might be useful for someone else to read some more useful information here, regardless of the fact that this question has been asked years ago.
Currently, there is no accepted answer, which could mean that it wasn't very clear what the OP was asking so I'll confront two problems here.
Finding the direction of a vector
I am not very fluent in C++ so I'll
go one abstraction below and write C. Consider the following function
double get_vector_direction (vector v)
{
return atan2(v.q.y - v.p.y, v.q.x - v.p.x); /* atan(ratio) */
}
As simple as this! Also, I like to define vectors this way:
typedef struct POINT { double x, y; } point;
typedef struct VECTOR { point p, q; } vector;
the atan family of functions returns the inverse tangent and this function returns the direction of a vector, which is the measure of the angle it makes with a horizontal line (in radians).
There is a diagram in the answers here that shows the horizontal line as the x component of a vector. It's a simplistic implementation of a Cartesian to Polar coordinates conversion.
Finding the distance between the initial and terminal point
You may also want to know the magnitude of the vector, which could be obtained using the distance formula: sqrt(pow(v.q.x-v.p.x, 2)+pow(v.q.y-v.p.y, 2));
The two functions make up direction() and distance() which are the two most essential functions when dealing with algebra during game development. I would also recommend vectoradd and maybe even vectorsub and of course, radtodeg to convert radians to degrees if the angle is to be showed to the player.
If under the direction you mean angle w.r.t. an arbitrary vector (let it be (p1,p3)), then you can calculate the angle using:
angle = arcos( (p1,p2) * (p1,p3) / (modulus((p1,p2)) * modulus((p1,p3)) ))
where * is the dot product. The angle will be in radians. To change it to degrees you can multiply it by 180/PI (PI=3.1415926...). Modulus is length of vector:
modulus((p1,p2))=square root((p1,p2) * (p1,p2)).
The answer is rather about math than C++ but the implementation of the simple formula is straightforward.

Efficient C++ quaternion multiplication using cv::Mat

I want to multiply 2 quaternions, which are stored in a cv::Mat structure. I want the function to be as efficient as possible. I have the following code so far:
/** Quaternion multiplication
*
*/
void multiplyQuaternion(const Mat& q1,const Mat& q2, Mat& q)
{
// First quaternion q1 (x1 y1 z1 r1)
const float x1=q1.at<float>(0);
const float y1=q1.at<float>(1);
const float z1=q1.at<float>(2);
const float r1=q1.at<float>(3);
// Second quaternion q2 (x2 y2 z2 r2)
const float x2=q2.at<float>(0);
const float y2=q2.at<float>(1);
const float z2=q2.at<float>(2);
const float r2=q2.at<float>(3);
q.at<float>(0)=x1*r2 + r1*x2 + y1*z2 - z1*y2; // x component
q.at<float>(1)=r1*y2 - x1*z2 + y1*r2 + z1*x2; // y component
q.at<float>(2)=r1*z2 + x1*y2 - y1*x2 + z1*r2; // z component
q.at<float>(3)=r1*r2 - x1*x2 - y1*y2 - z1*z2; // r component
}
Is this the fastest way with OpenCV? Would it be fastest using fixed-point arithmetic?
In this tutorial different ways to access different pixels are covered. The Mat::at function was found to be about 10% slower in comparison to direct pixel access, probably due to the extra check in debug mode.
If you are really off for performance, you should rewrite your method with the 3 different methods mentioned in the text and then profile to find the one which is best in your situation.
There -had- been an ARM vector floating point quaternion multiply out there I can not find now. I could find this SIMD library:
Bullet 3D Game Multiphysics Library
Quaternions are often used to rotate 3D vectors so you might consider checking that one quaternion is a pure vector (i.e., the scalar or real part is zero). This could cut your work to 12 multiplies, 8 adds/subtracts and one sign flip.
You can also use quaternion multiplication on two pure vectors to compute their dot and cross products simultaneously, so testing for this special case may also be worth it. If both quaternions are pure vectors, you only need do 9 multiplies, 5 add/subtracts and one sign flip.