3

おそらく簡単に解決できる問題に直面していますが、正しく理解できません: 2 つの QImages、固定サイズの背景イメージimgBg、およびimgFgアフィン変換を使用して変換し、ペイント (およびクリップ) する必要がある 2 つ目の QImage があります。背景画像。

アフィン変換は次のとおりです。

  • 原点を中心にイメージをスケーリング (均一なスケーリング)
  • 原点を中心に画像を回転
  • 前景の画像の中心が基準位置にくるように、前景の画像を背景画像上の特定の基準位置に移動します。

これが私がこれまでに行ったことです:

// Setup transform
QTransform trans;
trans.translate(-imgFg.width()/2, -imgFg.height()/2); // move center of image to origin
trans.scale(scaleFac, scaleFac);
trans.rotate(angleDegrees);
trans.translate(imgFg.width()/2, imgFg.height()/2);

// Transform foreground image
imgFg = imgFg.transformed(trans);

// Paint on background image
QPointF referencePos(imgBg.width()/3, imgBg.height()/2); // some reference position
QPainter painter(&imgBg);
painter.drawImage(referencePos - QPointF(imgFg.width()/2, imgFg.height()/2), imgFg);

基準位置だけを変更する限り、すべて正常に動作します。スケーリングおよび/または回転を使用すると、画像も正しくスケーリングおよび回転されますが、正しい位置に配置されません (前景の画像の中心が基準点と一致しません)。変換パイプラインに何か問題がありますか? 私は間違いを犯しましたか?

4

1 に答える 1

3

で実行するステートメントの順序を逆にする必要がありますQTransform順序は、直感的思考の逆でなければなりません。これは、線形代数における変換行列の行列乗算に関係しています。(変換行列の基底の変更...) 問題は、変換がソース座標系に適用されることです。これは直感的ではありません。

覚えておいてください:複数の変換を適用したいときはいつでも、画像に対して行うこととはの順序でそれらを実行してください。

例については、QTransform のドキュメントのサンプル コードを参照してください。

テキストを半分の幅に拡大縮小し、時計回りに 45 度回転させ、原点を (50, 50) に移動します。

ここに画像の説明を入力

QTransform transform;
transform.translate(50, 50);
transform.rotate(45);
transform.scale(0.5, 1.0);

別の問題は、倍率を考慮して画像を元の位置に戻す必要があることです (質問のコメントでこれを指摘してくれた Mat に感謝します)。

コード スニペットに適用されます (操作の直感的な順序については、下から上に読んでください):

// Setup transform
QTransform trans;
trans.translate(imgFg.width()*scaleFac/2, imgFg.height()*scaleFac/2);
trans.rotate(angleDegrees);
trans.scale(scaleFac, scaleFac);
trans.translate(-imgFg.width()/2, -imgFg.height()/2);

最後に重要なことですが、画像の中心を新しい原点 (基準点) にしたいので、元に戻す必要はありません (今は最初の操作で、コードでは最後の操作です)。次に、別のサイズ/2を追加するのではなく、参照点で画像をペイントします。また、画像に変換を適用してからこの画像をペイントしないでください。少なくともそれは良いスタイルではありません。変換をペインターに適用し、後で適用を解除するだけです。

QTransform trans;
trans.scale(scaleFac, scaleFac);
trans.rotate(angleDegrees);
trans.translate(imgFg.width()/2,imgFg.height()/2);

// Save old transform (only needed if you use other transformations)
const QTransform &oldTrans = painter.transform();
// Apply new transform
painter.setTransform(trans);
// Paint image at reference point
painter.drawImage(referencePoint, imgFg);
// Restore transform
painter.setTransform(oldTrans);
于 2012-05-27T12:46:04.783 に答える