PillowのImage.PERSPECTIVEを使う方法

正面から見た図を斜めから見た図に変換したいです。
例えば次のような図があります。

これを斜めから見ると次のような図になります。

これをPythonのPillowでやりたいと思います。
PillowにはImage.PERSPECTIVEという仕組みがあります。これを使えば良さそうですが、公式の解説ページを見ても全く理解できません。
見つけたのが次のページです。

PILのImage.transformの使い方 (PERSPECTIVE) – umejanのブログ

ありがとうございます。
こちらの通りやったところ、できましたので、メモを兼ねて記事にしておきます。

from PIL import Image, ImageDraw
import numpy as np

def find_coeffs(pa, pb):
  # http://umejan.hatenablog.com/entry/2016/04/27/225553
  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 = np.matrix(matrix, dtype=np.float)
  B = np.array(pb).reshape(8)

  res = np.dot(np.linalg.inv(A.T * A) * A.T, B)
  ret = np.array(res).reshape(8)
  wk = []
  for v in ret :
    wk.append(round(v, 3))
  (alpha,beta) = (wk[6]+1, wk[7]+1)
  (x0,y0) = (wk[2], wk[5])
  (x1,y1) = (round((wk[0]+x0)/alpha,3), round((wk[3]+y0)/alpha,3))
  (x2,y2) = (round((wk[1]+x0)/beta,3), round((wk[4]+y0)/beta,3))
  return ret

im = Image.open("yahoo.png")
(w, h) = im.size

coeffs = find_coeffs(
  [(0, 0 - h * 0.25), (w, 0), (w, h), (0, h + h * 1.25)],
  [(0, 0), (w, 0), (w, h), (0, h)])

im_new = im.transform(im.size, Image.PERSPECTIVE, coeffs, Image.BILINEAR)

im_new.show()

find_coeffsの引数がポイントです。
引数は2個。1個めは変換後の座標、2個めは変換前の座標です。
座標は左上、右上、右下、左下の順で指定します。

赤が変換前、青が変換後です。

コメント

タイトルとURLをコピーしました