使用Python PIL进行透视变换,使用源/目标坐标

7
我发现了这个问题,并尝试使用Python Pillow执行透视变换。
具体而言,我想做什么以及结果如何:

enter image description here

这是我用来尝试的代码:

from PIL import Image
import numpy

# function copy-pasted from https://dev59.com/-WYq5IYBdhLWcg3wzDvk#14178717
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()

我不确定转换是如何工作的,但似乎点会朝相反方向移动(例如,我需要执行(-15, 115)使点A向右移动。但它也不会移动15像素,而是5像素)。
如何确定目标点的确切坐标以正确扭曲图像?
1个回答

15
答案非常简单:只需交换源坐标和目标坐标即可。但这不是你的错:链接答案的作者让人特别容易混淆,因为在这种情况下,target, source是函数参数的一个令人困惑的顺序,因为函数参数没有有用的名称,并且示例进行了剪切的后向转换。
除了交换源和目标坐标之外,您还可以交换find_coeffs函数的参数。更好的做法是也将它们重命名,例如:
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)

只更换图片,保留其余代码,我得到了这个转换效果:

红色角落的沃尔特    ⇒    透视图中的红色角落的沃尔特


尽管你的测试图片很经典,但我认为是时候让其他东西来取代它了。在我的回答中,我会尽量使用我自己拍摄的图片。 - Mark Ransom
我不同意,但不想在这里讨论,所以我用我儿子拍的我的照片替换了图片。 - Walter Tross
我刚意识到在原始的SO答案中没有看到“其中pb是当前平面上的四个顶点,而pa包含结果平面上的四个顶点”,所以我假设pb是结果平面,而pa是当前平面。我一直在想为什么没有人遇到这个代码问题,但显然我自己无法阅读 :) 谢谢! - Maxim Zubarev
不客气!但是,正如我写的那样,在我看来,这不是你的错。顺便说一下,我在find_coeffs()里交换了第三行的循环变量。 - Walter Tross

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接