Opencv 如果在EstimaterialGidTransform或getAffineTransform中提供更多输入,会发生什么?
我使用的是大约两个100点的向量的变换,效果很好。 但无论如何,getAffineTransform不起作用 我知道findHomography使用RANSAC找到最佳矩阵,getPerspectiveTransform只需要4个点 我的问题是,如果我在EstimaterialGidTransform或getAffineTransform中提供更多输入,会发生什么Opencv 如果在EstimaterialGidTransform或getAffineTransform中提供更多输入,会发生什么?,opencv,Opencv,我使用的是大约两个100点的向量的变换,效果很好。 但无论如何,getAffineTransform不起作用 我知道findHomography使用RANSAC找到最佳矩阵,getPerspectiveTransform只需要4个点 我的问题是,如果我在EstimaterialGidTransform或getAffineTransform中提供更多输入,会发生什么 它是否只需要输入矩阵中的4个点?或者做一些RANSAC?您提到的功能可以分为3种不同类型: 类型1:getAffineTransfo
它是否只需要输入矩阵中的4个点?或者做一些RANSAC?您提到的功能可以分为3种不同类型: 类型1:getAffineTransform和getPerspectiveTransform。给定一个平面上的3个点和另一个平面上的3个匹配点,可以计算这些平面之间的仿射变换。给定4个点,你们可以找到透视变换。这就是getAffineTransform和getPerspectiveTransform所能做的:它们需要3对和4对点,不多不少,并计算相关的变换。唯一的 类型2:EstimaterialGidTransform。如果无法获得绝对精度的点(通常是从图像中获取点时的情况),则需要3对以上的点来减少误差。越多越好(即准确度越高)。有不止一种方法可以定义要减少的错误,以及使用何种方法来查找最小错误。这个变换是最小化最小平方误差(我认为最流行的误差定义)。它通过求解方程组来实现这一点。如果您正好提供了3点,那么结果当然将与getAffineTransform的结果相同。您可以问,如果GetTransform可以完成它的工作,为什么我们需要OpenCV中的getAffineTransform。唉,这不是OpenCV中唯一的冗余 类型3:findHomography。这个更先进。它不仅可以处理点位置的错误,而且还可以处理异常值的存在。如果点之间存在一些错误的匹配,那么使用它们进行最小二乘误差估计将导致非常差的精度。它可以使用RANSAC或LMeDs测试可能的匹配,并消除这些异常值。它的工作原理类似于变换的多次迭代:为不同的点子集找到最小二乘匹配。如果您知道不存在异常值,则可以将“method”参数设置为0,它的工作方式与EstimaterialGidTransform类似—通过尝试最小化所有点匹配产生的最小二乘误差 编辑。感谢米卡的评论。 我想我的记忆力在捉弄我。我记得这个转换是通过OpenCV中的方程组实现的,但现在我检查了一下,发现米卡是对的。它确实使用了一些硬编码的RANSAC。。。很抱歉误导了你 对于那些仍然对封闭形式解决方案而非RANSAC感兴趣的人,这里是:
// find affine transformation between two pointsets (use least square matching)
static bool computeAffine(const vector<Point2d> &srcPoints, const vector<Point2d> &dstPoints, Mat &transf)
{
// sanity check
if ((srcPoints.size() < 3) || (srcPoints.size() != dstPoints.size()))
return false;
// container for output
transf.create(2, 3, CV_64F);
// fill the matrices
const int n = (int)srcPoints.size(), m = 3;
Mat A(n,m,CV_64F), xc(n,1,CV_64F), yc(n,1,CV_64F);
for(int i=0; i<n; i++)
{
double x = srcPoints[i].x, y = srcPoints[i].y;
double rowI[m] = {x, y, 1};
Mat(1,m,CV_64F,rowI).copyTo(A.row(i));
xc.at<double>(i,0) = dstPoints[i].x;
yc.at<double>(i,0) = dstPoints[i].y;
}
// solve linear equations (for x and for y)
Mat aTa, resX, resY;
mulTransposed(A, aTa, true);
solve(aTa, A.t()*xc, resX, DECOMP_CHOLESKY);
solve(aTa, A.t()*yc, resY, DECOMP_CHOLESKY);
// store result
memcpy(transf.ptr<double>(0), resX.data, m*sizeof(double));
memcpy(transf.ptr<double>(1), resY.data, m*sizeof(double));
return true;
}
//查找两个点集之间的仿射变换(使用最小二乘匹配)
静态布尔计算函数(常量向量和srcPoints、常量向量和dstPoints、Mat和transf)
{
//健康检查
如果((srcPoints.size()<3)| |(srcPoints.size()!=dstPoints.size())
返回false;
//输出容器
转换创建(2,3,CV_64F);
//填写矩阵
常量int n=(int)srcPoints.size(),m=3;
材料A(n,m,CV_64F)、xc(n,1,CV_64F)、yc(n,1,CV_64F);
对于(int i=0;Iafar有人计算出,如果提供了3个以上的点,EstimaterialGidTransform会在内部使用某种RANSAC,但此RANSAC具有硬编码参数。此外,您可以使用参数bool fullAffine
计算6自由度仿射变换EstimaterialGidTransform
@Mika,您是对的。它使用RANSAC。至于“fullAffine”参数,默认情况下它设置为“true”,即它从3对或更多点计算仿射变换。对于线性方程优化解决方案,我想我有时可能需要它!作为您的新编辑,我们可以认为当由于使用了RANSAC
,该点超过了3点。但是,当给定的点有一些错误的点时,我们通常会得到更糟糕的结果。为什么使用DECOMP\u CHOLESKY
?