外参矩阵转四元数,左右手坐标系转化1

1, 外参矩阵转四元数

double rms = calibrateCamera(objectPoints, imagePoints, imageSize, cameraMatrix,
				distCoeffs, rvecs, tvecs, flags | CV_CALIB_FIX_K4 | CV_CALIB_FIX_K5);

			Rodrigues(rvecs[0], r);
			cout << rvecs[0] << endl;
			CcalinitEctrinsicMat(m_fExtrinsic, r, tvecs[0]);
//cv::solvePnP(object_points, corners, cameraMatrix, distCoeffs, rvecs, tvecs);
注意rvecs, tvecs是Mat还是vector<Mat>

//计算四元数

int sign(float x)
{
	return x >= 0 ? 1 : -1;
}
float myMax(float x, float y)
{
	return x >y ? x : y;

}

void QuaternionFromMatrix(const Mat& R, float quat[])
{
	// Adapted from: http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
	/*quat[0] = (float)sqrt(myMax(0.0, 1 + R.ptr<float>(0)[0] + R.ptr<float>(1)[1] + R.ptr<float>(2)[2]))/2;

	quat[1] = (float)sqrt(myMax(0.0, 1 + R.ptr<float>(0)[0] - R.ptr<float>(1)[1] - R.ptr<float>(2)[2]))/2;
	quat[2] = (float)sqrt(myMax(0.0, 1 - R.ptr<float>(0)[0] + R.ptr<float>(1)[1] - R.ptr<float>(2)[2]))/2;
	quat[3] = (float)sqrt(myMax(0.0, 1 - R.ptr<float>(0)[0] - R.ptr<float>(1)[1] + R.ptr<float>(2)[2]))/2;

	quat[1] *= sign(R.ptr<float>(2)[1] - R.ptr<float>(1)[2]);
	quat[2] *= sign(R.ptr<float>(0)[2] - R.ptr<float>(2)[0]);
	quat[3] *= sign(R.ptr<float>(1)[0] - R.ptr<float>(0)[1]);*/
	quat[0] = (float)sqrt(myMax(0.0, 1 + R.at<float>(0, 0) + R.at<float>(1, 1) + R.at<float>(2, 2))) / 2;

	quat[1] = (float)sqrt(myMax(0.0, 1 + R.at<float>(0, 0) - R.at<float>(1, 1) - R.at<float>(2, 2))) / 2;
	quat[2] = (float)sqrt(myMax(0.0, 1 - R.at<float>(0, 0) + R.at<float>(1, 1) - R.at<float>(2, 2))) / 2;
	quat[3] = (float)sqrt(myMax(0.0, 1 - R.at<float>(0, 0) - R.at<float>(1, 1) + R.at<float>(2, 2))) / 2;

	quat[1] *= sign(R.at<float>(2, 1) - R.at<float>(1, 2));
	quat[2] *= sign(R.at<float>(0, 2) - R.at<float>(2, 0));
	quat[3] *= sign(R.at<float>(1, 0) - R.at<float>(0, 1));
}


3, //左右手坐标系转化,计算四元数

void CcalinitEctrinsicMat(float* m_fExtrinsic, Mat rr, Mat tt)
{
	rr.convertTo(rr, CV_32F);
	tt.convertTo(tt, CV_32F);
	Mat R = Mat(3, 3, CV_32F), T = Mat(3, 1, CV_32F);
	T = tt;
	R = rr;
	////mrightEX = mrightEX.inv();
	//for (size_t i = 0; i < 3; i++)
	//{
	//	for (size_t j = 0; j < 3; j++)
	//	{
	//		R.at<float>(i, j) = mrightEX.at<float>(i, j);
	//		//T.at<float>(i, 0) = mrightEX.at<float>(i, 3);
	//	}
	//	T.at<float>(i, 0) = mrightEX.at<float>(i, 3);
	//}
	////左右手坐标系转化

	Mat R_CPP, R_inv, T_CPP;
	R_CPP = R;
	R_inv = R_CPP.inv();
	T_CPP = T;
	QuaternionFromMatrix(R_inv, m_fExtrinsic);

	// We need to invert rotations on X and Z axis
	m_fExtrinsic[1] = -m_fExtrinsic[1];
	m_fExtrinsic[3] = -m_fExtrinsic[3];
	Mat Tt = -R_inv * T_CPP;
	m_fExtrinsic[4] = (float)Tt.at<float>(0);
	m_fExtrinsic[5] = -(float)Tt.at<float>(1);
	m_fExtrinsic[6] = (float)Tt.at<float>(2);
}

---------------------------------------------------------

Rodrigues变换是为了实现opencv计算的外姿将旋转向量转化为旋转矩阵


			cv::Mat Rv, T, R;

			// 根据模板的真实点坐标设置objectPoints, imagePoints的值,调用更初级的一个函数FindExtrinsic2或类似的名字
			bool bSolved = cv::solvePnP(objectPoints, imagePoints, m_paraIntrinsic.cameraMatrix, m_paraIntrinsic.distCoeffs, Rv, T, false, CV_ITERATIVE);
			if(bSolved)
			{
				cv::Rodrigues(Rv, R);

				Mat Rt = R.t();
				
				QuaternionFromMatrix(Rt, m_fExtrinsic);
		
				// We need to invert rotations on X and Z axis
				m_fExtrinsic[1] = - m_fExtrinsic[1];
				m_fExtrinsic[3] = - m_fExtrinsic[3];

				Mat Tt = - Rt * T;

				m_fExtrinsic[4] = (float)Tt.at<double>(0);
				m_fExtrinsic[5] = - (float)Tt.at<double>(1);
				m_fExtrinsic[6] = (float)Tt.at<double>(2);

				m_fExtrinsic[7] = (float)m_paraIntrinsic.fov;

4,Google Cardboard里面的写法

// Copyright 2014 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using UnityEngine;

/// @cond
/// Encapsulates a rotation and a translation.  This is a convenience class that allows
/// construction and value access either by Matrix4x4 or Quaternion + Vector3 types.
public class Pose3D {
  /// Right-handed to left-handed matrix converter (and vice versa).
  protected static readonly Matrix4x4 flipZ = Matrix4x4.Scale(new Vector3(1, 1, -1));

  /// The translation component of the pose.
  public Vector3 Position { get; protected set; }

  /// The rotation component of the pose.
  public Quaternion Orientation { get; protected set; }

  /// The pose as a matrix in Unity gameobject convention (left-handed).
  public Matrix4x4 Matrix { get; protected set; }

  /// The pose as a matrix in right-handed coordinates.
  public Matrix4x4 RightHandedMatrix {
    get {
      return flipZ * Matrix * flipZ;
    }
  }

  /// Default constructor.
  /// Initializes position to the origin and orientation to the identity rotation.
  public Pose3D() {
    Position = Vector3.zero;
    Orientation = Quaternion.identity;
    Matrix = Matrix4x4.identity;
  }

  /// Constructor that takes a Vector3 and a Quaternion.
  public Pose3D(Vector3 position, Quaternion orientation) {
    Set(position, orientation);
  }

  /// Constructor that takes a Matrix4x4.
  public Pose3D(Matrix4x4 matrix) {
    Set(matrix);
  }

  protected void Set(Vector3 position, Quaternion orientation) {
    Position = position;
    Orientation = orientation;
    Matrix = Matrix4x4.TRS(position, orientation, Vector3.one);
  }

  protected void Set(Matrix4x4 matrix) {
    Matrix = matrix;
    Position = matrix.GetColumn(3);
    Orientation = Quaternion.LookRotation(matrix.GetColumn(2), matrix.GetColumn(1));
  }
}
/// @endcond

/// @cond
/// Mutable version of Pose3D.
public class MutablePose3D : Pose3D {
  /// Sets the position and orientation from a Vector3 + Quaternion.
  public new void Set(Vector3 position, Quaternion orientation) {
    base.Set(position, orientation);
  }

  /// Sets the position and orientation from a Matrix4x4.
  public new void Set(Matrix4x4 matrix) {
    base.Set(matrix);
  }

  /// Sets the position and orientation from a right-handed Matrix4x4.
  public void SetRightHanded(Matrix4x4 matrix) {
    Set(flipZ * matrix * flipZ);
  }
}
/// @endcond

<think>好的,我现在需要回答关于OSG库中右手坐标系的使用方式和实现原理的问题。首先,我需要仔细阅读用户提供的引用内容,确保理解每个引用的关键点,然后整理这些信息,形成一个结构清晰的回答。同时,我还需要生成相关问题,并确保所有数学表达式和独立公式的格式正确。 首先,用户提供的引用有四个,分别涉及OSG坐标系的方向、与其他库(如OpenGL、DirectX)的区别、坐标换规则以及数学基础。我需要将这些信息综合起来,解释OSG右手坐标系的具体使用方式和实现原理。 接下来,根据引用内容,OSG使用右手坐标系,但各轴方向与OpenGL不同。比如,引用1和引用2提到,OSG的X轴向右,Y轴向内(垂直于屏幕),Z轴向上。而OpenGL的坐标系中,Z轴是朝外的,Y轴向上,X轴向右。引用3还提到,OSG的坐标系可以视为OpenGL坐标系绕X轴旋后的结果。此外,引用1中的坐标换公式V' = V * Mn * ... * M0,说明局部坐标到世界坐标的换是通过矩阵连乘实现的,这可能涉及旋、平移和缩放矩阵的组合。 在实现原理方面,引用1提到OSG使用osg::Matrix、osg::Vec3和osg::Quat等类来处理坐标变换。这些类可能封装了矩阵运算、向量操作和四元数等功能,从而支持坐标系换。例如,矩阵乘法顺序(V * M0 * M1 ...)可能表示局部坐标系经过一系列变换矩阵后得到世界坐标,这与行主序矩阵有关。 另外,引用3中的摄像机设置示例显示,默认视点位于原点,看向Z轴负方向(即XOY平面),而向上向量是Y轴正方向,这进一步印证了OSG坐标系中Y轴朝内、Z轴向上的特点。这可能影响摄像机矩阵的构建和物体的位置计算。 需要注意的是,右手坐标系的实现还涉及到叉乘方向,如右手法则确定的正方向。在OSG中,进行旋或坐标变换时,可能需要遵循右手法则来确定旋方向或轴的方向。 现在,我需要将这些点组织成一个连贯的回答,分点说明坐标系方向、与其他库的区别、坐标换规则、数学类的作用以及实现原理中的矩阵运算。同时,确保使用正确的中文表达,并检查LaTeX格式是否正确,比如矩阵乘法的表示是否使用$$...$$或$...$。 在生成相关问题部分,需要围绕OSG坐标系的应用、与其他库的换、矩阵运算、摄像机设置以及数学基础等方面提问,确保问题相关且有深度。 最后,要确保引用标识正确添加到对应的内容末尾,例如在提到坐标轴方向时引用[^2],在换规则时引用[^1],在摄像机示例时引用[^3],在数学基础时引用[^4]。</think>### OSG库中右手坐标系的使用与实现原理 #### 一、坐标系定义与方向 OSG采用**右手坐标系**,其坐标轴定义如下: - **X轴**:屏幕水平方向,右侧为正方向 - **Y轴**:垂直于屏幕方向,向屏幕内为正方向 - **Z轴**:屏幕竖直方向,向上为正方向[^2][^3] 这种定义与OpenGL不同(OpenGL的Z轴朝外,Y轴向上,X轴向右),但通过将OpenGL坐标系绕X轴旋90°可得到OSG坐标系[^3]。 #### 二、坐标变换实现原理 1. **数学基础类** - 坐标变换通过$osg::Matrix$(矩阵)、$osg::Vec3$(三维向量)、$osg::Quat$(四元数)实现[^1] - 矩阵运算遵循行主序规则,局部坐标世界坐标公式为: $$V' = V \cdot M_0 \cdot M_1 \cdot \dots \cdot M_n$$ 其中$V$为局部坐标顶点,$M_i$为变换矩阵[^1] 2. **矩阵运算特性** - 矩阵连乘顺序体现变换叠加效果 - 示例:先平移后旋变换需写成$V \cdot T \cdot R$(T为平移矩阵,R为旋矩阵) 3. **摄像机坐标系** 默认摄像机参数: ```cpp vecEye = (0,0,0) // 视点位置 vecCenter = (0,0,-1) // 观察方向指向Z轴负方向 vecUp = (0,1,0) // 上方向为Y轴正方向[^3] ``` 这表明默认观察平面为XOY平面,符合Z轴向上的特性。 #### 三、与其他库的对比 | 特性 | OSG | OpenGL | DirectX | |---------------|----------------|----------------|----------------| | **坐标系类型** | 右手系 | 右手系 | 左手系 | | **Z轴方向** | 向上 | 向外 | 向里 | | **Y轴方向** | 向屏幕内 | 向上 | 向上 | #### 四、实现验证方法 1. **几何体测试**:在原点创建立方体,观察默认渲染方向 2. **矩阵追踪**:使用$osg::MatrixTransform$记录变换过程 3. **坐标系可视化**:通过HUD显示当前摄像机参数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值