首先,我想以手动辅助的方式完成它。用户在模型图像上选择基准点,然后在目标图像上选择目标点。用户应该定义点的数量(但至少不少于某些最小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算法
- 需要在最小二乘意义下寻找某些仿射变换算法