2012-07-16 10 views
7

Attribuite 4 punti che viene essere il risultato diCrea QTransform dato 4 punti definire l'unità trasformato quadrati

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

come posso trovare QTransform transform? (Ancora meglio: anche in un rettangolo di origine arbitraria)

motivazione: Dati i quattro punti angolo di un'immagine da trarre in un sistema di coordinate prospetticamente distorta, come posso disegnare l'immagine utilizzando QPainter?

Illustration of the problem

Questa è una schermata che illustra il problema in GIMP, dove si può trasformare un livello spostando intorno ai 4 angoli del livello. Ciò si traduce in una trasformazione prospettica. Voglio fare esattamente la stessa cosa in un'applicazione Qt. So che QTransform non è limitato alle trasformazioni affini ma può anche gestire le trasformazioni prospettiche.

+0

Nota: attualmente sto cercando di risolvere il problema. Comincio con p1 (che è il punto in alto a sinistra mappato (0,0)): quindi uso solo una matrice di traduzione. p2 e p3 possono essere raggiunti utilizzando una matrice di ridimensionamento e taglio. Ma ho problemi a raggiungere p4: non capisco la matematica dietro la trasformazione prospettica e quindi non so come il numero delle voci della matrice nella terza colonna influenzi la trasformazione. – leemes

risposta

2

Si dovrebbe essere in grado di farlo con QTransform.squareToQuad. Basta passarlo allo QPolygonF che si desidera trasformare.

A volte ho avuto alcuni problemi a ottenere squareToQuad per fare quello che voglio, e ho dovuto usare QTransform.quadToQuad invece, definendo il mio quad di partenza, ma si potrebbe avere più fortuna.

+0

Ancora, grazie mille. Accidenti, tutto il mio lavoro con tutta la matematica è stato per niente ... :) – leemes

1

Penso di aver trovato una soluzione, che calcola la matrice di trasformazione passo dopo passo.

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

Fino ad ora, trans descrive una trasformazione in parallelogramma. All'interno di questo paralellogramma, trovo p4 (relativamente) nel prossimo passo. Penso che questo possa essere fatto usando una formula diretta che non implichi un'inversione di 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; 

I valori x e y sono difficili da spiegare. Dato solo uno di questi (l'altro è impostato su 1), questo definisce solo il ridimensionamento relativo di p4. Ma una combinazione di entrambe le trasformazioni prospettiche xey, il significato di xey sono difficili; Ho trovato le formule per tentativi ed errori.

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

Alcuni test hanno dimostrato che questo porta ai risultati corretti. Tuttavia, non ho testato casi speciali come quelli in cui due punti sono uguali o uno di questi è nel segmento di linea tra gli altri due; Penso che questa soluzione potrebbe rompersi in tali situazioni.

Pertanto, ancora ricerca di alcune formule dirette per valori della matrice m11, m12 ... m33, dato il punto di coordinate p1.x(), p1.y() ... p4.x(), p4.y().

+0

Non dovresti essere in grado di utilizzare QTransform.squareToQuad? – dmd

+0

Aaaaah, grazie mille @dmd, questo è esattamente quello che stavo cercando, ovviamente.Non avevo abbastanza RTFM, o meglio detto, il nome della funzione non era assolutamente quello che mi aspettavo per una funzione del genere che fa esattamente ciò che voglio! – leemes

+0

@dmd, se lo scrivi come risposta, lo accetto. – leemes

Problemi correlati