我在网上看到了许多关于如何使用openCV进行相机+投影仪校准的博客文章和视频和源代码,以产生camera.yml
, projector.yml
和projectorExtrinsics.yml
文件。
我还没有看到任何人讨论如何处理这些文件之后。事实上,我自己已经做了一个校准,但我不知道我自己的应用程序的下一步是什么。
假设我编写了一个应用程序,该应用程序现在使用我校准的相机-投影仪系统来跟踪对象并在其上投射一些东西。我将使用contourFind()从移动的物体中抓取一些感兴趣的点,现在我想将这些点(从投影仪!)投影到物体上!
我想做的是(例如)跟踪一个对象的质心(COM),并在被跟踪对象的相机视图上显示一个点(在其COM处)。然后在物体的COM上实时投影一个点。
似乎projectPoints()
是我应该在加载yml文件后使用的openCV函数,但我不确定我将如何解释所有内在的&相机和投影仪的外部校准值。也就是说,projectPoints()
需要
- 要重新投影的点向量(呸!)
- 旋转+平移矩阵。我想我可以在这里用投影仪。或者我可以使用composeRT()函数来生成最后的旋转&最后的翻译矩阵从projectreextrinsics(我有在yml文件)和cameraExtrinsics(我没有)。附带问题:我不应该把它们也保存在文件中吗??)。
- intrinsic矩阵。这很棘手。我应该使用相机还是投影仪的固有矩阵?
- 畸变系数。我应该用投影仪还是用摄像机?
- 其他参数…
所以,如果我在projectPoints()
中使用投影仪或摄像机(哪一个??)内在特性+系数,那么我只会"纠正"这两种仪器中的一种。我将在哪里/如何使用其他乐器的内在??
除了load()
的yml文件和projectPoints()
,我还需要使用什么?(也许undistortion ?)
首先,你似乎对相机/投影仪模型的一般作用感到困惑:它的作用是将3D世界点映射到2D图像点。这听起来很明显,但这意味着给定外部属性R,t(方向和位置),畸变函数D(.)和本质属性K,您可以为这个特定的相机推断出3D点m的2D投影m: m = K.D(R.M+t)。projectPoints
函数就是这样做的(即3D到2D的投影),对于每个输入的3D点,因此你需要给它与你想要3D点投影的相机相关的输入参数(如果你想要投影仪2D坐标,投影仪K&D,如果你想要相机2D坐标)。
第二,当你联合校准你的相机和投影仪时,你不估计一组外部R,t用于相机和另一个用于投影仪,但只有一个R和一个t,这表示相机和投影仪的坐标系之间的旋转和平移。例如,这意味着假设您的相机具有旋转= identity和平移= 0,并且投影仪具有旋转= R和平移= t(或者反过来,取决于您如何进行校准)。
现在,关于你提到的应用,真正的问题是:你如何估计给定点的三维坐标?
使用两个摄像机和一个投影仪,这将是很容易的:你可以跟踪两个摄像机图像中感兴趣的对象,使用triangulatePoints
函数使用两个2D投影来三角测量它们的3D位置,最后使用projectPoints
在投影仪的2D坐标中投影这个3D点,以便知道在哪里用投影仪显示东西。
只有一个摄像机和一个投影仪,这仍然是可能的,但更困难,因为你不能从一个观察跟踪点三角测量。其基本思想是像处理稀疏立体视差估计问题一样处理该问题。一个可能的方法如下:
-
使用投影仪投影非模糊图像(例如黑白噪声),以便相机观察到的场景纹理。
-
和之前一样,跟踪相机图像中感兴趣的对象
-
对于每个感兴趣的对象,将相机图像中其位置周围的小窗口与投影仪图像关联起来,以便找到它在投影仪2D坐标中的投影位置
另一种方法,与上面使用校准参数的方法不同,可以使用stereoRectify
和StereoBM::operator()
(或GPU实现的gpu::StereoBM_GPU::operator()
)进行密集的3D重建,使用估计的场景深度将跟踪的2D位置映射到3D,最后使用projectPoints
投影到投影仪中。
无论如何,使用两个相机更容易,也更准确。