Rotate by warpPerspective after getPerspectiveTransform by 4 points in C++

asked 2019-11-16 15:35:56 -0500

Hi everyone. I use from getPerspectiveTransform and warpPerspective to rotate and crop my picture and have a straight picture, but when I do that in the end my picture doesn't stretch.

this is my code :

int main()
cv::Mat src = cv::imread("E:\\aaaaaa.jpg");
vector<Point> not_a_rect_shape;
not_a_rect_shape.push_back(Point(2224, 257));
not_a_rect_shape.push_back(Point(372, 393));
not_a_rect_shape.push_back(Point(338, 1498));
not_a_rect_shape.push_back(Point(2397, 1414));

// For debugging purposes, draw green lines connecting those points 
// and save it on disk
const Point* point = &not_a_rect_shape[0];
int n = (int)not_a_rect_shape.size();
Mat draw = src.clone();
polylines(draw, &point, &n, 1, true, Scalar(0, 255, 0), 3, LINE_AA);
imwrite("E:\\draw.jpg", draw);

// Assemble a rotated rectangle out of that info
RotatedRect box = minAreaRect(cv::Mat(not_a_rect_shape));
std::cout << "Rotated box set to (" << box.boundingRect().x << "," << box.boundingRect().y << ") " << box.size.width << "x" << box.size.height << std::endl;

Point2f pts[4];


// Does the order of the points matter? I assume they do NOT.
// But if it does, is there an easy way to identify and order 
// them as topLeft, topRight, bottomRight, bottomLeft?

cv::Point2f src_vertices[4];
src_vertices[0] = pts[0]; // bottomLeft
src_vertices[1] = pts[1]; // topLeft
src_vertices[2] = pts[2]; // Top Right
src_vertices[3] = pts[3]; // bottomRight

Point2f dst_vertices[4];
dst_vertices[0] = Point(0, box.boundingRect().height);
dst_vertices[1] = Point(0, 0);
dst_vertices[2] = Point(box.boundingRect().width, 0);
dst_vertices[3] = Point(box.boundingRect().width, box.boundingRect().height);

Mat warpMatrix = getPerspectiveTransform(src_vertices, dst_vertices);

cv::Mat rotated;
cv::Size size(box.boundingRect().width, box.boundingRect().height);
warpPerspective(src, rotated, warpMatrix, size, INTER_LINEAR, BORDER_CONSTANT);

imwrite("E:\\rotated.jpg", rotated);

return 0;

This is the original Picture : image description

And this is the result: image description

image description

But I need to stretch it like this: image description

I changed src_vertices and dst_vertices to 4 points and after that I changed dst_vertices as this manually and it was ok but it's not a good answer because I need to do that automatically:

Point2f dst_vertices[4];
dst_vertices[0] = Point(0, box.boundingRect().height);
dst_vertices[1] = Point(-90, -70);
dst_vertices[2] = Point(box.boundingRect().width+140, 0);
dst_vertices[3] = Point(box.boundingRect().width, box.boundingRect().height);

How Can I do that?

Thank you.

edit retag flag offensive close merge delete


Does the order of the points matter?

YES ! for both point sets, you need the same start point (e.g. top-left) and the same winding (e.g. clockwise)

berak gravatar imageberak ( 2019-11-17 02:22:55 -0500 )edit

The points must be 3D vectors (homogeneous coordinates) instead of 2D.

catvision gravatar imagecatvision ( 2019-12-02 19:56:19 -0500 )edit