使用OpenCV的solvePnP函数进行外部相机校准

时间:2015-09-21 20:56:57

标签: opencv computer-vision augmented-reality camera-calibration homography

我目前正在使用名为3DSlicer的医疗成像程序开发增强现实应用程序。我的应用程序在Slicer环境中作为模块运行,旨在提供使用外部跟踪系统增强Slicer中显示的摄像头输入所需的工具。

目前,一切都配置正确,以便我剩下的就是自动计算相机的外在矩阵,我决定使用OpenCV的solvePnP()功能。不幸的是,由于我没有获得正确的结果,这给了我一些困难。

我的跟踪系统配置如下:

  • 光学跟踪器的安装方式可以查看整个场景。
  • 跟踪标记严格附加到指针工具,相机和我们获取虚拟表示的模型。
  • 使用枢轴校准注册指针工具的尖端。这意味着使用指针记录的任何值都表示指针尖端的位置。
  • 模型和指针都有3D虚拟表示,可以增强实时视频输入,如下所示。
  • 指针和相机(从此处称为C)标记各自返回均匀变换,该变换描述了它们相对于附加到模型的标记的位置(从此处称为M)。作为原点的模型标记不会返回任何变换。

Depiction of correctly augmented environment. Extrinsic was manually adjusted to demonstrate process is correct, but is inaccurate.

我获得了两组点,一组2D和一组3D。 2D点是像素坐标中棋盘角的坐标,而3D点是相对于M的那些相同角的对应世界坐标。这些是使用openCV' detectChessboardCorners()函数记录的。二维点和三维指针。然后我将3D点从M空间转换为C空间,将它们乘以C逆。这是因为solvePnP()函数要求相对于相机的世界坐标系描述3D点,在这种情况下是C,而不是M.

完成所有这些后,我将点集传递到solvePnp()。但是,我得到的转变是完全错误的。老实说,我做错了。令我困惑的是,OpenCV使用与OpenGL不同的坐标格式,这是3DSlicer所基于的。如果有人能在这件事上提供一些帮助,我将非常感激。

如果有任何不清楚的地方,请不要犹豫。这是一个非常大的项目,因此我很难将所有内容提炼到手头的问题。我完全相信任何读这篇文章的人都会感到有些困惑。

谢谢!

更新#1:事实证明我是一个巨大的白痴。我记录共线点只是因为我太急于记录整个棋盘。当然这意味着对于最小二乘回归几乎有无限的解决方案,因为我只将解决方案锁定为2维!我的价值观现在更接近我的基本事实,实际上旋转列似乎是正确的,除非他们完全失灵。我不确定是什么原因引起的,但似乎我的旋转矩阵镜像在中心列上。除此之外,我的翻译成分应该是正面的,尽管它们的大小似乎是正确的。所以现在我基本上得到了所有错误顺序的正确值。

1 个答案:

答案 0 :(得分:1)

镜像/旋转模糊。

您基本上需要通过施加(1)场景位于摄像机前面的约束来重新定位坐标框架,以及(2)棋盘轴的方向与您期望的一样。这可以归结为将校准变换乘以适当的(“手工制作”)旋转和/或镜像。

基本问题是您正在使用的校准目标 - 即使看到所有角落,除非使用颜色信息,否则至少具有180度旋转模糊度。如果错过一些角落,事情会更加怪异。

您经常可以使用有关相机方向的先前信息w.r.t.正如我上面所建议的那样,解决这种模棱两可的场景。然而,在更动态的情况下,如果在目标可能仅部分可见的情况下需要进一步的自动化程度,那么使用可以单独识别每个小块角落的目标会更好。我最喜欢的是Matsunaga和Kanatani的“2D条形码”,它使用具有独特交叉的方形长度序列。请参阅论文here

相关问题