PythonのPillowで画像に枠線を付ける
- 作成日: 2020-09-24
- 更新日: 2024-01-02
- カテゴリ: Python
Pillowで枠線を付ける
Pythonの画像処理ライブラリであるPillow
を使って画像に枠線をつけてみます。
Pillow
には絵を描くためのモジュールImageDraw
があってこれを使うと枠線など自由に描くことが可能です。
環境にpip
などでPillow
をインストールしておきます。
$ pip install Pillow
使用する画像
今回はこの画像を使用します。
実際の実装
実装は↓のようになります。
from PIL import Image, ImageDraw
fname = 'img/sample.jpg' # 画像のファイル名
line_width = 4 # line width(枠線一本の幅)
waku_color = (0, 128, 255) # 枠線の色(RGB)
# 元になる画像からImageオブジェクトを作成
src_im = Image.open(fname)
sw, sh = src_im.size # 元の画像のサイズを取得
# キャンバスを作成
# この画像に枠線と元の画像を合成する
cw, ch = sw + line_width * 2, sh + line_width * 2 # キャンバスのサイズを元の画像から生成
canvas_im = Image.new('RGB', (cw, ch))
# キャンバスのImageDrawオブジェクトを作成
canvas = ImageDraw.Draw(canvas_im)
# キャンバスを単色で塗りつぶす
canvas.rectangle([(0, 0), (cw, ch)], fill=waku_color)
# キャンバスの画像に元の画像を貼り付け
canvas_im.paste(src_im, (line_width, line_width))
# 保存
canvas_im.save('out.jpg')
まず1行目ですが、
from PIL import Image, ImageDraw
ここではPillow
のImage
モジュールとImageDraw
モジュールをインポートしています。
Image
モジュールは画像を開いたり生成したり合成したりするのに使います。
ImageDraw
モジュールは画像に枠線などの絵を描くのに使います。
fname = 'img/sample.jpg' # 画像のファイル名
line_width = 4 # line width(枠線一本の幅)
waku_color = (0, 128, 255) # 枠線の色(RGB)
使用する変数を定義しています。
# 元になる画像からImageオブジェクトを作成
src_im = Image.open(fname)
sw, sh = src_im.size # 元の画像のサイズを取得
fname
のファイルを開きます。
これはImage
モジュールのopen
関数を使います。
open
関数は画像を開くのに成功するとその画像の拡張子に対応したオブジェクトを返します。
上の場合、fname
はjpg
画像なので返ってくるオブジェクトは<class 'PIL.JpegImagePlugin.JpegImageFile'>
になります。
# キャンバスを作成
# この画像に枠線と元の画像を合成する
cw, ch = sw + line_width * 2, sh + line_width * 2 # キャンバスのサイズを元の画像から生成
canvas_im = Image.new('RGB', (cw, ch))
先ほど開いた画像の横幅と高さから、キャンバスの画像を生成します。
今回の枠線の描き方は、まず元の画像より枠線分大きい画像(キャンバス)を生成します。
そしてその大きい画像を単色で塗りつぶし、その上から元の画像を貼り付けて合成するようにします。
こうすれば元の画像の画素を上書きすることなく画像に枠線をはめることができます。
# キャンバスのImageDrawオブジェクトを作成
canvas = ImageDraw.Draw(canvas_im)
キャンバスの画像からImageDraw
オブジェクトを生成します。
ImageDraw
オブジェクトは引数の画像に線や矩形などを自由に描けるオブジェクトです。
今回は矩形で単色で塗りつぶすのに使います。
# キャンバスを単色で塗りつぶす
canvas.rectangle([(0, 0), (cw, ch)], fill=waku_color)
ImageDraw
オブジェクトであるキャンバスのメソッドrectangle
を使って矩形を描画します。
第1引数の[(0, 0), (cw, ch)]
には矩形の左上の座標と、右下の座標を指定します。
fill
に色を表す文字列を指定するとその色で矩形が塗りつぶされます(red
, blue
など)。
またはfill=(0, 128, 255)
のようにRGB
値を指定することも可能です。
# キャンバスの画像に元の画像を貼り付け
canvas_im.paste(src_im, (line_width, line_width))
キャンバスを通じてキャンバスの画像に色が塗られたので、キャンバスの画像に元の画像を貼り付けます。
(line_width, line_width)
で貼り付ける位置を左上から枠線の幅分ずらしています。
キャンバスの画像は枠線の幅 * 2
分の大きさが横幅と高さに確保されているので、こうすることで枠線が上下左右にはみ出ることになります。
# 保存
canvas_im.save('out.jpg')
生成したキャンバスの画像を保存します。
保存した画像は↓のようになります。
周りに青い枠線が描かれてますね。
元の画像ファイル名を使いたい場合
元の画像ファイル名を維持し、たとえば_waku
などをファイル名に付加して画像を保存したい場合があります。
そういう時は↓のようにos.path.splitext
を使います。
from PIL import Image, ImageDraw
import os
fname = 'img/sample.jpg' # 画像のファイル名
line_width = 4 # line width(枠線一本の幅)
waku_color = (0, 128, 255) # 枠線の色(RGB)
# 元になる画像からImageオブジェクトを作成
src_im = Image.open(fname)
sw, sh = src_im.size # 元の画像のサイズを取得
# キャンバスを作成
# この画像に枠線と元の画像を合成する
cw, ch = sw + line_width * 2, sh + line_width * 2 # キャンバスのサイズを元の画像から生成
canvas_im = Image.new('RGB', (cw, ch))
# キャンバスのImageDrawオブジェクトを作成
canvas = ImageDraw.Draw(canvas_im)
# キャンバスを単色で塗りつぶす
canvas.rectangle([(0, 0), (cw, ch)], fill=waku_color)
# キャンバスの画像に元の画像を貼り付け
canvas_im.paste(src_im, (line_width, line_width))
# 保存
leftside, ext = os.path.splitext(fname) # ファイル名部分と拡張子を分離
dst_fname = leftside + '_waku' + ext # ファイル名を再合成
canvas_im.save(dst_fname)
スクリプトにしたい場合
元の画像ファイル名と出力先ファイル名をコマンドラインから指定できるようにするには↓のようにsys.argv
を使います。
from PIL import Image, ImageDraw
import sys
if len(sys.argv) < 3:
print('usage: waku.py [src-fname] [dst-fname]')
sys.exit(0)
fname = sys.argv[1]
dst_fname = sys.argv[2]
line_width = 4 # line width(枠線一本の幅)
waku_color = (0, 128, 255) # 枠線の色(RGB)
# 元になる画像からImageオブジェクトを作成
src_im = Image.open(fname)
sw, sh = src_im.size # 元の画像のサイズを取得
# キャンバスを作成
# この画像に枠線と元の画像を合成する
cw, ch = sw + line_width * 2, sh + line_width * 2 # キャンバスのサイズを元の画像から生成
canvas_im = Image.new('RGB', (cw, ch))
# キャンバスのImageDrawオブジェクトを作成
canvas = ImageDraw.Draw(canvas_im)
# キャンバスを単色で塗りつぶす
canvas.rectangle([(0, 0), (cw, ch)], fill=waku_color)
# キャンバスの画像に元の画像を貼り付け
canvas_im.paste(src_im, (line_width, line_width))
# 保存
canvas_im.save(dst_fname)
実行例。
$ python waku.py img/sample.jpg out.jpg
問題
Q1: ImageDraw
モジュールの第1引数として適当なものを答えよ
- Imageオブジェクト(に類するもの)
- sys.argv
- os.path.splitext
Q2: 画像に画像を貼り付けたい場合に適当な操作を答えよ
- Imageオブジェクトのopenを使う
- Imageオブジェクトのpasteを使う
- Imageオブジェクトのnewを使う
Q3: 画像を単色で塗りつぶしたい場合に適当な操作を答えよ
- Imageオブジェクトのrectangleメソッドを使う
- ImageDrawオブジェクトのrectangleメソッドを使う
- ImageDrawオブジェクトのlineメソッドを使う
正解はこちら↓
Q1: 1
Q2: 2
Q3: 2