Qt使用QTransform合并两张图片

3
我面临一个问题,可能很容易解决,但我做不对: 我有两个QImages,一个固定大小的背景图像imgBg,和第二个QImage imgFg,应该使用仿射变换进行转换,然后绘制(并剪裁)在背景图像上。
仿射变换如下:
  • 围绕其原点缩放图像(均匀缩放)
  • 围绕其原点旋转图像
  • 将前景图像平移到背景图像上的某个参考位置,使前景图像中心位于参考位置。
到目前为止,我已经完成了以下工作:
// 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);

只要我只改变参考位置,一切都正常。当使用缩放和/或旋转时,图像也被正确地缩放和旋转,但它没有放置在正确的位置(前景图像的中心与参考点不匹配)。 变换管道有问题吗?我犯了错误吗?

1
我怀疑第二次翻译应该考虑缩放因子。 - Mat
1个回答

3
你需要颠倒在QTransform上执行的语句顺序。顺序必须是直觉思维的反向顺序。这与线性代数中转换矩阵的矩阵乘法有关(转换矩阵的基础变换...)。问题在于转换应用于源坐标系,这有点不直观。

因此,请记住:每当您想要应用多个转换时,请按照您对图像所做的操作的反向顺序进行。

有关示例,请参见QTransform文档中的示例代码:

Scale text to the half width, then rotate it clockwise by 45 degrees, then move its origin to (50, 50):

enter image description here

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);

感谢您的详细解释!通过缩放因子对最终翻译进行缩放,问题得到了解决。 - Hyndrix

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接