[Python]Pillowで画像のサイズを変更する

Python

よく画像を決まったサイズに加工することが多いのですが、毎回毎回同じ工程――画像を縮小し、トリミング――をするのが面倒で、なんとかPythonを使って自動化できないかと思ってこのページにまとめました。

画像の加工には「OpenCV」もありますが、Pillowを選んだのは、リサイズとトリミングの処理だけならこちらの方が簡単そうだったからです。

このページでは、Pillowのインストール、画像の読み込み、確認、表示、保存、リサイズとトリミングをやっていきます。

参考サイト
Pillow(PIL Fork) documentation
Pythonの画像処理ライブラリPillow(PIL)の使い方

私の環境
Windows10
Git Bash
Python 3.8.2
Pillow 8.4.0

スポンサーリンク
スポンサーリンク

Pillowのインストール

インストールにはpipを使います。
以下のコマンドでインストールします。

pip install Pillow

Pillowは開発が終了したPILの後継ですが、共存はできないため、PILがすでに入っている場合、削除してからPillowをインストールしてください。

画像の読み込み

加工の前に画像を読み込まなくてはいけません。

まずImageモジュールをインポートします。

from PIL import Image

変数 = Image.open('画像のパス')

パッケージ「PIL」からImageモジュールを使うよ、Imageモジュールのopen関数を使って画像を呼び出し、変数に入れるよ、という意味です。パッケージ名が「Pillow」ではないんですね。

変数にはImageクラスのオブジェクトが入ります。

使用できる画像の形式は以下を参照してください。

サポートされているフォーマット[pillow.readthedocs.io]

実際にやってみます。

コンソール画面

$ python
Python 3.8.2
Type "help", "copyright", "credits" or "license" for more information.
>>> from PIL import Image 
>>> img = Image.open('sample.png')
>>> type(img) 
<class 'PIL.PngImagePlugin.PngImageFile'>

画像は作業ディレクトリに入れているため、ファイル名だけでパスが通っています。
別の場所にある場合、絶対パスや相対パスで適切に記述してください。

画像の確認

属性(サイズ・フォーマット)の確認

読み込んだ画像が持つ属性を調べてみましょう。

ちなみに読み込んだ画像が↓です。

'sample'
sample.png

imgはImageクラスのインスタンス(実体)です。

img.sizeで(横幅, 縦幅)のタプルを、

img.widthで横幅、

img.heightで縦幅、

img.formatで画像の形式を、

img.modeで色の形式を、参照できます。

>>> img.size
(300, 200)
>>> img.width
300
>>> img.height
200
>>> img.format
'PNG'
>>> img.mode
'RGBA'

※横と縦の幅はピクセル単位です。

画像の表示

画像をちょっと表示したいときには、showメソッドを使います。

>>> img.show()
新しくウインドウが現れ画像が表示される。

画像はデフォルトではPNGとして一時ファイルで保存され、それぞれの環境で設定されているビューワーから表示されます。

GUI環境でないLinuxなどの場合、画像表示するソフトが入っていないと、このメソッドは機能しません。

画像の保存

画像の加工より先に保存方法を説明します。

saveメソッドを使って保存します。

img.save('ファイルパス')

ファイルのパスには拡張子を含めて書くことで、Pillowが自動で判断してくれます。

もし形式がJPEGなら、属性にqualityを設定できます。
保存する画像の品質設定で、省略した場合のデフォルト値は75です。

quality――0(最低)から95(最高)までの幅での画質。デフォルト値は75。95を超える値は避ける必要があります。100にすると、JPEG圧縮アルゴリズムの一部が無効になり、画質がほとんど向上しないままファイルサイズが大きくなります。

JPEG-quality[pillow.readthedocs.io]
>>> img.save('sample.jpeg', quality=85)
OSError: cannot write mode RGBA as JPEG

おや、エラーが出てしまいました。
RGBAをJPEGに変換できない、とあります。

PNGでRGBAの透過情報があるとJPEGとして保存できないようなので、RGBに変換します。
convertメソッドを使います。

>>> img2 = img.convert('RGB') 
>>> img2.save('sample.jpeg', quality=85) 

上記を実行すると現在のディレクトリに「sample.jpeg」として保存されます。

リサイズ

リサイズにはメソッドのresizeを使います。

resize((横幅, 縦幅))

メソッドの()の中にタプルで渡すので、カッコが2重になります。

変更したい横幅、縦幅をピクセル単位のint型で指定します。

実際にやってみましょう。
こちらの素敵な画像を使用します。

女性が岩の上に座っている。湖の向こうには高い山がある。

※この上に貼っているものは縮小しています。
読み込んだ画像のオリジナルは「横640px、縦800px」のJPEGです。

$ python
Python 3.8.2
Type "help", "copyright", "credits" or "license" for more information.
>>> from PIL import Image
>>> img = Image.open('nadi-whatisdelirium.jpg')
>>> re_img1 = img.resize((300, 300)) 
>>> re_img1.save('resize1.jpeg', quality=85) 

リサイズ後の実際の画像

縦に圧縮されてしまった。
resize1.jpeg

アスペクト比を気にしないで縮小したため、女性のスタイルが変化して見えるようになってしまいました。

縦横の比率を保ったまま画像のサイズを変更したいと思います。

その画像がもつ属性を利用します。コードは上の続きです。

>>> size = (img.width // 2, img.height // 2)
>>> re_img2 = img.resize(size)
>>> re_img2.save('resize2.jpeg', quality=85) 
元の画像の50%に縮小。
resize2.jpeg

元の画像の横と縦、ともに2で割り、横320px、縦400pxに縮小しました。
コード中のサイズを求める計算式で「//」を使っているのは、そのまま割ってしまうとfloat型になってしまうからです。

今度は変な具合に圧縮されていませんね。

トリミング

トリミングに該当するメソッドはcropです。

crop((左, 上, 右, 下))

resizeと同じように、こちらのメソッドも()の中にタプルで渡すので、カッコが2重になります。

例えば「500×300」のサイズの画像があるとして、画像の左上の位置は(0px, 0px)です。右下は(500px, 300px)になります。

cropでは切り取りたい範囲を指定します。
左上の座標(l_x, l_y)と右下の座標(r_x, r_y)をひとつのタプルのなかでまとめて指定します。
(l_x, l_y, r_x, r_y)

「500×300」の画像から切り取る範囲に(50, 50, 450, 250)を指定すると、以下のイメージのようになります。

切り取られる範囲が点線で囲われている。

点線が切り取られる箇所です。

実際に画像を使ってやってみましょう。
リサイズのときに使った「resize2.jpeg」をもう一度使用します。

元の画像の50%に縮小。
resize2.jpeg(320px, 400px)

「300×300」の正方形に切り取りたいと思います。

>>> from PIL import Image
>>> img = Image.open('resize2.jpeg') 
>>> center = (img.width // 2, img.height // 2) 
>>> center
(160, 200)
>>> left = center[0] - 150           
>>> upper = center[1] - 150
>>> right = center[0] + 150
>>> lower = center[1] + 150
>>> size = (left, upper, right, lower) 
>>> size
(10, 50, 310, 350)
>>> img.crop(size).save('cropped.jpeg', quality=85) 

画像の中心から正方形に切り取りたいのでcenterを出しました。
centerからそれぞれ150px分引いたものと、足したものをタプルに収め、メソッドを使っています。

実際の画像

300px×300pxに切り取られた画像。
cropped.jpeg

中心から切り取ったため、女性がきれいに収まっています。

まとめ

Pillowを使って画像を加工してみました。
あとはモジュールにまとめると、決まった処理はいつでもできるようになります。

今回やったことをまとめると、

インストールは「pip install Pillow」

呼び出し方は
from PIL import Imge
変数 = Image.open('ファイルのパス')

size, width, height, format, modeなどの属性がある。

リサイズするメソッド「resize((横幅, 縦幅))」

トリミングするメソッド「crop((左, 上, 右, 下))」

保存するメソッド「save('ファイルのパス')」

このページが少しでもお役に立てたのなら幸いです。

タイトルとURLをコピーしました