これらの画像を、
こうしたい。
そういう関数があるだろうと思っていたけれど、無く、意外と面倒だったのでメモ。
変形。
Image.transform がある。しかも Transform.QUAD
という「欲しいものはこれでは?」という指定もある。が、これはやりたいことの逆。4隅を指定した四角形を、長方形になるように変形する。たぶん、写真に写った紙などの長方形のものを切り出すのに使うのだと思う。
行列を計算して、 Transform.PERSPECTIVE
で渡さないといけないらしい。
貼り付け。
上記の変形をした画像はこのように周囲が黒くなっている。
元の画像の部分だけを貼り付けたい。 Image.putalpha(255)
で元の画像をアルファ付きに変換する。そうすると transform
で外側の部分は透明になるので、この画像を paste
の貼り付け元とマスクの両方に指定すれば良い。
from PIL import Image
import numpy
imA = Image.open("a.jpg")
imB = Image.open("b.jpg")
# https://stackoverflow.com/a/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.float64)
B = numpy.array(pb).reshape(8)
res = numpy.dot(numpy.linalg.inv(A.T * A) * A.T, B)
return numpy.array(res).reshape(8)
imB.putalpha(255)
w, h = imB.size
coeffs = find_coeffs(
[(500, 200), (1400, 400), (1700, 1100), (300, 600)],
[(0, 0), (w, 0), (w, h), (0, h)],
)
imC = imB.transform(
imA.size,
Image.Transform.PERSPECTIVE,
coeffs,
Image.Resampling.BICUBIC,
)
imA.paste(imC, (0, 0), imC)
imA.save("result.png")