正面から見た図を斜めから見た図に変換したいです。
例えば次のような図があります。
これを斜めから見ると次のような図になります。
これを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()
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個めは変換前の座標です。
座標は左上、右上、右下、左下の順で指定します。
赤が変換前、青が変換後です。
コメント