找不到基础矩阵的问题,FindFundamentalMatrix函数无法找到基础矩阵。

5
我正在尝试使用基础矩阵和维基百科上给出的算法来恢复相机的运动。为此,我需要找到基础矩阵。我使用OpenCV::findFundamentalMat来实现这一点。
两个意外行为:
  1. 使用不同的拟合算法会产生不同的结果,特别是FM_8POINT
  2. 给定一组点对(y,x),yFx=0未被满足,总是大于0。
我理解有误吗?我的示例是否错误,或者发生了什么?有人能提供一个更好的测试示例吗?
以下是一个最小示例。创建12个人工点,将每个点向右移动10个像素,从这些点集中找到基础矩阵,并为每个点打印yFx
示例:
int main(int argc, const char* argv[])
{
   // Create two sets of points. Points in pts2 are moved 10pixel to the right of the points in pts1.
   std::vector<cv::Point2f> pts1, pts2;
   for(double y = 0; y < 460; y+=150)
   {
           for(double x= 0; x < 320; x += 150)
           {
                   pts1.push_back(cv::Point2f(x, y));
                   pts2.push_back(cv::Point2f(x+10.0, y));
           }
   }

   cv::Mat F = cv::findFundamentalMat(pts1, pts2);

   for(int i = 0; i < pts1.size(); i++)
   {
           // Creating p1, p2, the two points. Please let me know if this can be done in fewer lines.
           cv::Mat p1(3,1, CV_64FC1), p2(3,1, CV_64FC1);

           p1.at<double>(0) = pts1.at(i).x;
           p1.at<double>(1) = pts1.at(i).y;
           p1.at<double>(2) = 1.0;

           p2.at<double>(0) = pts2.at(i).x;
           p2.at<double>(1) = pts2.at(i).y;
           p2.at<double>(2) = 1.0;

           // Print yFx for each pair of points. This should be 0 for all.
           cout << p1.t() * F * p2 << endl;
   }
}

对于FM_RANSAC,我得到
[1.999], [2], [2], [1.599], [1.599], [1.599], [1.198], [1.198], [1.198], [0.798], [0.798], [0.798]

对于FM_8POINT,基础矩阵是zeros(3,3),因此对于所有的yxyFx都是0。
我只找到了:从本质矩阵中估计T和R,但那并没有帮助太多。 编辑yFx的顺序是错误的(在cout行中交换p1/p2)。这个例子也不起作用,因为所有的点都在一个平面上。
2个回答

3

我认为基本矩阵解决了方程p2.t() * F * p1 = 0,也就是说你在代码中颠倒了p1和p2的位置。至于8点法算法为什么会返回零矩阵,我不知道,抱歉。

编辑:好的,我想起来为什么8点法算法在这里产生了错误的结果。你两组点之间的运动是纯平移而没有旋转,即它只有三个自由度。基本矩阵有7个自由度,因此无法估计;这被称为退化情况。请参见这篇论文,进一步描述了估计基础/本质矩阵中的退化情况。

还可能存在这样一种情况,即通过人工移动像素坐标获得的两个视点之间不存在刚性变换,因此不存在满足要求的基本矩阵。更好的测试案例可能是使用 cv::warpPerspective 等函数与已知的变形矩阵。


好的,我搞错了p1和p2的顺序。感谢您发现了这个错误。我现在会去看这篇论文,而Hartley&Zisserman不久就会来到我的门口,也许他们可以提供帮助。 - Unapiedra

1
1) 使用不同的拟合算法会产生不同的结果,特别是FM_8POINT算法会有所不同。
不同的方法确实会产生不同的结果:
例如,在findFundamentalMat()函数中,RANSAC(随机抽样一致性)是默认方法,它使用一组包含一些随机点的点来估计变换的参数,它以一定的概率产生正确的结果。
而FM_8POINT是设计用于使用具有线性独立方程的8个点来查找参数的。
2) 给定一组点对(y, x),yFx = 0未被满足,且始终大于0。
这意味着您找到的基础矩阵不正确(估计错误),这是由于您输入的纯平移造成的,在现实中,这是不可能的(这是两个视点位于无限远处的图像的退化情况...(请参见极线几何))
希望能对您有所帮助...
Julien,

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