1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pillowで4隅の座標指定で変形して貼り付ける

Last updated at Posted at 2024-11-28

これらの画像を、

こうしたい。

そういう関数があるだろうと思っていたけれど、無く、意外と面倒だったのでメモ。

変形。

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")
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?