I stumbled upon this question and am trying to perform perspective transformation with Python Pillow.
This is specifically what I am trying to do and what the result looks like:
And this is the code that I used to try it:
from PIL import Image
import numpy
# function copy-pasted from https://stackoverflow.com/a/14178717/744230
def find_coeffs(pa, pb):
matrix = []
for p1, p2 in zip(pa, pb):
matrix.append([p1[0], p1[1], 1, 0, 0, 0, -p2[0]*p1[0], -p2[0]*p1[1]])
matrix.append([0, 0, 0, p1[0], p1[1], 1, -p2[1]*p1[0], -p2[1]*p1[1]])
A = numpy.matrix(matrix, dtype=numpy.float)
B = numpy.array(pb).reshape(8)
res = numpy.dot(numpy.linalg.inv(A.T * A) * A.T, B)
return numpy.array(res).reshape(8)
# test.png is a 256x256 white square
img = Image.open("./images/test.png")
coeffs = find_coeffs(
[(0, 0), (256, 0), (256, 256), (0, 256)],
[(15, 115), (140, 20), (140, 340), (15, 250)])
img.transform((300, 400), Image.PERSPECTIVE, coeffs,
Image.BICUBIC).show()
I am not exactly sure how the transformation works, but it seems the points move quite into the opposite direction (e.g. I need to do (-15, 115) to make point A move to the right. However, it also won't move 15 pixels but 5).
How can I determine the exact coordinates of the target points to skew the image properly?
Let’s now quickly analyze the python code to do a perspective transformation. First we need to load the image we want to transform. So let’s import the libraries and then we load the image. We then need to select 4 points, in order: top-left, top-right, bottom-left, bottom-right.
In Perspective Transformation, we can change the perspective of a given image or video for getting better insights into the required information. In Perspective Transformation, we need to provide the points on the image from which want to gather information by changing the perspective.
In Perspective Transformation, we need to provide the points on the image from which want to gather information by changing the perspective. We also need to provide the points inside which we want to display our image. Then, we get the perspective transform from the two given sets of points and wrap it with the original image.
Python PIL | Image.transform () method Last Updated : 02 Aug, 2019 PIL is the Python Imaging Library which provides the python interpreter with image editing capabilities. The Image module provides a class with the same name which is used to represent a PIL image.
The answer is very simple: just swap the source and target coordinates. But it's not your fault: the author of the linked answer made it particularly easy to get confused, because target, source
is (in this case) a confusing order for function arguments, because function arguments have no helpful names, and because the example does the backward transformation of a shear.
Instead of swapping source and target coordinates, you can also swap the arguments of the find_coeffs
function. Even better, rename them too, like
def find_coeffs(source_coords, target_coords):
matrix = []
for s, t in zip(source_coords, target_coords):
matrix.append([t[0], t[1], 1, 0, 0, 0, -s[0]*t[0], -s[0]*t[1]])
matrix.append([0, 0, 0, t[0], t[1], 1, -s[1]*t[0], -s[1]*t[1]])
A = numpy.matrix(matrix, dtype=numpy.float)
B = numpy.array(source_coords).reshape(8)
res = numpy.dot(numpy.linalg.inv(A.T * A) * A.T, B)
return numpy.array(res).reshape(8)
Leaving the rest of your code the same, only using a different image, I get this transformation:
⇒
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With