PDA

View Full Version : Perspective correction with QTransform



dustparticle
3rd June 2008, 13:12
I have a QGraphicsScene and in this scene I have a QGraphicsPixmapItem. In addition I have four points (QGraphicsItem) in the scene that I can move around on top (z = 1) of the QGraphicsPixmapItem. By placing these points and mapping them to the scene I can select an area of the pixmap:
http://img37.picoodle.com/img/img37/4/6/3/f_cap1m_b764e47.jpg (http://www.picoodle.com/view.php?img=/4/6/3/f_cap1m_b764e47.jpg&srv=img37)
(picture: cap-1)

At the moment I am just using the top left and the bottom right points to create a rectangle to copy an area:


QPixmap copy = pixmap.copy(upperLeftX, upperLeftY, rectWidth, rectHeight);


I can now copy any rectangular area, which is nice, but what I would like to do in addition to this is to position the points in any quadrilateral arrangement:
http://img31.picoodle.com/img/img31/4/6/3/f_cap2m_eb028fa.jpg (http://www.picoodle.com/view.php?img=/4/6/3/f_cap2m_eb028fa.jpg&srv=img31)
(picture: cap-2)

I then want to perform a perspective correction of that area and finally make a copy of the result.

So what I want is to make picture "cap-2" look like picture "cap-1". Any ideas regarding how I could aproach this problem? Is this possible with only the QPixmap and the four point coordinates that are available? I'm not expecting it to work perfectly. A fairly good aproximation would be OK.


So far I have been thinking along these lines:

1. Use the information from the mapped points to make a QTransform and then use this QTransform to transform the whole pixmap.


QTransform transform;
// create transform (use transform.rotate(degree, Qt::?Axis)? or make a QTransform from scratch?)
QPixmap transformedPixmap = originalPixmap.transformed(transform);

Then select the area I want and copy it:


transformedPixmap.copy(upperLeftX, upperLeftY, rectWidth, rectHeight);

(I don't know how to make a QTransform that will perform the required transformation. Suggestions?)

OR

2. Create a QPolygonF with the mapped points. Then use the quadToSquare function to create the transform (bool QTransform::quadToSquare ( const QPolygonF & quad, QTransform & trans )). I am not able to get this to work (quadToSquare() returns false).


QPolygonF area(5);
area << selector->getUpperLeftNodePoint() << selector->getLowerLeftNodePoint() <<
selector->getLowerRightNodePoint() << selector->getUpperRightNodePoint() <<
selector->getUpperLeftNodePoint();
QTransform trans;
bool transOK = QTransform::quadToSquare(area, trans);
if (transOK) cout << "Transformed: true" << endl;
else cout << "Transformed: false" << endl;

If you have any suggestions regarding how I could make one of my approaches work correctly or if you know some other way to tackle this problem I would be very grateful. Questions, general tips, detailed instructions, code and suggested reading are all welcome.

Thanks

-----------
OS: Mac OS X 10.5.3
Qt version: 4.4.0

jacek
3rd June 2008, 23:01
2. Create a QPolygonF with the mapped points. Then use the quadToSquare function to create the transform (bool QTransform::quadToSquare ( const QPolygonF & quad, QTransform & trans )). I am not able to get this to work (quadToSquare() returns false).


QPolygonF area(5);
area << selector->getUpperLeftNodePoint() << selector->getLowerLeftNodePoint() <<
selector->getLowerRightNodePoint() << selector->getUpperRightNodePoint() <<
selector->getUpperLeftNodePoint();
QTransform trans;
bool transOK = QTransform::quadToSquare(area, trans);
if (transOK) cout << "Transformed: true" << endl;
else cout << "Transformed: false" << endl;


I think that Qt doesn't expect to see a quad with five vertices. Try omitting the second upper left node point.