[Python] Pillowによる画像処理(ImageDrawオブジェクトで図形描画)

Python モジュール 画像処理

Pillowはサードパーティ製の画像処理モジュールです。このモジュールに含まれるImageDrawオブジェクトを使うと、画像に図形やテキストを描画することができます。本記事ではこのImageDrawオブジェクトの使い方についてまとめます。

確認した環境

    • OS: Ubuntu16.04LTS
    • Python 3.7.0
    • Pillow 5.3.0

公式リファレンス:https://pillow.readthedocs.io/en/5.3.x/index.html

インストール

Pillowは3rdパーティ製のモジュールです。自分の環境に無いときはインストールしましょう。公式リファレンスに記載の通りpipコマンドでできます。

$ pip install Pillow

Anaconda環境の場合は以下でインストール可能です。

$ conda install pillow

ImageDrawモジュールを使って図形を描画する

ベース画像の準備

まずはベースとなる画像を準備します。

既存のファイルを呼び出す場合は、以下のようにopen()メソッドを使います。

>>> from PIL import Image
>>> img = Image.open('sample.jpg')

または、新規に(例えば300x300pxのグレー地の画像)作成するには、Image.new()関数を使って以下のようにします。

>>> img = Image.new('RGBA', (300, 300), 'gray')

以降、このグレー地の画像に点や線などの図形を描画していきます。

詳細はこちらの記事でもまとめていますので、ご参照ください。
→ [Python] Pillowによる画像処理(Imageオブジェクト)

画像に図形を描画する

ImageオブジェクトをDraw()メソッドに渡すとImageDrawオブジェクトが生成されます。

# ImageDrawモジュールのインポート
>>> from PIL import ImageDraw

#ImageDrawオブジェクトの生成
>>> d = ImageDraw.Draw(img)

ImageDrawオブジェクトは線や矩形、円(楕円)、テキスト等を描画する為のいろいろなメソッドをサポートしており、Imageオブジェクトに対しインプレースで描画処理が実行されます。
詳しくは以降で説明します。

点の描画

point()メソッドを使います。

  • 点の座標を第一引数に設定します。複数ある場合はタプルで表した座標(x, y)を[ ]でくくってリストにします。
  • 色はキーワード引数fillで設定。

以下は、赤い点を(50, 50), (150, 150)に描画した例です。

# (50, 50)、(150, 150)の2点を描画
>>> d.point([(50, 50), (150, 150)], fill='red')
>>> img.show()

よくみないとわかりませんが、赤い点が2つあります。

線の描画

line()メソッドを用います。

  • 直線の始点と終点座標をタプル(x, y)で表し、それらを[ ]でくくってリストにしたものを第一引数に渡します。
  • 線幅はキーワード引数width、線の色はfillで設定。

以下は、(0, 50), (200, 50), (0, 150), (200, 150)を通る線の組み合わせを描画するコードです。

>>> d.line([(0, 50), (200, 50), (0, 150), (200, 150)], fill='red', width=2) 
>>> img.show()

矩形(くけい)の描画

rectangle()メソッドを用います。

  • 矩形の左上と右下の座標をタプル(x, y)で表し、[ ]でくくったリストを第一引数に渡します。
  • 線色はキーワード引数outline、線幅はwidth、塗りつぶし色はfillで設定。

以下は、枠線が幅:3pxで緑色、塗りつぶしが黄色の100×100サイズの矩形を描画した例です。

>>> d.rectangle([(50, 50), (150, 150)], fill='yellow', outline='green',  width=3)
>>> img.show()

円(楕円)の描画

ellipse()メソッドを使います。

  • 第一引数は、円(または楕円)の位置とサイズを表す座標を設定。
    この座標は前節と同じように左上、右下座標を指定する矩形タプルです。
  • 正方形になるよう座標設定をすれば円、長方形なら楕円になります。
  • 線幅、線の色、塗りつぶしの色も矩形の場合と同じ

以下は、線色がライム、幅が4px、塗りつぶしが青色の円を描画したものです。

>>> d.ellipse([(70, 70), (120, 120)], fill='blue', outline='lime', width=4)
>>> img.show()

多角形の描画

polygon()メソッドを用います。

  • 線の描画と同様に、直線の始点と終点座標をタプル(x, y)で表し、[ ]でくくってリストにしたものを第一引数に渡します。
  • 線の描画と異なるのは、最初と最後の座標が線で結ばれることです。
  • 線幅、線の色、塗りつぶしの色設定は矩形の場合と同じです。

以下に例を示します。

>>> d.polygon([(25, 25), (100, 35), (175, 25), (175, 40), (25, 40)], fill='purple', outline='pink')
>>> img.show()

テキストの描画

text()メソッドを使います。

    • 第一引数にはテキストを配置する座標(x, y)を設定。
    • 第二引数には描画するテキストを”文字列”で設定。
    • 文字色はキーワード引数fillで設定。
    • 文字列に改行文字(\n)が入っている場合は、行間(px数)をspacing、位置をalign(”right”, “left”, “center”)で設定。

※この他にもフォント設定などの細かいパラメータはありますが、ここでは割愛します。

以下に例を示します。

>>> d.text((25, 160), 'Test Message\nExample', fill='red', spacing=10, align='right')
>>> img.show()

ここでテキストの位置を決める際に便利なのが、テキストのサイズを出力してくれるtextsize()メソッドです。

  • 第一引数に表示するテキストを設定。
  • 改行文字(\n)がある場合は、行間をキーワード引数spacingにpx数で設定。
>>> d.textsize('Test Message\nExample', spacing=10)
(72, 32)

この場合、x方向は72px、y方向は32pxのテキストボックスであることがわかります。
この情報があれば、どこに配置するかを計算することが出来ますね。

もう少し具体的な例

最後に、これまで説明してきた一連の流れを具体的な例で示します。

# 画像をオープン
>>> img = Image.open('coffee.jpg')
# ImageDrawオブジェクトを生成
>>> d = ImageDraw.Draw(img)
# 矩形を描画
>>> d.rectangle([(35, 50), (140, 130)], outline='lime', width=2)
# テキストを描画
>>> d.text((150, 40), 'Coffee\nand\nSnacks', fill='yellow', align='center')
# 楕円を描画
>>> d.ellipse([(140, 120), (265, 170)], outline='red', width=2)
# ファイルへ保存
>>> img.save('coffe_marked.png')
# 画面表示
>>> img.show()

元画像

描画後

今回の内容は、こちらの記事で使った顔検出結果を画像に描画する際にも使っています。
Face++の顔検出Web APIを試してみた
コードはこちらにアップしています。

まとめ

Pillowモジュールを使って画像に図形やテキストを描画する方法についてまとめました。

Learn more...

書籍でもう少し詳しく学びたい場合はこちらもどうぞ。筆者もかなり参考にさせてもらっています!

シェアする
ひびきをフォローする
Hbk project