リファクタリングをPythonで実践!基本手法とコード例・注意点まで
Pythonといえば、AIの分野で活躍するプログラミング言語。
AIの分野のなかでも、画像処理をすることも多いでしょう。
本記事では、Pythonで画像処理を行えるライブラリである「Pillow」について紹介します。
1. Pillowとは?
Pillowは、Python上で画像処理を行うためのライブラリです。
Pillowを使用することで、Pythonで読み込んだ画像を簡単に加工できます。
2. Pillowとほかの画像処理ライブラリとの違い
画像処理ライブラリとして、Pillowのほかに「PIL」や「OpenCV」といったライブラリを目にすることも多いはず。
ここでは、これらのライブラリとの違いを解説していきます。
①PILとPillowの違い
Python向けの画像処理ライブラリとしては、PillowのほかにPILが存在します。
しかしながら、PILの開発は現在ストップしており、2011年にリリースされてから新しいバージョンがリリースされていません。
Pillowは、そんなPILを代替する目的で作成されたライブラリです。
機能面においては大差がないようにも見えますが、2022年現在も新しいバージョンがリリースされています。
そのため、特に新しいバージョンのPythonの利用が前提となる場合、PILを選択する理由はないと言えるでしょう。
②OpenCVとPillowの違い
Python専用の画像処理ライブラリとして開発されたPillowとOpenCVは、そもそもの立ち位置が少し異なります。
Pillowと異なり、OpenCV自体は元々Pythonと関係ない独立したソフトウェアであり、OSへソフトウェアをインストールする必要があります。
そのうえで、PythonからOpenCVを使用するためにライブラリを介してOpenCVへアクセスするのです。
また、OpenCVは独立したソフトウェアとして動作するため、Python以外にも、C++やJavaといったプログラム言語からも使用できるのがメリット。
機能面においても、Pillowはリサイズやトリミングといった画像の変換処理に特化したライブラリなのに対し、OpenCVはAI分野にも活用される高機能な画像処理ソフトウェアという違いがあります。
そのため、「どちらかを使う」というよりも、「どちらも使う」ことが多くなるでしょう。
3. Pillowのインストール
それでは、実際にPillowをインストールして使用していきましょう。
①インストール前に注意すること
前述のとおり、PillowはPILを代替する目的として開発されたライブラリです。
そのため、PILとPillowが両方インストールされている場合には正常に動作しないので、注意しましょう。
②インストール方法
Pillowはpipコマンドを利用してインストールします。
pip install pillow
③インストールできないときに確認すること
Pillowのインストールに失敗する場合には、以下のことを確認しましょう。
・すでにPILがインストールされていないか
・Pillowに対応するPythonのバージョンがインストールされているか
対応バージョンやインストール方法については、公式サポートもあわせて確認してみてください。
4. Pillowの基本的な使い方
ここでは、Pillowを用いた画像の取り扱い方を紹介します。
①画像の読み込み
画像の読み込みには、「Image.open」を使用します。
この際、Imageをインポートすることを忘れないようにしましょう。
この例では、以下の「sample.jpg」を読み込んで使用します。
この画像は神奈川工科大学 情報学部 情報工学科等からダウンロードできます。
## Iillow
from PIL import Image, ImageFilter
## 画像の読み込み
img = Image.open("sample.jpg")
②画像の表示
画像を表示するには、Imageオブジェクトのshowメソッドを使用します。
img.show()
なお、JupyterLabやGoogle Colaboratoryを使用している場合には、以下のように「img」と記述するだけで画像が表示されます。
③画像の情報を取得
Imageオブジェクトには画像の情報が格納されているため、それらのプロパティ情報を取得することで画像に関するさまざまな情報を取得できます。
print('ファイル名:', img.filename)
print('サイズ:', img.size)
print('横幅:', img.width)
print('縦幅:', img.height)
print('カラーモード:', img.mode)
print('フォーマット:', img.format)
これを実行すると、以下のように出力されます。
ファイル名: sample.jpg
サイズ: (150, 150)
横幅: 150
縦幅: 150
モード: RGB
フォーマット: JPEG
④画像の保存
画像を保存するには、saveメソッドを使用します。
この例では、他の画像ファイルとして保存しています。
img.save('sample_copy.jpg')
5. Pillowで行える画像処理
Pillowを用いた画像処理の種類と、その方法を紹介します。
① クロップ・リサイズ
cropメソッドを使用することで、その画像の一部を切り抜きできます。
メソッドには、切り抜きをするx、y座標を指定します。
# (20,20)の座標から(100,100)までの座標部分を切り出し(クロップ)
cropped = img.crop((20, 20, 100, 100))
cropped.show()
切り抜き前:
切り抜き後:
リサイズする場合にはresizeメソッドを使用します。
### リサイズ(リサイズ後のサイズを指定)
resized = img.resize((100, 100))
resized.show()
リサイズ前:
リサイズ後:
ちなみに、このサイズ指定に縦横比はされません。
### 縦横比を保持しないでリサイズされる
wide_resized = img.resize((200, 100))
wide_resized.show()
これを出力すると以下のようになります。
リサイズ前:
リサイズ後:
縦横比を加味したリサイズをしたい場合の例
縦横比を加味してリサイズする場合には、画像の横幅と高さを取得して計算するようにしましょう。
# リサイズする割合
ratio = 1.3
# 計算したwidthとheightを使用してリサイズ
resized_x13 = img.resize((int(img.width * ratio), int(img.height * ratio)))
resized_x13.show()
リサイズ前:
リサイズ後:
② 回転
回転するには、rotateメソッドを使用します。
# 45°回転する
rotated = img.rotate(45)
rotated.show()
③ 2値化
カラー画像を白か黒の2つの値に変換することを「2値化」と呼びます。
元の画像:
グレースケール:
2値化した画像:
あまり馴染みのない手法となりますが、AIの分野では使用する可能性があるため、手法だけでも覚えておくと良いでしょう。
2値化の手順としては、以下の順番で実施します。
- グレースケール化する
- 数値データに変換する
- 0か1に変換する
# 必要なライブラリをインポートi
import numpy as np
from matplotlib import pylab as plt
# グレースケール化
grayscaled = img.convert('L')
grayscaled.show()
# 画像を配列に変換する
img_array = np.array(grayscaled, 'f')
# グレースケールのうち、白(0)と黒(255)の中間である128を基準に白黒へ変換
img_array = (img_array > 128) * 255
# matplotlibを使用して表示
plt.imshow(img_array)
ここで注意したいのが、img_arrayは画像ではなく「数値の配列」として保持されているという点。
そのため、今回はこの2値化した数値データを可視化するために、グラフ表示のための「matplotlib」を使用しています。
④ 輪郭抽出
画像の部分の輪郭を抽出し、線のみを描画します。
これらは「Filter」を使用することで簡単に実現できます。
from PIL import Image, ImageFilter
img = Image.open('sample.jpg')
# BLUR
blured = img.filter(ImageFilter.BLUR)
blured.show()
同様に、Filterに指定する値を「CONTOUR」とすることで黒い輪郭が描画されます。
img.filter(ImageFilter.CONTOUR).show()
⑤ ぼかし
Pillowを用いてぼかしを実現するにはいくつかの方法がありますが、今回はその中でも使用頻度の高い3つのぼかし手法を紹介します。
・ぼかし
・ガウスぼかし
・ボックスぼかし
それぞれぼかしの手法が若干異なるので、使用したいぼかし方法を選択すると良いでしょう。
なお、ぼかしの処理については輪郭抽出と同様にFilterの指定値を変更するだけなので、Filterの指定方法のみ紹介します。
・BLUR
まずは、通常のぼかし(BLUR)から紹介します。
img.filter(ImageFilter.BLUR) .show()
・Gaussian Blur(ガウスぼかし)
ガウスぼかしは、引数としてぼかしの強さを指定できます。
数値が大きいほど強いぼかしがかかります。
img.filter(ImageFilter.GaussianBlur(3)) .show()
・Box Blur
ボックスぼかしも、ガウスぼかしと同様に強さを指定できます。
img.filter(ImageFilter.BoxBlur(3)) .show()
⑥ 画像の貼り付け
2種類の画像を読み込み、画像の上に他の画像を張り付けます。
透過画像などを活用すれば、簡単な合成画像も作成できます。
from PIL import Image
### 画像の上に画像を貼り付け
background = Image.open('background.jpg')
foreground = Image.open('sample.jpg')
# 100x100にリサイズした女性の画像を座標(25,25)に貼り付け
background.paste(foreground.resize((100,100)), (25, 25))
background.show()
このbackgroundを表示すると、以下のように出力されます。
⑦ 図形の描画
ImageDrawを使用することで、画像の上に図形を描画することも可能です。
from PIL import Image, ImageDraw
# 描画先の画像
base = Image.open('sample.jpg')
# 描画オブジェクトを作成
draw = ImageDraw.Draw(base)
## 円を描画
draw.ellipse((20, 20, 50, 50), fill=(255, 0, 0))
## 四角形を描画
draw.rectangle((100, 100, 130, 120), fill=(0, 255, 0))
base.show()
※掲載された社名、製品名は、各社の商標及び登録商標です。