Emgu(C#的OpenCV)-使用cvStereoRectify构建视差图

7
我一直在使用Emgu C#封装的OpenCV来收集家庭立体摄像机拍摄的图像。两个网络摄像头固定在一块木板上,间距为35厘米,希望能够产生10-20米范围内的深度图。我已经尽力让它们尽可能平行(根据三角测量测试结果约为89.3度)。
我正在尝试从这些图像中制作视差图,虽然代码可以正常运行,但结果非常随机。我的意思是每次尝试运行立体矫正时,都会得到非常不同的结果,并且图像通常变形得非常严重,屏幕上几乎什么也看不到。
据我了解,做法如下:
1.打印棋盘格图案(例如6x8个内角),粘贴在平面物体上。
2.从相机1拍摄大约10张照片,保持棋盘格完全可见但位置不同。
3.使用CameraCalibration.FindChessboardCorners查找内角(6x8)。
4.使用img.FindCornerSubPix()将这些角落位置细化到亚像素级别。
5.使用CameraCalibration.CalibrateCamera()计算内部摄像机详细信息,并将其保存为XML文件。
6.对相机2重复上述步骤。
7.现在您拥有了内部摄像机失真信息,可以拍摄立体照片并使用CameraCalibration.StereoCalibrate()和之前计算的内部数据来计算外部信息(相机1和2之间的偏移和旋转)。
8.使用CvInvoke.cvStereoRectify()、CvInvoke.cvInitUndistortRectifyMap()和CvInvoke.cvRemap()构建输出图像,应该在Y轴上对齐,以便运行其中一个立体对应测试。
我发现您需要使用Emgu 2.1 ver 806才能使cvStereoRectify无需访问冲突错误即可正常工作。
我的问题是:
A)我的过程是否正确?我将相机内部校准作为单独的过程进行,因为由于相机间距为35厘米,在办公室很难使棋盘格同时出现在两个相机视野中并且还要移动它。我认为由于这些值是内在的,因此与相机相关,因此应该可以顺利地传递到立体程序中。这是正确的吗?
似乎在cvStereoRectify过程中会改变内在值,并使其非常不同。
例如:第一阶段的畸变值=0.22、-1.2、0.01、-0.01、2.6;经过cvStereoRectify处理后,这些值被更改为10、-489、-0.03、-0.09、13208。

我不是专家,但第一组数据看起来更像其他人的评论,第二组数据看起来相当离谱!

B) 在cvStereoRectify期间有没有停止内在+畸变值更新的方法?

C) 对于内在值(937,0,290,0,932,249,0,0,1),这个结果看起来正确吗?

非常感谢任何提示...我已经卡在这里有一段时间了...我真的不确定哪个部分出现了错误。任何提示或建议都将不胜感激...


我刚刚发现,如果您同时从L和R相机收集图像集,然后解决所有对象模型点(即棋盘角坐标)和两组图像角坐标(即左右相机子像素坐标),则一切似乎都能更好地运作。 - timemirror
似乎当棋盘相对靠近摄像头时,它的表现更好...我的问题是,由于我的相机距离很远,这给了我很少的工作空间。因此,我只是制作了一个更大的棋盘(200%),并将其放得更远...这样可以为我提供角落匹配的准确性,也有更多的移动空间。看起来有所帮助...仍在努力! - timemirror
@timemirror:你有没有看过Matlab校准工具箱(www.vision.caltech.edu/bouguetj/calib_doc/)或Danail Stoyonov的相机校准工具(http://ubimon.doc.ic.ac.uk/dvs/m581.html)?这两个工具都非常出色。顺便问一下,你在使用emguCV库时有什么发现吗?它的结果令你满意吗? - Kevin Boyd
您可以使用这些工具验证您在emguCV库中的发现,您还可以在此链接http://www.vision.caltech.edu/bouguetj/calib_doc/htmls/links.html找到许多其他校准工具箱的链接。 - Kevin Boyd
1
@Kevin Boyd - 感谢提供的链接和评论。不幸的是,我没有使用Matlab的访问权限。我发现Emgu非常好用。我发现我的立体相机校准有两个主要问题:a) 我必须同时校准立体系统中的两个相机;b)该系统使用两个廉价网络摄像头,具有手动对焦功能,其中一个对焦环略微松动,因此在校准后移动相机时,对焦会稍微变化,但足以使之前的校准失效。最终,我换成了高质量的视频摄像头,Emgu运行得非常完美。 - timemirror
我正在尝试做类似的事情,关于Emgu CameraCalibration.CalibrateCamera()函数,我有一个问题。您(或这里其他任何人)是否需要对IntrinsicCameraParameters参数进行任何预处理?比如起始值为某个特定值?此外,该函数采用ExtrinsicCameraParameters[]而不是(我预期的)ExtrinsicCameraParameters对象作为“out”参数。有人能提供有关如何处理这两个参数的见解吗?或者告诉我它们是否需要处理?我得到了一个'NaN'值作为返回。祝平安。 - sparkFinder
1个回答

0

我已经有几年没有使用EMGU了,但我曾经用它来校准相机和Kinect。

我发现如果矩形完全水平,矩形的角落顺序可能会有些混淆——我从未真正弄清楚原因,但这对我来说似乎可以解决问题。尝试将棋盘设置为滚动45度(即从前面看,你会看到更多的菱形,如果这有任何意义的话)。

我非常基本地理解,这应该使得两个摄像头都能够确保选择与第一个角相同的角作为起始角进行计数。

我不能保证这会解决你的问题——可能只是我的代码出了什么问题,导致当棋盘处于平面状态时无法产生规律性结果。不过,你可以很快测试一下,也许就能解决问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接