コードDE描画

プログラミングで図を描く練習

【pythonista3】Pillowモジュールで画像を編集する(画像の貼り付け)メソッドの使用例9選

pythonスクリプトでjpgやpmgなどの画像を加工、作成することが出来る。

簡単な画像処理にPillowモジュールが使われる。このモジュールは、読み込んだ画像をもとに新たな画像の作成、保存が出来る。

iOSアプリのpythonista3には標準でこのモジュールがあるがver1.1.7と古い。(2020年3月アップデート版現在。)

pythonista3内でPillowモジュールが出来ることを紹介する。

以下では、次の5つの操作を説明する。

  • 図形を貼り付け
  • 文字を貼り付け
  • 画像を貼り付け
  • 画像の混合
  • 画像を並べる

使用環境

使っているアプリの都合上、Pillowモジュールが古い。そのため関数の引数など現在の仕様が若干異なる場合がある。

Pythonista3では最初からPillowモジュールが入っているためインストールは必要がない。

使い方

お借りした画像のリソース

以下では次の2つの画像を使う。

sample.jpg
sample.jpg

上の画像をsample.jpgとする。

smp.jpg
smp.jpg

この画像をsmp.jpgとする。

以下のマスク画像を使う。

mask2.png
mask2.png

この画像をmask2.pngとする。

図形を貼り付け

例1

画像に図形を貼り付ける。

  • 実行結果

図形を貼り付けた画像
図形を貼り付けた画像

from PIL import Image,ImageDraw

# 画像オブジェクト生成
img=Image.open('sample.jpg')
base=Image.new('RGB',img.size,(128,128,128))

# 描画オブジェクト生成
draw=ImageDraw.ImageDraw(base)

# 貼り付け
base.paste(img)

x,y,r=10,10,50
w=int(img.width)
# 図形を貼り付け
draw.rectangle((x,y,x+r,y+r),fill=(0,0,255),outline=(0,255,255))
draw.ellipse((w-x-r,y,w-x,y+r),fill=(255,0,0),outline=(255,255,0))

# 画像を保存
base.save('pillow-paste-1.png')
  • 解説

図形の貼り付けはImageDrawオブジェクトのrectangle,ellipseメソッドを使う。

メソッドの引数は次のようになる。fill引数は塗り潰し、outline引数は枠線の色を指定する。

描画オブジェクト.rectangle((左端のx座標,上端のy座標,右端のx座標,下端のy座標),fill=(R成分,G成分,B成分),outline=(R成分,G成分,B成分))

ellipseメソッドも同様の引数をとる。

手順は以下のようになる。

  1. 画像を読み込む
  2. 画像オブジェクト(img)に描画オブジェクト(draw)を作る
  3. 描画オブジェクトに図形を貼り付ける
  4. 画像オブジェクトを保存する

保存するのはdrawではなくimgであることに注意する。

画像を貼り付け

例2

画像に別の画像を張り付ける。

  • 実行結果

画像を貼り付けた画像
画像を貼り付けた画像

from PIL import Image

# 画像オブジェクト生成
base=Image.open('sample.jpg')
img=Image.open('smp.jpg')

# リサイズ
paste=img.resize((img.width//5,img.height//5))

# 貼り付け
base.paste(paste,(10,10))

# 画像を保存
base.save('pillow-paste-2.png')
  • 解説

Imageオブジェクトのpasteメソッドを使う。 引数で張り付ける座標を指定出来る。

output = Imageオブジェクト.paste(張り付ける画像オブジェクト,(x座標,y座標))
例3

貼り付けた那像のはみ出した部分は切り捨てられる。

  • 実行結果

はみ出した画像
はみ出した画像

from PIL import Image

# 画像オブジェクト生成
base=Image.open('sample.jpg')
img=Image.open('smp.jpg')

# リサイズ
paste=img.resize((img.width//3,img.height//3))

# 貼り付け
base.paste(paste,(-30,20))

# 画像を保存
base.save('pillow-paste-3.png')
例4

マスク画像を使う。

  • 実行結果

マスク画像を使った画像
マスク画像を使った画像

from PIL import Image,ImageOps

# 画像オブジェクト生成
base=Image.open('sample.jpg')
img=Image.open('smp.jpg')

# リサイズ
paste=img.resize((img.width//5,img.height//5))

mask=Image.open('mask2.png')
mask=ImageOps.invert(mask.resize(paste.size).convert('L'))

# 貼り付け
base.paste(paste,(10,10),mask)

# 画像を保存
base.save('pillow-paste-4.png')
  • 解説

マスク画像を使って画像を張り付けることも出来る。

マスク画像のサイズは元の画像と合わせる。

output = Imageオブジェクト.paste(張り付ける画像オブジェクト,(x座標,y座標),mask=マスク画像)

画像を混ぜる

例5

2つの画像を割合を指定して混ぜ合わせる。

合成前に画像のサイズを合わせておく。

  • 実行結果

ピクセルを混ぜた画像
ピクセルを混ぜた画像

from PIL import Image

# 画像読み込み
img1=Image.open('sample.jpg')
img2=Image.open('smp.jpg')
# サイズを合わせる
img3=img2.resize(img1.size)

# 混ぜる
out=Image.blend(img1,img3,0.4)

# 画像を保存
out.save('pillow-mix-1.png')
  • 解説

Imageオブジェクトのblendメソッドを使う。 引数を次のように指定する。

out=Image.blend(image1,image2,mask)

mask=0の場合はimage2になり、mask=1の場合はimage1になる。それ以外の値ではmaskの数値に応じた割合で合成する。

例6

2つの画像をマスク画像を利用して混ぜ合わせる。

合成前に画像のサイズを合わせておく。

  • 実行結果

マスク画像で合成した画像
マスク画像で合成した画像

from PIL import Image

# 画像読み込み
img1=Image.open('sample.jpg')
img2=Image.open('smp.jpg')
# サイズを合わせる
img3=img2.resize(img1.size)

maskimg=Image.open('mask2.png')
# サイズを合わせる
mask=maskimg.resize(img1.size)
# マスクを使って合成
out=Image.composite(img1,img3,mask)

# 画像を保存
out.save('pillow-mix-2.png')
  • 解説

Imageオブジェクトのcompositeメソッドを使う。 引数を次のように指定する。

out=Image.composite(image1,image2,mask)

マスク画像はグレースケールの画像を使う。マスク画像のピクセルが黒の場合はimage2になり、白の場合はimage1になる。それ以外の値ではグレーの度合いに応じた割合で合成する。

画像を並べる

例7

画像を縦に並べる。

  • 実行結果

縦に並べた画像
縦に並べた画像

from PIL import Image

# 画像を読み込む
img1=Image.open("sample.jpg")
img2=Image.open("smp.jpg")

# サイズを決める
w=img2.width*img1.height/img2.height
h=img1.height

# ベースの画像を用意
img=Image.new("RGB",(img1.width,img1.height+h),(0,0,0))

# 貼り付け
img.paste(img1,(0,0))
img.paste(img2,(0,img1.height))

# 保存
img.save('pillow-paste-5.png')
  • 解説

手順は以下のようになる。

  1. 2つの画像を読み込む
  2. 画像のサイズを調整する
  3. 2つの画像がぴったり収まる画像オブジェクトを生成する
  4. 1つ目の画像を生成した画像に張り付ける
    • 左上(座標=(0,0))に張り付ける
  5. 2つ目の画像を生成した画像に張り付ける
    • 1つ目の画像の下(座標=(0,1つ目の画像の高さ))に張り付ける
  6. 生成した画像を保存する
例8

画像を横に並べる。

  • 実行結果

横に並べた画像
横に並べた画像

from PIL import Image

# 画像を読み込む
img1=Image.open("sample.jpg")
img2=Image.open("smp.jpg")

# サイズを決める
w=img1.width
h=img2.height*img1.width/img2.width

# ベースの画像を用意
img=Image.new("RGB",(img1.width+w,img1.height),(0,0,0))

# 貼り付け
img.paste(img1,(0,0))
img.paste(img2,(img1.width,0))

# 保存
img.save('pillow-paste-6.png')
  • 解説

手順は以下のようになる。

  1. 2つの画像を読み込む
  2. 画像のサイズを調整する
  3. 2つの画像がぴったり収まる画像オブジェクトを生成する
  4. 1つ目の画像を生成した画像に張り付ける
    • 左上(座標=(0,0))に張り付ける
  5. 2つ目の画像を生成した画像に張り付ける
    • 1つ目の画像の右(座標=(1つ目の画像の幅,0))に張り付ける
  6. 生成した画像を保存する

文字を貼り付け

例9

画像に文字を貼り付ける。

  • 実行結果

文字を貼り付けた画像
文字を貼り付けた画像

from PIL import Image,ImageDraw,ImageFont

# 画像オブジェクト生成
img=Image.open('smp.jpg')
base=Image.new('RGB',(img.size),(128,128,128))
# 描画オブジェクト生成
draw=ImageDraw.ImageDraw(img)
# 貼り付け
base.paste(img)
# フォントオブジェクト生成
font=ImageFont.truetype("ipag.ttf",20)

# 文字を貼り付け
draw.multiline_text((10,50),'レオナルド\n\nヴィンチ',fill=(0,0,255),font=font,spacing=30)

# 画像を保存
img.save('pillow-paste-7.png')
  • 解説

文字の貼り付けはImageDrawオブジェクトのmultiline_textメソッドを使う。

メソッドの引数は次のようになる。

描画オブジェクト.multiline_text((x座標,y座標),文字列,fill=(R成分,G成分,B成分),font=フォントオブジェクト,align=文字の構え,spacing=改行幅)
  • 座標:文字の左上の座標を指定する
    • (中央ではない)
  • 文字列:改行も含めることが出来る
  • fill引数は文字の色を指定する
  • align引数は文字の構えを指定する
    • align='center':中央構え
    • align='left':左構え
    • align='right':右構え
  • spacing引数は改行の幅をピクセル単位で指定する

フォントオブジェクトはフォントと文字のサイズを指定する。 文字のサイズはフォントオブジェクトで指定することに注意する。 日本語を表示させるには日本語のフォントを使う。

変数=ImageFont.truetype(フォント名,文字サイズ)

手順は以下のようになる。

  1. 画像を読み込む
  2. 画像オブジェクト(img)に描画オブジェクト(draw)を作る
  3. フォントオブジェクトを生成する
  4. 描画オブジェクトに文字を貼り付ける
  5. 画像オブジェクトを保存する

まとめ

Imageオブジェクト、imageDrawオブジェクトのメソッドを使って次のような画像の合成が出来る。

  • Imageオブジェクト
    • pasteメソッド
      • 座標を指定する
      • マスク画像を指定する
    • blendメソッド
      • 全体を混ぜる
    • compositeメソッド
    • マスク画像を使って混ぜる
  • ImageDrawオブジェクト
    • 図形を貼り付ける
    • 文字を貼り付ける

参考リンク

フォントダウンロード先