Ask Your Question
0

Wrong perspective transform

asked 2018-07-31 10:17:05 -0600

papabiceps gravatar image

I'm trying to do perspective transform of an image to realign the perspective. This is the input image. I want to transform the input into a rectangle.

enter image description here

The old_pts in the code refer to the points points of the quadrangle. new_pts refer to the bounding rectangle around old_pts.

I calculated perspective transform from these points using:

M = cv2.getPerspectiveTransform(old_pts, new_pts)

I transformed the original image using:

transformed_img = cv2.warpPerspective(new_img, M, (new_img.shape[1], new_img.shape[0]))

But I'm getting an output that is not as expected. This is the output image. I don't know what is it I'm doing wrong. Any ideas ?

enter image description here

# new_img = cv2.imread('IMG_20180731_123517_HDR.jpg')
# new_img = cv2.resize(new_img, (int(new_img.shape[2] / 10), int(new_img.shape[0] / 10)))
old_pts = np.float32([[14, 163],
                      [11, 301],
                      [242, 294],
                      [226, 166]]
                     ) 
bor = cv2.boundingRect(old_pts)  # bounding_rect
ul = [bor[0], bor[2]]  # upper left
ur = [bor[0], bor[2] + bor[3]]  # upper right
br = [bor[0] + bor[2], bor[2] + bor[3]]  # bottom right
bl = [bor[0] + bor[2], bor[2]]  # bottom left

new_pts = np.float32([ul, ur, br, bl])

# for point in new_pts:
#     cv2.circle(new_img, (point[0], point[1]), 2, (0, 0, 255), -1)
old_pts = old_pts[:, ::-1]
new_pts = new_pts[:, ::-1]
M = cv2.getPerspectiveTransform(old_pts, new_pts)
M_inv = np.linalg.inv(M)
transformed_img = cv2.warpPerspective(new_img, M, (new_img.shape[1], new_img.shape[0]))

transforemed_img = transformed_img.astype(np.uint16)
cv2.imwrite('transformed.png', transformed_img)
cv2.imshow('transformed.png', transformed_img)
cv2.imshow('original', new_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
edit retag flag offensive close merge delete

Comments

I think the order of the points old_pts and new_pts are wrong. I tried flipping them over x-axis and tried all combinations that came to my mind, I'm not getting the result I wanted. I strongly suspect the points are the culprits. Any ideas ?

papabiceps gravatar imagepapabiceps ( 2018-08-01 01:02:29 -0600 )edit

your src_pts go clockwise, your dst_pts counterclockwise.

also your dst points have errors, e.g. ul = (bor[0], bor[1])

berak gravatar imageberak ( 2018-08-01 06:33:58 -0600 )edit

No, they don't. I have checked just now. These are the outputs of olp_pts and new_pts respectively.

[[163.  14.]   
 [301.  11.]
 [294. 242.]
 [166. 226.]]

[[163.  11.]
 [302.  11.]
 [302. 243.]
 [163. 243.]]
papabiceps gravatar imagepapabiceps ( 2018-08-01 07:18:18 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
0

answered 2018-08-03 18:57:42 -0600

updated 2018-08-03 18:58:40 -0600

image description

        1st-------2nd
          |         |
          |         |
          |         |
        3rd-------4th

         cv::Mat src= cv::imread( "c://03p.jpg",0);
         if (!src.data)
                         return 0;
         vector<Point> not_a_rect_shape;
        not_a_rect_shape.push_back(Point(122,0));
        not_a_rect_shape.push_back(Point(814,0));
        not_a_rect_shape.push_back(Point(22,540));
        not_a_rect_shape.push_back(Point(910,540));
         // 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, CV_AA);
        imwrite( "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;
         // 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?
         //(0,0) (960,0) (0,540) (960,540)
        cv::Point2f src_vertices[4];
        src_vertices[0] = not_a_rect_shape[0];
        src_vertices[1] = not_a_rect_shape[1];
        src_vertices[2] = not_a_rect_shape[2];
        src_vertices[3] = not_a_rect_shape[3];

        Point2f dst_vertices[4];
        dst_vertices[0] = Point(0, 0);
        dst_vertices[1] = Point(960,0);
        dst_vertices[2] = Point(0,540);
        dst_vertices[3] = Point(960,540);
        Mat warpMatrix = getPerspectiveTransform(src_vertices, dst_vertices);
        cv::Mat rotated;
        warpPerspective(src, rotated, warpMatrix, rotated.size(), INTER_LINEAR, BORDER_CONSTANT);
         // Display the image
        cv::namedWindow( "Original Image");
        cv::imshow( "Original Image",src);
        cv::namedWindow( "warp perspective");
        cv::imshow( "warp perspective",rotated);
        imwrite( "03p.jpg",src);
        cv::waitKey();
        return 0;
edit flag offensive delete link more

Comments

Any ideas on how to automatically order vertices instead of manually ordering them.

papabiceps gravatar imagepapabiceps ( 2018-08-03 21:14:03 -0600 )edit

in practise , i get all points ,and save the min x,min y one as the topleft,I will give you some code later

jsxyhelu gravatar imagejsxyhelu ( 2018-08-04 01:56:25 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2018-07-31 10:17:05 -0600

Seen: 4,492 times

Last updated: Aug 03 '18