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

PILのImage.transformの使い方 (EXTENT)

先日、pythonで画像を変形させてみたいと思った。まあ、バッチで処理したかったので。

調べてみたらImage.transformという関数があるのを知るが、 使ってみようとしたところ、どんなパラメータを指定したらいいのかわからず途方にくれる。(泣)

ネットで調べたりして、なんとか使えるレベルまでになったので Image.transform の使い方を整理してみた。

とりあえず、今回は概要とEXTENTの使い方。

Image.transformの概要

reference

Image Module — Pillow (PIL Fork) 3.1.1 documentation

自分の環境では、Python2.7.6でPillowが2.3.0だが、ここで問題ないと思われるので。

Pillowに限らず、Python周りのバージョンとドキュメントの関連性の知識が足りずこれでいいのか判断できない。あとでPythonのドキュメントを見ておかないと。

変形方法の種類 (method)

methodというパラメータで指定するが、以下の5つがある。

  • PIL.Image.EXTENT
    矩形を切り取って拡大。

  • PIL.Image.AFFINE
    AFFINE変換。移動、拡大、縮小、回転、反転ができる。

  • PIL.Image.PERSPECTIVE
    遠近感のある画像に変換。

  • PIL.Image.QUAD
    ランベルトの四角形っていうやつの変形と思われる。 端がよれて"くる"ってなってる紙とかの写真を四角形に補正するために使われるのだと思う。

  • PIL.Image.MESH
    QUADを連続して行うためのもの。

変形のパラメータ (data)

dataで変形のパラメータを指定する。

methodの変形方法に合わせて指定する必要がある。

ここがpillowのリファレンスに記載がなく困った。

ネットで検索したところ以下がヒット。これを参考にした。

The Image Module

描画時の補間の方法。filter。 (resample)

変形するときに描画する点を埋め合わせないといけないケースがあるが、 その方法を指定する。
以下の3つがある。

  • PIL.Image.NEAREST
    デフォルト。となりの点を見て補間。2値画像や"P"モードの場合、これしか指定できない。 "P"モードとはパレットを使うモードらしいが、よくわからず。

  • PIL.Image.BILINEAR
    2x2で見て補間。

  • PIL.Image.BICUBIC
    4x4で見て補間。

Image.EXTENT の変形

Image.EXTENTのdata指定方法。

4 tupples (x0, y0, x1, y1)

Image.EXTENTのサンプル

# -*- 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.EXTENT
# 
# data : 4 tupples (x0, y0, x1, y1)
# 
# dataで矩形を指定して切り取る。
# 
subnm = "nearest"
data = (0, 5, 20, 20)
im2 = im.transform(im.size, Image.EXTENT, data, Image.NEAREST)

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

subnm = "bilinear"
data = (0, 5, 20, 20)
im2 = im.transform(im.size, Image.EXTENT, data, Image.BILINEAR)

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

subnm = "bicubic"
data = (0, 5, 20, 20)
im2 = im.transform(im.size, Image.EXTENT, data, Image.BICUBIC)

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

変換元の画像

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

変換後の画像

  • resample=Image.NEAREST
    f:id:umejan:20160424202632p:plain

  • resample=Image.BILINEAR
    f:id:umejan:20160424202654p:plain

  • resample=Image.BICUBIC
    f:id:umejan:20160424202621p:plain

コメント

EXTENTはそのままなので簡単。

関連

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

PILのImage.transformの使い方 (QUAD, MESH) - umejanのブログ

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