我有对象让我们在模型图像上说。我想计算模型图像上的对象和目标图像上的对象之间的变换(位移、缩放、旋转)。我想假设对象可以被视为 2D,因此应该只计算 2D 转换。
首先,我想以手动辅助的方式进行。用户在模型图像上选择基点,然后在目标图像上选择目标点。点数应由用户定义(但不少于至少 2-3 个点)。当点给出不同的信息时,应该对转换进行平均,例如,可以从中计算匹配的质量。
所以问题是关于计算两组点的转换,但是因为我想在图像上做这件事,所以我添加了图像处理标签。
特别受欢迎的是带有一些代码或伪代码的参考和建议。
两点是很简单的问题,只需要线的旋转,比例和位移,但是如何用更多的点来做,并且平均它并计算一些质量因素。
目前的解决方案是:
void transformFnc(std::vector<PointF> basePoints, std::vector<PointF> targetPoints,
PointF& offset, double rotation, double scale)
{
std::vector<Line> basePointsLines;
std::vector<Line> targetPointsLines;
assert(basePoints.size() == targetPoints.size());
int pointsNumber = basePoints.size();
for(int i = 0; i < pointsNumber; i++)
{
for(int j = i + 1; j < pointsNumber; j++)
{
basePointsLines.push_back(Line(basePoints[i], basePoints[j]));
targetPointsLines.push_back(Line(targetPoints[i], targetPoints[j]));
}
}
std::vector<double> scalesVector;
std::vector<double> rotationsVector;
double baseCenterX = 0, baseCenterY = 0, targetCenterX = 0, targetCenterY = 0;
for(std::vector<Line>::iterator it = basePointsLines.begin(), i = targetPointsLines.begin();
it != basePointsLines.end(), i != targetPointsLines.end(); it++, i++)
{
scalesVector.push_back((*i).length()/(*it).length());
baseCenterX += (*it).pointAt(0.5).x();
baseCenterY += (*it).pointAt(0.5).y();
targetCenterX += (*i).pointAt(0.5).x();
targetCenterY += (*i).pointAt(0.5).y();
double rotation;
rotation = (*i).angleTo((*it));
rotationsVector.push_back(rotation);
}
baseCenterX = baseCenterX / pointsNumber;
baseCenterY = baseCenterY / pointsNumber;
targetCenterX = targetCenterX / pointsNumber;
targetCenterY = targetCenterY / pointsNumber;
offset = PointF(targetCenterX - baseCenterX, targetCenterY - baseCenterY);
scale = sum(scalesVector) / scalesVector.size();
rotation = sum(rotationsVector) / rotationsVector.size();
}
我能在这段代码中找到的唯一优化是从比例和旋转中消除那些与其他值相差太大的值。
我正在寻找解决方案命题的代码或伪代码。它也可以是一些代码的引用。
到目前为止,我知道的答案是:
- 可以使用RANSAC算法
- 我需要寻找一些最小二乘意义上的仿射变换计算算法