複数の画像を一括でリサイズしたい場合にどうやって行っていますか?

Photoshopやペイントといった画像編集ツール、ブラウザ経由でリサイズするオンラインサイトまたはインストール型の無料ソフトウェアなど人によってさまざまだと思います。扱う画像が少なければPhotoshopなどのツールでもいいかもしれませんが、数が増えると効率が急激に下がります。またオンラインサイトや無料ツールはセキュリティ的に問題がないのかという不安がいつも付きまといます。

そんな時にPythonを使っている人または使ってみたい人におすすめなのがPythonの画像処理ライブラリPillowを使ったリサイズです。

大量の画像を一括リサイズも簡単に行うことができるので、Pythonを使って仕事の効率化を考えている人はぜひチャレンジしてみてください。

本文書の処理はWindows10環境を使って行っています。

Pillowとは

PillowはPython Image Library(PIL:Python画像ライブラリ)から派生したライブラリで、画像のサイズ変更やトリミング、輝度やコントラストの変更など画像に関するさまざま処理を行うことができます。PILを元に作られているライブラリなので、Pillowモジュールを利用する場合はPILという名前を使用します。

Pillowのインストール

環境によってはインストール済みの場合もあるのでpip listコマンドで確認を行います。


>pip list
Package    Version
---------- -------
・・・
Pillow     5.3.0
・・・

上記のように表示される場合はインストール済みなのでインストールは必要ありませんが、最新版でない場合はアップデートを行います。

インストールされていない場合は、pipコマンドを利用してPillowのインストールを行います。


>pip install Pillow

アップデートをする場合は下記のコマンドを実行します。


>pip install -U Pillow

インストールまたはアップデート後は、インストールが完了しているか確認するためにpip listコマンドを再度実行しましょう。

本環境では、バージョンである6.1.0であることがわかります。


>pip list
Package    Version
---------- -------
・・・
Pillow     6.1.0
・・・

画像の処理

画像ファイルを開く

Pillowを使って画像ファイルを読み込んで、読み込んだ画像をWindowsのアプリで表示させます。

pythonプログラムを保存しているフォルダにpillow_github.pngというファイル名で画像を保存してそのファイルを利用します。

アプリで画像を開くコードは下記の通りです。


from PIL import Image

im = Image.open("pillow_github.png")

im.show()

PILモジュールからImageクラスを読み込んで、openメソッドで画像パスを指定して画像を開いています。ファイルを開いた後showメソッドを実行すると”フォト”アプリケーションが起動して、開いたファイルの画像が画面に表示されます。

Pillowのshowメソッドでフォトが開く
Pillowのshowメソッドでフォトが開く
指定したpillow_github.pngを直接開いているわけではなく一時的にBMPファイルが作成されそのファイルを開いています。ファイル名がtmp11axx13m.BMPとなっているのがわかります。

画像ファイルの情報を取得する

Pillowで開いた画像ファイルの属性情報はImageインスタンスが持つ属性filenameやsizeを使って確認することができます。


from PIL import Image

im = Image.open("pillow_github.png")

print(im.filename) #ファイル名
print(im.size) #サイズ
print(im.width) #幅
print(im.height) #高さ
print(im.mode) #モード
print(im.format) #フォーマット

実行すると各属性値を取得することができます。


pillow_github.png
(1128, 890)
1128
890
RGBA
PNG
画像のサイズの単位はピクセルです。上記では幅が1128ピクセルで高さが890ピクセルです。

画像をリサイズする

早速リサイズを行いたいと思います。サイズ1920, 1200の画像を320, 200に変更するプログラムです。わずか3行でリサイズを行うことができます。

変更を行いたいファイルはpythonプログラムが保存されているフォルダに保存しておく必要があります。サイズ変更後のファイルは同じフォルダに保存されます。


from PIL import Image

im = Image.open("img8.jpg")

im_resized = im.resize((320,200))

im_resized.save('img8-1.jpg')
作成される画像が粗い場合もあるので必ず画像を確認してください。粗い場合は下記の”リサイズした画像が粗い場合”を参考にリサイズのフィルターを変更してください。

横幅を指定して画像をリサイズする

リサイズしたい画像のサイズがいつもきまっている場合は、横、高さを固定した同じ設定でも問題ありません。通常は横、高さは画像によって異なる場合が大半です。そのような画像をリサイズする場合は、 縦横比を保ったままリサイズを行う 必要があります。

横幅を指定して縦横比を保ったままリサイズを行う方法を確認します。


from PIL import Image

im = Image.open("img8.jpg")

width = 700

ratio = width / im.width

height = int(im.height * ratio) #(5)

im_resized = im.resize((width, height))

im_resized.save('img8-1.jpg')

横幅に700を指定し、高さは縦横比を保つためにratioを求めます。そのratioを使って高さを出します。

元のサイズ1920, 1200 なので700, 437でリサイズされます。

width, heightの値は整数である必要があります。少数の含まれた値を設定するとエラーになります。そのため5行目ではintをつけて整数にしています。

リサイズした画像が粗い場合

リサイズを実行して画像が粗いと感じた場合はresizeメソッドを行う際のリサイズのフィルターを変更します。

フィルターは下記のものがあります。デフォルトは一番上のNEARESTの設定です。

  • NEAREST
  • BOX
  • BILINEAR
  • HAMMING
  • BICUBIC
  • LANCZOS

マニュアルには上記の設定に関する比較表は見つけられませんでしたが個別の説明はマニュアルの各所に記述されています。例えばHAMMINGはBILINEARと同じパフォーマンスである一方サイズの縮小の質はBICUBICと同じだがサイズを拡大する場合はあまり質が良くないと記述されています。どのフィルターが一番いいか検証も行っていなので、一番質が高いとされているLANCZOSを利用します。

見つけられなかっただけで各フィルターの処理速度や作成される画質についての比較がマニュアルのどこかに記述されているかもしれません。

変更方法は、resizeの際に下記のようにフィルターを設定します。


im_resized = im.resize((width, height), Image.LANCZOS)

実際にLANCZOSに変更して実行し、デフォルト設定のNEARESTに比較して画質が良くなっているか確認を行ってください。

複数の画像を一括処理

ここまでの説明でPillowを利用すると画像のリサイズが行えることがわかりました。ここからは画像のリサイズではなく複数の画像を一括で処理するための方法について説明を行っていきます。

複数の画像を扱う場合は、1つ1つの画像の名前をその都度入力していくことは非効率なのでできません。そのため、リサイズしたいファイルの名前を取得する機能が必要になります。

画像ファイルの名前を取得する

フォルダに保存されている画像ファイルの名前を自動で取得する方法が必要になります。

フォルダ下に保存されているファイル名を取得するためにglobモジュールを利用します。 拡張子がpngのファイルだけ取得しています。


import glob

for file_name in glob.glob('*.png'):
	
	print(file_name)

実行するとpythonプログラムファイルが保存されているフォルダ内にある.pngファイルのみ取得することができます。


>py test.py
pillow_github.png
show_image.png
square.png

リサイズしたファイルを保存する場所

リサイズしたファイルを保存する場所を作成します。pythonプログラムファイルが保存されているフォルダの下にresizedフォルダを作成します。

リサイズされたファイルがすべてのそのフォルダに保存されるようにプログラムを更新します。


from PIL import Image

import os,glob

for file_name in glob.glob('*.png'):

  im = Image.open(file_name)

  width = 700

  height = int(im.height * width / im.width)

  im_resized = im.resize((width, height), Image.LANCZOS)

  saved_path = os.path.join('resized',im.filename)

  im_resized.save(saved_path)

globモジュールを使って取得したファイル一覧からforを使って個別のファイル名を取得します。

ファイルを横幅700のサイズでリサイズして、resizedフォルダに保存されるといったシンプルなものです。

実行後、resizedフォルダを見ると同じ名前で横幅が700になったファイルを確認することができます。