ARKit 中是否公开了 pnp 求解器,或者如何使用 EmguCV c# 包装器在 Unity3D 项目中使用 opencv 的 SolvePnP 函数

Is there a pnp solver exposed in ARKit, or how to use opencv's SolvePnP function within a Unity3D project using the EmguCV c# wrapper

高级上下文:

在 Unity3D AR 项目中,系统使用机器学习提供图像中的一组 2D 像素坐标与世界坐标中的同一组 3D 点之间的对应关系。 根据这两组之间的对应关系,我想估计产生该图像的相机姿势。

要实现的低级目标:

我的研究结果建议我使用 PnP-Ransac 算法。 Perspective-n-Points 是我遇到的这个问题的名称:从匹配的 2D-3D 点中找到相机姿势。 即插即用问题定义:https://en.wikipedia.org/wiki/Perspective-n-Point

我试过的

1) 我试图在 ARKit 中找到一个 PnP 求解器,但找不到,所以我猜它没有暴露。 2) 我尝试使用商店中的 EmguCV 资产,这应该允许我在我的 Unity 项目中使用 openCV。 OpenCV solvePnP 文档:https://docs.opencv.org/3.3.0/d9/d0c/group__calib3d.html#ga50620f0e26e02caa2e9adc07b5fbf24e

问题:

ARKit 框架中是否公开了 PnP 求解器,如果没有,我如何在 Unity 项目中使用 EmguCV C# 包装器正确使用 openCV 的 PnP 求解器(要注意的坐标系,要提供的正确函数参数)像相机固有矩阵,如何解释输出以获得正确的相机姿势)?

我在回答问题时遇到的问题:

使用 SolvePnPRansac 导致 Unity-Editor 自身崩溃,即使我将它放在 try-catch 块中(可能我的输入参数有意外的格式)。 我仅使用 solvePnP 就取得了更大的成功,但结果并不是我所期望的。 文档指出输出向量 rvec 和 tvec 对应于将对象从模型坐标系带到相机坐标系的平移和旋转。因此,如果我将相机放在 (0,0,0) 方向,观察 -z 方向,使对象在 tvec 处具有欧拉旋转 rvec,我希望渲染的对象与我用于像素坐标对应的图像相似.我是不是理解错了?

我的怀疑: openCV的坐标系表示图像坐标y从上到下,而z和x保持右前。我尝试在 y 轴上反转 2D 和 3D 坐标,但没有用

编辑[我在此处删除了我的代码,因为自从我提出问题以使其正常工作以来,我对其进行了很多更改]

(许多)相关帖子 我查看了其他 41 个带有标签 opencv-solvePnP 的 Whosebug 问题,但 none 其中 none 与 Unity3D 或 c# 相关

solvePnP with Unity3D

没有得到答案

How can I estimate the camera pose with 3d-to-2d-point-correspondences (using opencv)

区别:我需要在 unity3D c# 项目中完成

obtaining 2d-3d point correspondences for pnp or posit

我明白了,我需要使用数学算法,这是理论,但现在我如何使用我可以支配的库

ARKIT 是否提供 PnP 求解器?我还是不知道

关于如何在unity项目中使用openCV:这里是我自己的回答:

1) 坐标系:只需确保您的二维点具有正确的垂直坐标方向:根据您获取这些二维点的方式,可能没有任何改变。

2) 使用什么内在矩阵:

var pixelsPerMeter = (((float)Screen.height / 2f)) / (Mathf.Tan(_mainCamera.fieldOfView * Mathf.Deg2Rad / 2f));
var fx = pixelsPerMeter;
var cx = Screen.width * 0.5f;
var fy = pixelsPerMeter;
var cy = Screen.height * 0.5f;
var cameraMatrix = new Emgu.CV.Matrix<float>(new float[3, 3] {
        {fx,0,cx},
        {0,fy,cy},
        {0,0,1}
        });

EDIT:到目前为止,以上仅适用于我的统一编辑器。直到现在,使用 ARKit 在移动设备上部署对我来说仍然会产生不正确的结果!

3)如何从结果中解释tvec和rvec:

使用 Rodrigues 将 rvec 正确转换为旋转矩阵,简单地执行 Quaternion.Euler(rvec[0], rvec[1], rvec[2]) 是行不通的!

首先旋转你的物体,然后通过 tvec 平移它,最后额外应用你的相机的 localToWorld 矩阵来放置物体相对于相机的位置(如果你希望物体有一个固定的位置并且相机被放置, 只需反转由 rvec 和 tvec 产生的矩阵)