Create a QTransform based on 4 points defining the transformed unit square

Given that 4 points are the result

QPolygon poly = transform.mapToPolygon(QRectF(0, 0, 1, 1)); 

How can I find QTransform transform ? (Even better: an arbitrary source rectangle is also specified)

Motivation. Given that the four corner points of the image should be drawn in a perspective distorted coordinate system, how to draw an image using QPainter?

Illustration of the problem

This is a screenshot illustrating a problem in GIMP where you can transform a layer by moving around the 4 corners of the layer. This leads to a transformation of perspective. I want to do the same in a Qt application. I know that QTransform is not limited to affine transforms, but can also handle perspective transformations.

+7
source share
2 answers

You can do this with QTransform.squareToQuad . Just pass it the QPolygonF you want to convert.

I sometimes had problems with what squareToQuad had to do, and I had to use QTransform.quadToQuad , defining my own starting quad, but you might have more luck.

+2
source

I think I found a solution that calculates the transformation matrix step by step.

 // some example points: QPointF p1(1.0, 2.0); QPointF p2(2.0, 2.5); QPointF p3(1.5, 4.0); QPointF p4(3.0, 5.0); // define the affine transformation which will position p1, p2, p3 correctly: QTransform trans; trans.translate(p1.x(), p1.y()); trans.scale(p2.x() - p1.x(), p3.y() - p1.y()); trans.shear((p3.x() - p1.x()) / trans.m11(), (p2.y() - p1.y()) / trans.m22()); 

So far, the trance describes a parallelogram transformation. In this parallelogram, I find p4 (relatively) in the next step. I think this can be done using a direct formula that is not related to the inverse of trans.

 // relative position of the 4th point in the transformed coordinate system: qreal px = trans.inverted().map(p4).x(); qreal py = trans.inverted().map(p4).y(); // this defines the perspective distortion: qreal y = 1 + (py - 1) / px; qreal x = 1 + (px - 1) / py; 

The x and y values ​​are hard to explain. Given only one of them (the other is 1 ), this determines the relative scaling of only p4 . But the combination of perspective x and y transformation, the meaning of x and y is difficult; I found the formulas by trial and error.

 // and thus the perspective matrix: QTransform persp(1/y, 0, 1/y-1, 0, 1/x, 1/x-1, 0, 0, 1); // premultiply the perspective matrix to the affine transformation: trans = persp * trans; 

Some tests have shown that this leads to the correct results. However, I did not test special cases, such as those where two points are equal or one of them is on a line segment between the other two; I think this decision may break in such situations.

Therefore, I'm still looking for some direct formulas for the values ​​of the matrix m11 , m12 ... m33 , given the point coordinates p1.x() , p1.y() ... p4.x() , p4.y() .

+1
source

All Articles