2012-07-16 26 views
7

mieli 4 punkty będąc być wynikiemTworzenie QTransform podane 4 punkty definiujące przekształcone kwadrat jednostkowy

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

jak znajdę QTransform transform? (Nawet lepiej: również podane dowolne źródło prostokąt)

Motywacja: Biorąc pod uwagę cztery punkty narożne obrazu należy wyciągnąć w perspektywicznie zniekształconego układzie współrzędnych, w jaki sposób można narysować obraz przy użyciu QPainter?

Illustration of the problem

To ekranu ilustrujący problem Gimp gdzie można przekształcić warstwą, przesuwając się po 4 rogach warstwy. Powoduje to transformację perspektywy. Chcę zrobić dokładnie to samo w aplikacji Qt. Wiem, że QTransform nie jest ograniczony do transformacji afinicznych, ale może również obsługiwać przekształcenia perspektywy.

+0

Uwaga: aktualnie próbuję rozwiązać problem. Zaczynam od p1 (który jest zmapowanym lewym górnym punktem (0,0)): Dlatego używam tylko macierzy translacji. p2 i p3 można uzyskać za pomocą macierzy skalowania i ścinania. Ale mam problemy z osiągnięciem p4: nie rozumiem matematyki kryjącej się za transformacją perspektywy i dlatego nie wiem, jak liczba wpisów w macierzy w trzeciej kolumnie wpływa na transformację. – leemes

Odpowiedz

2

Powinieneś być w stanie to zrobić z QTransform.squareToQuad. Po prostu przekaż mu numer QPolygonF, który chcesz przekształcić.

Czasami miałem problemy z SquareToQuad, aby robić to, co chcę, i musiałem użyć QTransform.quadToQuad zamiast tego, definiując własne początkowe quady, ale możesz mieć więcej szczęścia.

+0

Jeszcze raz, dziękuję bardzo. Cholera, cała moja praca z całą matematyką była na darmo ... :) – leemes

1

Myślę, że znalazłem rozwiązanie, które krok po kroku oblicza macierz transformacji.

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

Do tej pory trans opisuje transformację równoległoboku. Wewnątrz tego paralellogramu znajduję p4 (relatywnie) w następnym kroku. Myślę, że można to zrobić za pomocą bezpośredniej formuły nie obejmującej inwersji 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; 

Wartości x i y są trudne do wyjaśnienia. Biorąc pod uwagę tylko jeden z nich (drugi zestaw do 1), definiuje to względne skalowanie tylko z p4. Ale kombinacja transformacji perspektywy x i y, znaczenie xiy jest trudne; Znalazłem formuły metodą prób i błędów.

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

Niektóre testy wykazały, że prowadzi to do prawidłowych wyników. Nie testowałem jednak przypadków specjalnych, takich jak te, w których dwa punkty są równe lub jeden z nich znajduje się na linii między dwoma innymi; Myślę, że to rozwiązanie może załamać się w takich sytuacjach.

Dlatego też nadal szukać pewnych bezpośrednich formuł dla wartości matryca m11, m12 ... m33, biorąc pod uwagę punkt współrzędne p1.x(), p1.y() ... p4.x(), p4.y().

+0

Nie powinieneś używać QTransform.squareToQuad? – dmd

+0

Aaaaah, bardzo dziękuję @dmd, to dokładnie to, czego szukałem, oczywiście.Nie napisałem wystarczająco RTFM, a raczej nie powiedziałem, że nazwa funkcji całkowicie nie jest tym, czego oczekiwałem w przypadku takiej funkcji, która dokładnie robi to, czego chcę! – leemes

+0

@dmd, jeśli napiszesz to jako odpowiedź, zaakceptuję to. – leemes