前回の記事でPythonの外部パッケージとして、グラフ作成のための外部モジュール「matplotlib」について使い方などを説明しました。
今回はイメージ処理(画像処理)のためのライブラリで「pillow」という外部パッケージについて、その内容と使い方などを説明していきたいと思います。
- 外部パッケージについての内容がわかる
- pillowパッケージについて、その内容と具体的な使い方が分かる
pillowのインストール
イメージ処理(画像処理)もプログラミング言語で自動化出来ます。
イメージ処理の分野だとPythonでは「Pillow」が最も使いやすく有名なパッケージです。
イメージを読み込み、それを回転したり拡大・縮小したり、あるいは特定のフィルター処理などを行ってイメージを加工し保存する機能を提供します。
matplotlibパッケージのインストール
では、「pillow」パッケージをインストールしてみましょう。
インストールは前回説明した「pip」コマンドを使ってインストールします。
ターミナルを起動して、以下のコマンドを実行すると「pillow」モジュールの最新バージョンがインストールされます。
ちなみに、筆者の環境でインストールを実行すると以下の表示がされました。
$ pip install pillow
Collecting pillow
Using cached Pillow-9.1.0-cp310-cp310-macosx_10_9_x86_64.whl (3.1 MB)
Installing collected packages: pillow
Successfully installed pillow-9.1.0
最終行に「Successfully installed」もしくは「Requirement already satisfied」と表示されていれば、pillowのインストールが正しく行われています。
イメージ処理の基本
ではpillowを使ってみたいと思いますが、まずサンプル用に実行ファイルと同じディレクトリに「image.jpg」という名前でフルカラーの画像を用意しておきます。
ちなみに画像はいつもお世話になっているフリー画像サイト「Pixabay」からなるべくカラフルな画像を選びました
では、この画像ファイルを使っていろいろ画像編集をしていきます。
pillowでのイメージ処理の流れ
まずはpillowを使ったイメージ処理の基本について説明します。
pillowでイメージ処理を行うには、以下のような流れで処理を行います。
- イメージファイルを開いて読み込み、Imageインスタンスを作成する
- Imageインスタンスのメソッドを呼び出してイメージを操作する
- 処理済みのImageをファイルに保存する
イメージ処理の基本的なコードを見てみましょう。
pillowは「PIL」というモジュールとして用意されています。
この中にイメージ操作に必要となるモジュールがさらにいくつか用意されています。
imageの作成
イメージ処理の基本は「Image」というモジュールで、これが画像編集するイメージのモジュールになります。
イメージ処理には必ずこのImageモジュールをインポートしておきます。
そして最初にImageの「open」関数でイメージファイルを読み込み、imageインスタンスを生成します。
open関数は読み込むファイル名とアクセス権を引数に設定します。
imageの保存
読み込んだimageインスタンスを操作して修正済みのイメージを作成し、最後に「save」メソッドを呼び出して保存します。
saveは第1引数に保存するファイル名、第2引数にフォーマット名を指定して実行します。
フォーマットによってはオプション情報がさらに必要となる場合もあります。
これで問題なくファイルが保存されれば作業終了です。
なおopenとsaveメソッドでは、IOErrorという例外が発生することがありますのでtry構文で囲って実行するようにしておくのが良いです。
イメージを回転させる
では実際に操作してみましょう。
まずは簡単な操作として「イメージを90度回転させる」ところからやってみましょう。
Imageインスタンスのrotateメソッドを使ってイメージを回転させます。
これは指定した角度だけイメージを回転させたImageインスタンスを生成するメソッドです。
引数に回転する角度を指定して呼び出すと、指定の角度だけイメージを回転させたimageインスタンスを作成して返します。
では実際に使ってみましょう。
from PIL import Image
try:
img = Image.open("image.jpg","r")
img2 = img.rotate(90, expand=True)
img2.save("image_saved.jpg","JPEG")
except IOError as err:
print(err)
プログラムの5行目でrotateメソッドを呼び出していますが、第1引数「90」が回転する角度で、これで指定した角度だけ左回りに回転させます。
その後の「expand=」というキーワード引数は、イメージが回転して幅が増えただけイメージの大きさを広げて調整するためのものです。
これをTrueにするとイメージが自動調整され、Falseだと最初のイメージのサイズそのままではみ出た部分はカットされます。
これを実行するとimage.jpgファイルと同じ場所に「image_saved.jpg」という画像ファイルが新たに作成されます。
これが処理済みのイメージファイルとなり、開いてみるとimage.jpgの画像が90度左回りに回転したものが保存されているのが分かります。
イメージサイズの変更
イメージの大きさはImageインスタンスにある「resize」メソッドを呼び出します。
resizeは引数に横幅と高さの値のタプルを使います。
これで指定した大きさにリサイズされたイメージのImageインスタンスが返されます。
ではやってみましょう。
from PIL import Image
try:
img1 = Image.open("image.jpg","r")
w,h = img1.size
size = (int(w/4) ,int(h/4))
img2 = img1.resize(size)
img2.save("image_saved.jpg","JPEG")
except IOError as err:
print(err)
実行するとimage.jpgの縦横サイズを1/4に縮小したイメージが保存されます。
イメージの大きさはImageインスタンスのsizeプロパティに保管されています。
これはタプルになっていて、size[0]が横幅、size[1]が高さの値となります。
5行目でそれぞれの値を変数w,hに取り出し、6行目でこれらの値を4で割ってint型にキャストしたものをタプルに保管します。
7行目でこのsizeを使ってリサイズしています。
これで縦横が1/4に縮小されたイメージのimageインスタンスが変数img2に代入されるので、これをsaveメソッドで保存します。
モノクロに変換
写真などのイメージは通常フルカラーで作成されていることが多いです。
Imageの「convert」メソッドでこれをモノクロにしたり、GIFなどで使われているパレットモード(色数の少ない画像)に変換したり出来ます。
引数にはモードを示す文字列を指定します。
いくつかモードがありますが、主に使う3つを挙げておきます。
引数 | モード |
---|---|
“1” | 1bitのモノクロイメージ |
“L” | グレースケール |
“P” | パレットモード |
ではこちらもやってみましょう。
from PIL import Image
try:
img1 = Image.open("image.jpg","r")
img2 = img1.convert("1")
img2.save("image_saved_1.jpg","JPEG")
img2 = img1.convert("L")
img2.save("image_saved_L.jpg","JPEG")
except IOError as err:
print(err)
GIF画像がなかったので、JPEGで変換できる「1」と「L」でモノクロ変換してみました
実行するとimage.jpgのイメージを「1ビットモノクロ」(上)と「グレースケール」(下)に変換しました。
ポスタライズ・平均化・反転
PILには、Image以外のモジュールも用意されています。
イメージ処理で比較的よく利用されているものとしては「ImageOps」モジュールが挙げられます。
これは、イメージを様々に操作する関数をまとめたモジュールで、多くの機能がありますが、特によく使う関数をあげておきます。
ポスタライズはイメージを指定のビット数の色数で塗り分けることで、ポスターのような効果が得られます。
平均化は逆に全体のRGB各色の輝度を均していくもので、全体的に平板な印象のイメージに変わります。
反転は輝度を逆にしたもので、写真のネガのようなイメージになります。
ではこちらも実施してみましょう
from PIL import Image,ImageOps
try:
img1 = Image.open("image.jpg","r")
img2 = ImageOps.posterize(img1,1)
img2.save("image_saved_p.jpg","JPEG")
img2 = ImageOps.equalize(img1)
img2.save("image_saved_e.jpg","JPEG")
img2 = ImageOps.invert(img1)
img2.save("image_saved_i.jpg","JPEG")
except IOError as err:
print(err)
実行した結果は以下です。
いずれもメソッドを呼び出すだけで簡単に作成できます。
セピア調にする
ImageOpsには「colorize」という関数も用意されていて、これはグレースケールイメージを特定の色調に変更するのに利用され、モノクロ写真をセピア調にするような処理に利用できます。
colorizeは3つの引数を設定するのが基本です。
第1引数は処理するイメージ画像で、その他の引数はblackとwhiteというキーワード引数です。
これらは黒と白のそれぞれに設定する色を示すもので、RBGの各色の輝度を0〜255の整数で表した値をタプルでまとめます。
例えば、赤なら(255,0,0)というように指定します。
こちらも実施してみましょう。
from PIL import Image,ImageOps
try:
img1 = Image.open("image.jpg","r")
bw_img = img1.convert("L")
img2 = ImageOps.colorize(
bw_img,
black=(0,0,0),
white=(255,200,150))
img2.save("image_saved_c.jpg","JPEG")
except IOError as err:
print(err)
5行目でイメージをグレースケールに変換したものを用意します。
6行目でcolorizeでセピア調に変換したイメージを作成します。
グレースケールの中でblackは(0,0,0)と黒を指定して、whiteは(255,200,150)とセピア調の色合いを設定します。
これで全体的にセピア調のイメージが出来上がります。
ちなみにcolorizeは事前にグレースケールしたイメージが必要です、カラーのままのイメージをcolorizeに渡すと例外が発生しますので注意しましょう
各ドットの輝度を操作する
イメージは1つ1つドットにRBGのそれぞれの値が設定されて色の表示が決まります。
この1つ1つのドットの値を操作するのがImageインスタンスの「point」というメソッドです。
このpointは引数が非常に分かりにくく、引数にはルックアップテーブルと呼ばれるシーケンスか、あるいはラムダ式などの関数を指定します。
ルックアップテーブルとは、イメージの各ドットの輝度情報をテーブルにまとめたもので、手作業で作成するのはほぼ不可能です。
何らかの機能を使って取得するか、あるいは輝度の変換処理をまとめた関数を指定して利用することになります。
うーん、引数になにを指定して良いかよく分からないな
ではここではラムダ式を使って簡単に輝度を変えてみましょう。
実際にサンプルを作ってみましょう。
from PIL import Image
try:
img1 = Image.open("image.jpg","r")
img2 = img1.point(lambda p: p*2)
img2.save("image_saved_point.jpg","JPEG")
except IOError as err:
print(err)
これを実行すると、image.jpgのイメージを明るくしたものが作成されます。
ここでは5行目で引数で渡されたpを2倍にするラムダ式を引数に設定しており、これでpointで渡される1つ1つのドットの輝度が2倍に変換されるようになります。
ですので、輝度が高まり明るくなりました。
こういう具合にラムダ式の引数で値を増減することで、イメージ全体を明るくしたり暗くしたりできます。
まとめ
今回は、Pythonでの外部ライブラリの画像編集のモジュールpillowの利用方法について学びました。
pillowはこの他にもたくさんの機能が用意されていますので、色々調べてみて実際に使ってみるのも良いかと思います。