У меня есть объект, который можно сказать на образ модели. Я хочу вычислить преобразование (смещение, масштаб, вращение) между объектом на образ модели и объектом на целевом изображении. Я хочу сделать предположение, что объект можно рассматривать как 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
- Мне нужно искать алгоритм вычисления аффинного преобразования в наименьшем квадратичном смысле