読者です 読者をやめる 読者になる 読者になる

PILのImage.transformの使い方 (QUAD, MESH)

PILのImage.transformの使い方 (AFFINE) - umejanのブログのつづき。

Image.QUADの変形

ランベルトの四角形の変形?

wikipediaの"平行線公準"に記載のあった四角形だと思う。

Image.QUADのdata指定方法

8 tupples (x0, y0, x1, y1, x2, y2, x3, y3)

四角形の左上、左下、右下、右上の角を指定する。

Image.QUADのサンプル

Image.MESHのサンプルに含めた。

Image.MESHの変形

Image.QUADを連続して実行する。

たぶん、格子状に画像を繰り返すのに使うと思う。

ほかの使い道は浮かばず。

Image.MESHのdata指定方法

出力域のサイズとQUADのdataと同じパラメータのリスト。

こんな感じで指定する。

[
  [(width1, height1, (x1_0, y1_0, x1_1, y1_1, x1_2, y1_2, x1_3, y1_3)],
  [(width2, height2, (x2_0, y2_0, x2_1, y2_1, x2_2, y2_2, x2_3, y2_3)],
  ...
]

Image.QUADとImage.MESHのサンプル

画像の右端を引き伸ばしたサンプル(QUAD)と
画像の右端を縮めたサンプル(QUAD)と
画像を格子状に4つ繰り返したサンプル(MESH)。

# -*- coding: utf-8 -*-
from __future__ import print_function
from PIL import Image
from PIL import ImageDraw
import numpy as np
import argparse

parser = argparse.ArgumentParser(description="Image.transformのサンプル")

parser.add_argument("--output","-o", required=True, type=str
                   , help="出力ファイル")

args = parser.parse_args()

# 変換元の画像をロード
def load_image() :
  #im = Image.open("xxxx.png")

  # サンプルとして、41x33の画像を作成。グレースケール256階調
  # 8ドットごとに格子を描画
  im = Image.new("L", (41, 33), color=0)
  draw = ImageDraw.Draw(im)
  for i in range(6) :
    draw.line([(i*8, 0), (i*8, 32)], fill=255, width=1)
  for i in range(5) :
    draw.line([(0, i*8), (40, i*8)], fill=255, width=1)
  
  # 四角を左上の格子の中に描画
  draw.rectangle([3, 3, 6, 6], fill=255)
  
  del draw

  return im


im = load_image()


#
# Image.QUAD
# 
# data : 8 tupples (x0, y0, x1, y1, x2, y2, x3, y3)
# 左上、左下、右下、右上の角を指定
# 
# ランベルトの四角形
# 
subnm = "quad"
data = (0, 0, 0, 33, 41, 33, 32, 10) # ランベルトの四角形?
im2 = im.transform(im.size, Image.QUAD, data, Image.BILINEAR)

filenm = args.output + "_" + subnm + "_" + "_".join(map(str, data)) + ".png"
print("filenm:", filenm)

im2.save(filenm)

subnm = "quad2"
data = (0, 0, 0, 33, 41, 33, 51, -10) # ランベルトの四角形の逆パターン
im2 = im.transform(im.size, Image.QUAD, data, Image.BILINEAR)

filenm = args.output + "_" + subnm + "_" + "_".join(map(str, data)) + ".png"
print("filenm:", filenm)

im2.save(filenm)

#
# Image.MESH
# 
# data : 以下のリスト
#  出力域のboxと
#  4隅(x1, y1, x2, y2, x3, y3, x4, y4)
#  例)
#   [
#    ( 0, 0, 20, 33), (0, 0, 0, 33, 41, 33, 32, 10),
#    (21, 0, 41, 33), (0, 0, 0, 33, 28, 20, 41, 0)
#   ]
# 
# QUADの処理を繰り返す。
# 使い方としては、格子状に画像を繰り返したりするくらいか。
#

subnm = "mesh"
print("im.size",im.size)
data = [
    [( 0,  0, 20, 16), (0, 0, 0, 33, 41, 33, 41, 0)],
    [(21,  0, 41, 16), (0, 0, 0, 33, 41, 33, 41, 0)],
    [( 0, 17, 20, 33), (0, 0, 0, 33, 41, 33, 41, 0)],
    #[(21, 17, 41, 33), (0, 0, 0, 33, 41, 33, 32, 10)] 変形して適用することも可能
    [(21, 17, 41, 33), (0, 0, 0, 33, 41, 33, 41, 0)]
]

#im2 = im.transform(im.size, Image.MESH, data, Image.BILINEAR)
im2 = im.transform(im.size, Image.MESH, data, Image.NEAREST)

filenm = args.output + "_" + subnm + "_" + "_".join(map(str, data)) + ".png"
print("filenm:", filenm)

im2.save(filenm)

変換元の画像

f:id:umejan:20160424202553p:plain ※ふちが白枠。

変換後の画像

  • 画像の右端を引き伸ばしたサンプル(QUAD)
    f:id:umejan:20160426185038p:plain
  • 画像の右端を縮めたサンプル(QUAD)
    f:id:umejan:20160426185051p:plain
  • 画像を格子状に4つ繰り返したサンプル(MESH)
    f:id:umejan:20160426185105p:plain

関連

PILのImage.transformの使い方 (EXTENT) - umejanのブログ
PILのImage.transformの使い方 (AFFINE) - umejanのブログ
PILのImage.transformの使い方 (PERSPECTIVE) - umejanのブログ