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

使用solvePnP()与SOLVEPNP_IPPE_SQUARE的ARKit相机位姿估计异常问题

解决ARKit+OpenCV solvePnP获取相机位置的距离错误问题

看了你的代码和日志输出,你这里犯了两个典型的solvePnP使用错误,直接导致了translationVector.z的结果完全不符合预期,下面逐一拆解并给出修复方案:

1. 图像点坐标转换错误

Vision框架检测到的二维码角点(visionResult.topLeft等)本身就是像素坐标系下的原始坐标,不需要再乘以图像分辨率。你的convertImagePoints函数错误地对坐标做了放大,导致图像点位置完全偏离,这会直接让solvePnP计算出错误的姿态。

修复代码:

修改convertImagePoints方法,直接使用原始CGPoint的x和y值:

+ (vector<Point2f>) convertImagePoints: (NSArray<NSValue *> *) array toSize: (CGSize) size {
    vector<Point2f> points;
    for (NSValue * value in array) {
        CGPoint point = [value CGPointValue];
        // 移除错误的分辨率乘法,直接使用像素坐标
        points.push_back(Point2f(point.x, point.y));
    }
    return points;
}

2. 图像点与物体点的顺序不匹配

solvePnP要求图像点数组和3D物体点数组的顺序必须严格一一对应,否则姿态估计会完全错误。你的代码中:

  • 图像点顺序:topLeft → topRight → bottomLeft → bottomRight
  • 物体点顺序:左上 → 右上 → 右下 → 左下

两者的第三、第四个点顺序不匹配,导致solvePnP无法正确关联2D和3D点。

修复代码:

调整3D物体点的顺序,和图像点保持一致:

+ (vector<Point3f>) getObjectPointsWithSquareLength: (NSNumber*) squareLength {
    vector<Point3f> points;
    double squareLengthDouble = [squareLength doubleValue];
    float halfSize = squareLengthDouble / 2.0;
    // 顺序对应:topLeft, topRight, bottomLeft, bottomRight
    points.push_back(Point3f(-halfSize, halfSize, 0));    // 左上
    points.push_back(Point3f(halfSize, halfSize, 0));     // 右上
    points.push_back(Point3f(-halfSize, -halfSize, 0));   // 左下(对应图像的bottomLeft)
    points.push_back(Point3f(halfSize, -halfSize, 0));    // 右下(对应图像的bottomRight)
    return points;
}

3. 坐标系转换的额外验证

解决前两个问题后,再确认坐标系转换逻辑:

  • OpenCV的坐标系是:X向右,Y向下,Z向前
  • SceneKit的坐标系是:X向右,Y向上,Z向后

你当前的RotX矩阵绕X轴旋转180度的转换是正确的,修复前两个问题后,tvec scenekit的z值应该接近-2(因为SceneKit的Z轴向后,相机到二维码的距离是2米,二维码处于相机Z=-2的位置,对应相机相对于二维码的位置Z=2),你可以根据这个逻辑调整最终translation向量的符号。


内容的提问来源于stack exchange,提问作者Dim Roe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 06:56:11