sapi
sapi

Reputation: 10224

OpenCV Perspective Transform giving unexpected result

I am trying to transform from a trapezoid (in the first image) to a rectangle (in the second image), but getting a strange result (in the third image).

enter image description here

My plan was to use a perspective transform, defined by the four corner points of the trapezoid and the four corner points of the rectangle.

In this example, for the trapezoid they are:

ptsTrap = [[  50.          100.        ]
           [  50.          200.        ]
           [ 250.           64.73460388]
           [ 250.          235.26539612]]

and for the rectangle:

ptsRect = [[  50.  100.]
           [  50.  200.]
           [ 250.  100.]
           [ 250.  200.]]

I am getting a perspective transform from these points:

T = cv2.getPerspectiveTransform(ptsTrap, ptsRect)

And then building the image from that:

arrTrapToRect = cv2.warpPerspective(arrTrap, T, arrTrap.shape[:2])

However, as you can see from the image, this isn't giving the expected transformation.

I can't seem to work out why even the points that defined the transform are not being projected according to it. Any ideas?

Upvotes: 5

Views: 4150

Answers (1)

Aurelius
Aurelius

Reputation: 11329

Your methodology is correct. The problem arises when you specify the coordinates of your corner points. I don't know how you calculated them, but you have swapped your X and Y axes. This is reflected in the transformation applied to your final image. I find the corner points to be:

ptsTrap = [[[  99.   51.]]
           [[  64.  251.]]
           [[ 234.  251.]]
           [[ 199.   51.]]]

ptsRect = [[[ 102.   49.]]
           [[ 100.  249.]]
           [[ 200.  250.]]
           [[ 200.   50.]]]

Finding the perspective transform from these points gives the correct result: Perspective Transform result

For reference, this is the code I used:

import cv2
import numpy as np

def find_corners(image):
    im = cv2.Canny(image, 100, 200)

    cnt = cv2.findContours(im,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[0]
    cnt = cv2.approxPolyDP(cnt[0], 5, True)
    return cnt.astype(np.float32)

def main(argv):
    trap = cv2.imread('trap.png', cv2.IMREAD_GRAYSCALE)
    rect = cv2.imread('rect.png', cv2.IMREAD_GRAYSCALE)

    ptsTrap = find_corners(trap)
    ptsRect = find_corners(rect)

    T = cv2.getPerspectiveTransform(ptsTrap, ptsRect)

    warp = cv2.warpPerspective(trap, T, rect.shape[:2])

    cv2.imshow('', warp)
    cv2.imwrite('warp.png', warp)
    cv2.waitKey()
    cv2.destroyAllWindows()

Upvotes: 9

Related Questions