私はオブジェクトをモデル画像で言いましょう。モデル イメージ上のオブジェクトとターゲット イメージ上のオブジェクト間の変換 (変位、スケール、回転) を計算したいと考えています。オブジェクトは 2D として扱うことができるので、2D 変換のみを計算する必要があると仮定したいと思います。
まず、手動で支援したいです。ユーザーは、モデル イメージ上のベース ポイントを選択し、次にターゲット イメージ上のターゲット ポイントを選択します。ポイント数はユーザーが定義する必要があります (ただし、最低 2 ~ 3 ポイント以上)。ポイントが異なる情報を提供する場合、変換を平均化する必要があります。たとえば、これからマッチングの品質を計算できます。
したがって、質問は2セットのポイントの変換を計算することですが、画像でそれを実行したいので、画像処理タグを追加しました。
特に歓迎されるのは、いくつかのコードまたは疑似コードに関する参照とアドバイスです。
2 つのポイントを使用すると、非常に簡単な問題になります。線の回転、スケール、および変位のみを取得する必要がありますが、より多くのポイントを使用してそれを平均化し、いくつかの品質係数を計算する方法です。
現在の解決策は次のとおりです。
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 アルゴリズムを使用できます
- 最小二乗法でのアフィン変換計算アルゴリズムを探す必要があります