Browse Source

Added Quaternions class.

git-svn-id: https://emgucv.svn.sourceforge.net/svnroot/emgucv/trunk@693 d7f09016-e345-0410-b530-edf29a71df78
UWP10
canming 16 years ago
parent
commit
13d37fbac2
  1. 113
      Emgu.CV.Extern/quaternions.cpp
  2. 27
      Emgu.CV.Extern/quaternions.h
  3. 184
      Emgu.CV/CameraCalibration/Quaternions.cs
  4. 1
      Emgu.CV/Emgu.CV.csproj

113
Emgu.CV.Extern/quaternions.cpp

@ -0,0 +1,113 @@
#include "quaternions.h"
CVAPI(void) eulerToQuaternions(double x, double y, double z, Quaternions* quaternions)
{
double
sinX = sin(x / 2.0),
cosX = cos(x / 2.0),
sinY = sin(y / 2.0),
cosY = cos(y / 2.0),
sinZ = sin(z / 2.0),
cosZ = cos(z / 2.0);
quaternions->w = cosX*cosY*cosZ + sinX*sinY*sinZ;
quaternions->x = sinX*cosY*cosZ - cosX*sinY*sinZ;
quaternions->y = cosX*sinY*cosZ + sinX*cosY*sinZ;
quaternions->z = cosX*cosY*sinZ - sinX*sinY*cosZ;
}
CVAPI(void) quaternionsToEuler(Quaternions* quaternions, double* x, double* y, double* z)
{
double q0 = quaternions->w;
double q1 = quaternions->x;
double q2 = quaternions->y;
double q3 = quaternions->z;
*x = atan2(2 * (q0 * q1 + q2 * q3), 1.0 - 2.0 * (q1 * q1 + q2*q2));
*y = asin(2 * (q0 * q2 - q3 * q1));
*z = atan2(2 * (q0 * q3 + q1 * q2), 1.0 - 2.0 * (q2*q2 + q3*q3));
}
CVAPI(void) quaternionsToRotationMatrix(Quaternions* quaternions, CvMat* rotation)
{
double a = quaternions->w;
double b = quaternions->x;
double c = quaternions->y;
double d = quaternions->z;
cv::Mat r = cv::cvarrToMat(rotation);
CV_Assert(r.rows == 3 && r.cols == 3);
cv::MatIterator_<double> rIter = r.begin<double>();
*rIter++ = a*a+b*b-c*c-d*d; *rIter++ = 2.0*b*c-2.0*a*d; *rIter++ = 2.0*b*d+2.0*a*c;
*rIter++ = 2.0*b*c+2.0*a*d; *rIter++ = a*a-b*b+c*c-d*d; *rIter++ = 2.0*c*d-2.0*a*b;
*rIter++ = 2.0*b*d-2.0*a*c; *rIter++ = 2.0*c*d+2.0*a*b; *rIter++ = a*a-b*b-c*c+d*d;
}
void quaternionsRotate(double w, double x, double y, double z, double v1, double v2, double v3, double*vr)
{
double
t2 = w*x,
t3 = w*y,
t4 = w*z,
t5 = -x*x,
t6 = x*y,
t7 = x*z,
t8 = -y*y,
t9 = y*z,
t10 = -z*z;
*vr++ = 2*( (t8 + t10)* v1 + (t6 - t4)* v2 + (t3 + t7)* v3 ) + v1,
*vr++ = 2*( (t4 + t6)* v1 + (t5 + t10)* v2 + (t9 - t2)* v3 ) + v2,
*vr = 2*( (t7 - t3)* v1 + (t2 + t9)* v2 + (t5 + t8)* v3 ) + v3;
}
CVAPI(void) quaternionsRotatePoint(Quaternions* quaternions, CvPoint3D64f* point, CvPoint3D64f* pointDst)
{
quaternionsRotate(quaternions->w, quaternions->x, quaternions->y, quaternions->z, point->x, point->y, point->z, (double*) pointDst);
}
CVAPI(void) quaternionsRotatePoints(Quaternions* quaternions, CvMat* pointSrc, CvMat* pointDst)
{
cv::Mat p = cv::cvarrToMat(pointSrc);
cv::Mat pDst = cv::cvarrToMat(pointDst);
CV_Assert((p.rows == 3 && p.cols == 1) || p.cols ==3);
CV_Assert(pDst.rows == p.rows && pDst.cols == p.cols);
double *v;
cv::MatIterator_<double> pIter = p.begin<double>();
cv::MatIterator_<double> pDstIter = pDst.begin<double>();
if ((p.rows == 3 && p.cols == 1))
{
v = pIter.ptr;
quaternionsRotate(quaternions->w, quaternions->x, quaternions->y, quaternions->z, *v, *(v+1), *(v+2), pDstIter.ptr);
} else
{
for(int i = 0; i < p.rows; i++, pIter+=3, pDstIter+=3)
{
v = pIter.ptr;
quaternionsRotate(quaternions->w, quaternions->x, quaternions->y, quaternions->z, *v, *(v+1), *(v+2), pDstIter.ptr);
}
}
}
CVAPI(void) quaternionsMultiply(Quaternions* quaternions1, Quaternions* quaternions2, Quaternions* quaternionsDst)
{
double w1 = quaternions1->w;
double x1 = quaternions1->x;
double y1 = quaternions1->y;
double z1 = quaternions1->z;
double w2 = quaternions2->w;
double x2 = quaternions2->x;
double y2 = quaternions2->y;
double z2 = quaternions2->z;
quaternionsDst->w = (w1*w2 - x1*x2 - y1*y2 - z1*z2);
quaternionsDst->x = (w1*x2 + x1*w2 + y1*z2 - z1*y2);
quaternionsDst->y = (w1*y2 - x1*z2 + y1*w2 + z1*x2);
quaternionsDst->z = (w1*z2 + x1*y2 - y1*x2 + z1*w2);
}

27
Emgu.CV.Extern/quaternions.h

@ -0,0 +1,27 @@
#include "cxcore.h"
typedef struct Quaternions
{
double w;
double x;
double y;
double z;
} Quaternions;
/* convert eluer angle (in radian) to quaternions */
CVAPI(void) eulerToQuaternions(double x, double y, double z, Quaternions* quaternions);
/* convert quaternions to eluer angle (in radian) */
CVAPI(void) quaternionsToEuler(Quaternions* quaternions, double* x, double* y, double* z);
/* convert quaternions to (3x3) rotation matrix */
CVAPI(void) quaternionsToRotationMatrix(Quaternions* quaternions, CvMat* rotation);
/* rotate the (3x1 or nx3) matrix of points using the quaternions */
CVAPI(void) quaternionsRotatePoint(Quaternions* quaternions, CvPoint3D64f* point, CvPoint3D64f* pointDst);
/* rotate the (3x1 or nx3) matrix of points using the quaternions */
CVAPI(void) quaternionsRotatePoints(Quaternions* quaternions, CvMat* pointSrc, CvMat* pointDst);
/* quaternionsDst = quaternions1 * quaternions2 */
CVAPI(void) quaternionsMultiply(Quaternions* quaternions1, Quaternions* quaternions2, Quaternions* quaternionsDst);

184
Emgu.CV/CameraCalibration/Quaternions.cs

@ -0,0 +1,184 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using Emgu.CV.Structure;
namespace Emgu.CV
{
/// <summary>
/// A unit quaternions that defines rotation in 3D
/// </summary>
[Serializable]
//TODO: Check if mono has System.Windows.Media.Media3D.Quaternion implemented and if it comes as a package on Ubuntu and fedora
public struct Quaternions
{
private double _w;
private double _x;
private double _y;
private double _z;
/// <summary>
/// The W component of the quaternion.
/// </summary>
public double W
{
get { return _w; }
set { _w = value; }
}
/// <summary>
/// The X component of the quaternion.
/// </summary>
public double X
{
get { return _x; }
set { _x = value; }
}
/// <summary>
/// The Y component of the quaternion.
/// </summary>
public double Y
{
get { return _y; }
set { _y = value; }
}
/// <summary>
/// The Z component of the quaternion.
/// </summary>
public double Z
{
get { return _z; }
set { _z = value; }
}
[DllImport(CvInvoke.EXTERN_LIBRARY)]
private extern static void eulerToQuaternions(double x, double y, double z, ref Quaternions q);
[DllImport(CvInvoke.EXTERN_LIBRARY)]
private extern static void quaternionsToEuler(ref Quaternions q, ref double x, ref double y, ref double z);
[DllImport(CvInvoke.EXTERN_LIBRARY)]
private extern static void quaternionsToRotationMatrix(ref Quaternions quaternions, IntPtr rotation);
[DllImport(CvInvoke.EXTERN_LIBRARY)]
private extern static void quaternionsRotatePoint(ref Quaternions quaternions, ref MCvPoint3D64f point, ref MCvPoint3D64f pointDst);
[DllImport(CvInvoke.EXTERN_LIBRARY)]
private extern static void quaternionsRotatePoints(ref Quaternions quaternions, IntPtr pointSrc, IntPtr pointDst);
[DllImport(CvInvoke.EXTERN_LIBRARY)]
private extern static void quaternionsMultiply(ref Quaternions quaternions1, ref Quaternions quaternions2, ref Quaternions quaternionsDst);
/// <summary>
/// Set the value of the quaternions using euler angle
/// </summary>
/// <param name="x">Rotation around x-axis (roll) in radian</param>
/// <param name="y">Rotation around y-axis (pitch) in radian</param>
/// <param name="z">rotation around z-axis (yaw) in radian</param>
public void SetEuler(double x, double y, double z)
{
eulerToQuaternions(x, y, z, ref this);
}
/// <summary>
/// Get the equaivalent euler angle
/// </summary>
/// <param name="x">Rotation around x-axis (roll) in radian</param>
/// <param name="y">Rotation around y-axis (pitch) in radian</param>
/// <param name="z">rotation around z-axis (yaw) in radian</param>
public void GetEuler(ref double x, ref double y, ref double z)
{
quaternionsToEuler(ref this, ref x, ref y, ref z);
}
/// <summary>
/// Fill the (3x3) rotation matrix with the value such that it represent the quaternions
/// </summary>
/// <param name="rotation">The (3x3) rotation matrix which values will be set to represent this quaternions</param>
public void GetRotationMatrix(Matrix<double> rotation)
{
quaternionsToRotationMatrix(ref this, rotation);
}
/// <summary>
/// Rotate the points in <paramref name="pointsSrc"/> and save the result in <paramref name="pointsDst"/>. Inplace operation is supported (<paramref name="pointsSrc"/> == <paramref name="pointsDst"/>).
/// </summary>
/// <param name="pointsSrc">The points to be rotated</param>
/// <param name="pointsDst">The result of the rotation, should be the same size as <paramref name="pointsSrc"/>, can be <paramref name="pointSrc"/> as well for inplace rotation</param>
public void RotatePoints(Matrix<double> pointsSrc, Matrix<double> pointsDst)
{
quaternionsRotatePoints(ref this, pointsSrc, pointsDst);
}
/// <summary>
/// Rotate the specific point and return the result
/// </summary>
/// <param name="point">The point to be rotated</param>
/// <returns>The rotated point</returns>
public MCvPoint3D64f RotatePoint(MCvPoint3D64f point)
{
MCvPoint3D64f result = new MCvPoint3D64f();
quaternionsRotatePoint(ref this, ref point, ref result);
return result;
}
/// <summary>
/// Get the rotation axis of the quaternion
/// </summary>
public MCvPoint3D64f RotationAxis
{
get
{
return new MCvPoint3D64f(X, Y, Z);
}
set
{
X = value.x;
Y = value.y;
Z = value.z;
}
}
/// <summary>
/// Returns the rotation angle in radian
/// </summary>
public double RotationAngle
{
get
{
return 2.0* Math.Acos(W);
}
set
{
W = Math.Cos(value / 2.0);
}
}
/// <summary>
/// Multiply the current Quaternions with <paramref name="quaternionsOther"/>
/// </summary>
/// <param name="quaternionsOther">The other rotation</param>
/// <return>A composition of the two rotations</return>
public Quaternions Multiply(Quaternions quaternionsOther)
{
Quaternions result = new Quaternions();
quaternionsMultiply(ref this, ref quaternionsOther, ref result);
return result;
}
/// <summary>
/// Computes the multiplication of two quaternions
/// </summary>
/// <param name="q1">The quaternions to be multiplied</param>
/// <param name="q2">The quaternions to be multiplied</param>
/// <returns>The multiplication of two quaternions</returns>
public static Quaternions operator *(Quaternions q1, Quaternions q2)
{
return q1.Multiply(q2);
}
}
}

1
Emgu.CV/Emgu.CV.csproj

@ -63,6 +63,7 @@
<ItemGroup>
<Compile Include="AdaptiveSkinDetector.cs" />
<Compile Include="CameraCalibration\HomographyMatrix.cs" />
<Compile Include="CameraCalibration\Quaternions.cs" />
<Compile Include="Flann\CenterInitType.cs" />
<Compile Include="Flann\Index.cs" />
<Compile Include="ImageFeature.cs" />

Loading…
Cancel
Save