Skip to content
On this page

坐标系

坐标系

本节将介绍2D&3D融合数据(包括相机参数在内)的坐标系。

点云标注工具主要涉及到2个方面的坐标系:3D点云坐标系和2D图片坐标系。

3D点云坐标系

3D点云工具使用的是右手坐标系。点云数据的坐标系是世界坐标系,而点云的坐标系则是以Z轴向上(如下图所示)。

3D标注结果的坐标位置信息是相对点云坐标系的坐标值。

2D图片坐标系

在点云工具的2D和3D融合工具映射中,图像的原点位于图像的左上角。水平表示X轴,垂直表示Y轴。X值向右增大,Y值向下增大(如下图所示)。

2D标注结果中的坐标位置信息是相对于图像坐标系的值。

相机参数 (2D&3D融合数据集)

该工具中的2D和3D映射转换过程与通用数据集的基本相同,转换参数包括相机外参参数和相机内参参数。相机参数示例:

bash
 {
        // or camera_internal
        "cameraInternal": {
            "fx": 933.4667,
            "fy": 934.6754,
            "cx": 896.4692,
            "cy": 507.3557
        },
        "width": 1920,
        "height": 1080,
        // or camera_external
        "cameraExternal": [
            -0.7209479393140598,
            -0.04004438206239668,
            -0.6918312773097581,
            0,
            0.6911177056736608,
            0.0317737123271339,
            -0.7220434530617444,
            0,
            0.05089583188421044,
            -0.9986925846676711,
            0.004768189029478265,
            0,
            0.009297776700688867,
            1.6581292167169648,
            -1.0197515012137728,
            1
        ],
        "rowMajor": false
    }
  • 宽度:图像宽度
  • 高度:图像高度
  • cameraExternal:相机内参参数
  • cameraInternal:带有4x4的相机矩阵
  • rowMajor:无论相机外参是否为row-major order行主序,默认值为行序。

详细内容请参考Camera Calibration and 3D Reconstruction

通用数据集转换

通用数据转换过程如下:点坐标 * 相机外参参数 * 相机内参参数 = 图像坐标。

  • X/Y/Z: 点云坐标系坐标
  • r11...t3: 相机外参参数矩阵信息
  • Fx/Fy/Cx/Cy: 相机内参参数信息
  • S(u,v): 图像坐标

工具数据转换

工具的数据转换过程如下:

S(u,v) = M(internal) x M(external) x P

  • P : 点云坐标系坐标
  • M(internal) : 4x4内部参数矩阵(行顺序)
  • M(external) : 4x4外部参数矩阵(行顺序)

将相机参数集成到工具中时,需要将4x3或3x3矩阵填充到4x4矩阵中,如下所示:

内部参数转换

外部参数转换

转换示例青请参考KITTI Dataset

Velodyne LiDAR坐标系中的一个三维点x被投影到第i个相机图像中的一个点y,表达式为:

y = P(i) @ R(0) @ Tvelo_cam @ xA

参考kitti-coordinate-transformation

代码示例:

bash
// Example: Calculate external matrix of camera 1

// camera 0 projection matrix as internal matrix
// 7.215377e+02 0.000000e+00 6.095593e+02 0.000000e+00
// 0.000000e+00 7.215377e+02 1.728540e+02 0.000000e+00
// 0.000000e+00 0.000000e+00 1.000000e+00 0.000000e+00
let P_rect_matrix_0 = createMatrixFrom4x3(config.cameras[0].P_rect);

// camera 1 projection matrix
// 7.215377e+02 0.000000e+00 6.095593e+02 -3.875744e+02
// 0.000000e+00 7.215377e+02 1.728540e+02 0.000000e+00
// 0.000000e+00 0.000000e+00 1.000000e+00 0.000000e+00
let P_rect_matrix_1 = createMatrixFrom4x3(config.cameras[1].P_rect);
// camera 0 rotate matrix
let R_rect_matrix_0 = createMatrixFrom3x3(config.R_rect);
// velodyne-camera transform
let RT_velo_to_cam_matrix = createMatrixFrom4x3(config.RT_velo_to_cam);

// external parameters
let external_matrix = new THREE.Matrix4().copy(P_rect_matrix_0).invert()
                    .multiply(P_rect_matrix_1)
                    .multiply(R_rect_matrix_0)
                    .multiply(RT_velo_to_cam_matrix);

// elements of THREE.Matrix4 is column-major, need to convert to row-major
external_matrix.transpose()
console.log(external_matrix.elements)
// [0.0002347736981472108,-0.9999441545437641,-0.010563477811052198,-0.5399474051919163,
// 0.010449407416592824,0.010565353641379319,-0.9998895741176488,-0.07510879138296463,
// 0.9999453885620024,0.00012436537838650657,0.010451302995668946,-0.2721327964058732,
// 0,0,0,1]

// internal parameters from camera 0 projection matrix
// fx: 7.215377e+02  fy: 7.215377e+02
// cx: 6.095593e+02  cy: 1.728540e+02


// tool function
// 3x3 convert to 4x4
function createMatrixFrom3x3(a: Array<number>): THREE.Matrix4 {
    return new THREE.Matrix4().set(a[0], a[1], a[2], 0, a[3], a[4], a[5], 0, a[6], a[7], a[8], 0, 0, 0, 0, 1);
}

// 4x3 convert to 4x4
function createMatrixFrom4x3(a: Array<number>): THREE.Matrix4 {
    return new THREE.Matrix4().set(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], 0, 0, 0, 1);
}

转换示例The PandaSet Dataset

代码示例:

bash
// poses parameter from poses.json
function createExternalMatrix(poses) {
    let quaternion = new THREE.Quaternion(pos.heading.x, pos.heading.y, pos.heading.z, pos.heading.w);
    let position = new THREE.Vector3(pos.position.x, pos.position.y, pos.position.z);
    let external_matrix = new THREE.Matrix4();
    external_matrix.compose(position, quaternion, new THREE.Vector3(1, 1, 1));

    // elements of THREE.Matrix4 is column-major, need to convert to row-major
    external_matrix.transpose()

    return external_matrix;
}

// internal parameters from intrinsics.json
// { fx: 933.4667, fy: 934.6754, cx: 896.4692, cy: 507.3557 }

3D坐标到2D坐标的转换