当我从每个摄像机的视图中获取对象的图片时,如何使用OpenCV检索旋转矩阵,平移向量以及每个摄像机的某些缩放因子?对于每张图片,我都有几个特征点的图像坐标.并非所有特征点都在所有图片中都可见.我想将对象的特征点的计算的3D坐标映射到稍微不同的对象,以将第二对象的形状与第一对象对齐.
我听说它可以使用,cv::calibrateCamera(...)
但我无法通过它......
有人有这种问题的经历吗?
在OpenCV中,我遇到了和你一样的问题.我有一个立体图像对,我想计算相机的外部参数和所有观察点的世界坐标.此问题已在此处理:
Berthold KP Horn.相对方向重新审视.Berthold KP Horn.人工智能实验室,麻省理工学院,545技术...
http://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.64.4700
但是,我无法找到这个问题的合适实现(也许你会找到一个).由于时间的限制,我没有时间去理解本文中的所有数学并自己实现,所以我想出了一个适合我的快速解决方案.我将解释我做了什么来解决它:
假设我们有两个摄像头,第一个摄像头有外部参数RT = Matx :: eye().现在猜一下第二台相机的旋转R. 对于在两个图像中观察到的每对图像点,我们计算它们在世界坐标中的相应光线的方向并将它们存储在2d阵列目录中(编辑:假设内部相机参数是已知的).我们可以这样做,因为我们假设我们知道每个相机的方向.现在我们构建一个超定线性系统AC = 0,其中C是第二个摄像机的中心.我为你提供了计算A的功能:
Mat buildA(Matx&R, Array dirs) { CV_Assert(dirs.size(0) == 2); int pointCount = dirs.size(1); Mat A(pointCount, 3, DataType ::type); Vec3d *a = (Vec3d *)A.data; for (int i = 0; i < pointCount; i++) { a[i] = dirs(0, i).cross(toVec(R*dirs(1, i))); double length = norm(a[i]); if (length == 0.0) { CV_Assert(false); } else { a[i] *= (1.0/length); } } return A; }
然后调用cv :: SVD :: solveZ(A)将为您提供此系统的范数1的最小二乘解.这样,您可以获得第二台摄像机的旋转和平移.然而,由于我只是猜测了第二台摄像机的旋转,我对其旋转进行了几次猜测(使用3x1矢量欧米茄参数化,我使用cv :: Rodrigues计算旋转矩阵)然后我通过在具有数字jacobian的Levenberg-Marquardt优化器中重复地求解系统AC = 0.它对我有用,但它有点脏,所以如果你有时间,我鼓励你实现论文中的解释.
编辑:
以下是Levenberg-Marquardt优化器中用于评估残留载体的例程:
void Stereo::eval(Mat &X, Mat &residues, Mat &weights) { MatxR2Ref = getRot(X); // Map the 3x1 euler angle to a rotation matrix Mat A = buildA(R2Ref, _dirs); // Compute the A matrix that measures the distance between ray pairs Vec3d c; Mat cMat(c, false); SVD::solveZ(A, cMat); // Find the optimum camera centre of the second camera at distance 1 from the first camera residues = A*cMat; // Compute the output vector whose length we are minimizing weights.setTo(1.0); }
顺便说一句,我在互联网上搜索了一些,并找到了一些其他代码,可用于计算相机之间的相对方向.我还没有尝试过任何代码,但它似乎很有用:
http://www9.in.tum.de/praktika/ppbv.WS02/doc/html/reference/cpp/toc_tools_stereo.html
http://lear.inrialpes.fr/people/triggs/src/
http://www.maths.lth.se/vision/downloads/