我正试图通过使用基本矩阵和维基百科上给出的算法。对于我需要找到基本矩阵。我正在使用OpenCV::findFundamentalMat
。
两种意想不到的行为:
- 使用不同的拟合算法产生不同的结果,尤其是CCD_ 2不同
- 给定一组点对(y,x(,yFx=0不成立,并且总是大于0
我有什么不明白的吗?我的例子是假的吗继续吗?有人能提出一个更好的测试例子吗?
下面是一个最小的例子。创建12个人工点,每个点移动右边10个像素的点,从这两组点并针对每个点打印CCD_ 3。
示例:
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)
,因此yFx
为0对于所有y
、x
。
我只从本质矩阵中找到了:T和R估计,但这并没有多大帮助。
编辑:yFx
是错误的循环方式(p1
/p2
在cout行中切换(。这个例子也不起作用,因为所有的点都位于一个平面上。
我相信基本矩阵求解方程p2.t() * F * p1 = 0
,即在代码中p1和p2颠倒。至于为什么8点算法返回零矩阵,我不知道,对不起。
编辑:好吧,我想我还记得为什么8点算法在这里产生了糟糕的结果。你在两组点之间的运动是纯平移,没有旋转,即它只有三个自由度。基本矩阵有7个自由度,因此无法估计;这被称为退化情况。关于基本/本质矩阵估计中退化情况的进一步描述,请参见本文。
也可能是这样的情况:通过人工移动像素坐标,在两个视点之间没有刚性变换,因此没有满足要求的基本矩阵。一个更好的测试用例可能是使用一个已知扭曲矩阵的函数,如cv::warpPerspective。
1( 使用不同的拟合算法产生不同的结果,尤其是FM_ 8POINT不同。
不同的方法不会给出相同的结果,这是真的:
- 例如,RANSAC(RANdom SAmple Consensus(是findFundamentalMat((中的默认方法,它用一组包含一些先前异常值的随机点的点来估计变换的参数,它以一定的概率产生正确的结果
- 而FM_8POINT被设计为使用具有线性无关方程的系统来寻找具有8个点的参数
2( 给定一组点对(y,x(,yFx=0不成立总是大于0。
这意味着你发现的基本矩阵是不正确的(估计不好(,这是由于你作为输入给出的纯平移,而实际上这是不可能的(这是2幅图像的退化情况,视点位于无穷远…(见极线几何(
我希望它能帮助你。。。Julien,