You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将3D长方体投影到2D相机图像并精准处理相机校准与变换?

3D长方体到2D相机图像的精准渲染步骤

以下是针对给定数据,完成3D长方体到2D图像渲染的完整流程,包含坐标系变换、相机校准应用和最终图像缩放三个核心部分:

1. 生成长方体的8个3D顶点

先从长方体的中心、尺寸和旋转数据,计算出其在世界坐标系下的8个顶点:

  • 定义长方体的局部顶点(以自身中心为原点):[±x/2, ±y/2, ±z/2]
  • 对局部顶点应用Z轴旋转(rotation3D.z),再叠加中心坐标得到世界坐标
// 生成长方体局部顶点(以自身中心为原点)
const halfSize = {
  x: cuboidData.size3D.x / 2,
  y: cuboidData.size3D.y / 2,
  z: cuboidData.size3D.z / 2
};
const localVertices = [
  [-halfSize.x, -halfSize.y, -halfSize.z],
  [-halfSize.x, -halfSize.y, halfSize.z],
  [-halfSize.x, halfSize.y, -halfSize.z],
  [-halfSize.x, halfSize.y, halfSize.z],
  [halfSize.x, -halfSize.y, -halfSize.z],
  [halfSize.x, -halfSize.y, halfSize.z],
  [halfSize.x, halfSize.y, -halfSize.z],
  [halfSize.x, halfSize.y, halfSize.z]
];

// Z轴旋转函数
const rotateZ = (point, angle) => {
  const cos = Math.cos(angle);
  const sin = Math.sin(angle);
  return [
    point[0] * cos - point[1] * sin,
    point[0] * sin + point[1] * cos,
    point[2]
  ];
};

// 转换为世界坐标系顶点
const worldVertices = localVertices.map(v => {
  const rotated = rotateZ(v, cuboidData.rotation3D.z);
  return [
    rotated[0] + cuboidData.center3D.x,
    rotated[1] + cuboidData.center3D.y,
    rotated[2] + cuboidData.center3D.z
  ];
});

2. 世界坐标 → 相机坐标变换

利用coordSystem中的四元数和平移数据,将世界坐标系顶点转换到相机坐标系(约定:Z轴指向场景前方,X轴向右,Y轴向下):

// 四元数转旋转矩阵(世界到相机的旋转)
const quatToMat = (q) => {
  const [x, y, z, w] = q;
  return [
    1 - 2*y*y - 2*z*z, 2*x*y - 2*z*w,     2*x*z + 2*y*w,
    2*x*y + 2*z*w,     1 - 2*x*x - 2*z*z, 2*y*z - 2*x*w,
    2*x*z - 2*y*w,     2*y*z + 2*x*w,     1 - 2*x*x - 2*y*y
  ];
};

// 相机在世界中的平移向量
const cameraTranslation = coordSystem.translation;
// 世界到相机的旋转矩阵
const rotationMatrix = quatToMat(coordSystem.quaternion);

// 世界点转相机点:P_cam = R*(P_world - T)
const worldToCamera = (point) => {
  const dx = point[0] - cameraTranslation[0];
  const dy = point[1] - cameraTranslation[1];
  const dz = point[2] - cameraTranslation[2];
  return [
    rotationMatrix[0]*dx + rotationMatrix[1]*dy + rotationMatrix[2]*dz,
    rotationMatrix[3]*dx + rotationMatrix[4]*dy + rotationMatrix[5]*dz,
    rotationMatrix[6]*dx + rotationMatrix[7]*dy + rotationMatrix[8]*dz
  ];
};

const cameraVertices = worldVertices.map(worldToCamera);

3. 相机坐标 → 图像平面投影(含畸变校正)

使用相机内参矩阵将3D相机点投影到2D图像平面,再应用畸变系数校正:

// 解析相机内参矩阵
const fx = cameraCalibration.camera_matrix[0];
const cx = cameraCalibration.camera_matrix[2];
const fy = cameraCalibration.camera_matrix[5];
const cy = cameraCalibration.camera_matrix[6];

// 畸变系数:k1, k2, p1, p2, k3
const [k1, k2, p1, p2, k3] = cameraCalibration.distortion_coeffs;

// 相机点投影到图像像素坐标(含畸变校正)
const projectPoint = (point) => {
  const [x, y, z] = point;
  // 归一化坐标
  const uNorm = x / z;
  const vNorm = y / z;
  
  // 计算畸变
  const r2 = uNorm*uNorm + vNorm*vNorm;
  const distortion = 1 + k1*r2 + k2*r2*r2 + k3*r2*r2*r2;
  const uDistorted = uNorm * distortion + 2*p1*uNorm*vNorm + p2*(r2 + 2*uNorm*uNorm);
  const vDistorted = vNorm * distortion + p1*(r2 + 2*vNorm*vNorm) + 2*p2*uNorm*vNorm;
  
  // 转换为图像像素坐标
  return [
    fx * uDistorted + cx,
    fy * vDistorted + cy
  ];
};

const imageVertices = cameraVertices.map(projectPoint);

4. 图像坐标缩放至目标尺寸

原图像尺寸为4112px宽、2504px高,目标宽度600px,保持宽高比:

const targetWidth = 600;
const aspectRatio = cameraCalibration.width_px / cameraCalibration.height_px;
const targetHeight = Math.round(targetWidth / aspectRatio); // 约365px

// 缩放图像坐标
const scaleFactor = targetWidth / cameraCalibration.width_px;
const scaledVertices = imageVertices.map(pt => [
  pt[0] * scaleFactor,
  pt[1] * scaleFactor
]);

5. 渲染长方体

将缩放后的8个顶点按长方体的棱边连接,即可在目标2D图像上渲染出精准的长方体轮廓。


内容的提问来源于stack exchange,提问作者NIYAS RAHMAN

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 17:49:51