Python

【Python】外部パッケージの利用(画像編集:pillow)

外部パッケージの利用(画像編集:pillow)Python

前回の記事でPythonの外部パッケージとして、グラフ作成のための外部モジュール「matplotlib」について使い方などを説明しました。

今回はイメージ処理(画像処理)のためのライブラリで「pillow」という外部パッケージについて、その内容と使い方などを説明していきたいと思います。

この記事を読んで分かること
  • 外部パッケージについての内容がわかる
  • pillowパッケージについて、その内容と具体的な使い方が分かる
スポンサーリンク

pillowのインストール

イメージ処理(画像処理)もプログラミング言語で自動化出来ます。

イメージ処理の分野だとPythonでは「Pillow」が最も使いやすく有名なパッケージです。

イメージを読み込み、それを回転したり拡大・縮小したり、あるいは特定のフィルター処理などを行ってイメージを加工し保存する機能を提供します。

matplotlibパッケージのインストール

では、「pillow」パッケージをインストールしてみましょう。

インストールは前回説明した「pip」コマンドを使ってインストールします。

ターミナルを起動して、以下のコマンドを実行すると「pillow」モジュールの最新バージョンがインストールされます。

pip install pillow

メモ

お使いのPython実行環境によっては、上記pipコマンドでエラーがでる場合がありますので、その場合はpipコマンド前に上記「python -m」または「python3 -m」をつけるように読み替えて下さい。

ちなみに、筆者の環境でインストールを実行すると以下の表示がされました。

$ 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」という名前でフルカラーの画像を用意しておきます。

pillowのサンプル画像
image.jpg

ちなみに画像はいつもお世話になっているフリー画像サイト「Pixabay」からなるべくカラフルな画像を選びました

では、この画像ファイルを使っていろいろ画像編集をしていきます。

pillowでのイメージ処理の流れ

まずはpillowを使ったイメージ処理の基本について説明します。

pillowでイメージ処理を行うには、以下のような流れで処理を行います

  1. イメージファイルを開いて読み込み、Imageインスタンスを作成する
  2. Imageインスタンスのメソッドを呼び出してイメージを操作する
  3. 処理済みのImageをファイルに保存する

イメージ処理の基本的なコードを見てみましょう。

pillowは「PIL」というモジュールとして用意されています。

この中にイメージ操作に必要となるモジュールがさらにいくつか用意されています。

from PIL import Image

変数 = Image.open(ファイル名, “r” )
…..イメージ処理を行う…..
Imageのインスタンス.save(ファイル名, フォーマット)

imageの作成

イメージ処理の基本は「Image」というモジュールで、これが画像編集するイメージのモジュールになります。

イメージ処理には必ずこのImageモジュールをインポートしておきます。

そして最初にImageの「open」関数でイメージファイルを読み込み、imageインスタンスを生成します。

open関数は読み込むファイル名とアクセス権を引数に設定します。

imageの保存

読み込んだimageインスタンスを操作して修正済みのイメージを作成し、最後に「save」メソッドを呼び出して保存します。

saveは第1引数に保存するファイル名、第2引数にフォーマット名を指定して実行します。

フォーマットによってはオプション情報がさらに必要となる場合もあります。

これで問題なくファイルが保存されれば作業終了です。

なおopenとsaveメソッドでは、IOErrorという例外が発生することがありますのでtry構文で囲って実行するようにしておくのが良いです。

ポイント

イメージの加工は「Imageのopenで読み込む」「Imageインスタンスの表示を操作する」「saveで保存する」という手順で行う。

スポンサーリンク

イメージを回転させる

では実際に操作してみましょう。

まずは簡単な操作として「イメージを90度回転させる」ところからやってみましょう。

Imageインスタンスのrotateメソッドを使ってイメージを回転させます。
これは指定した角度だけイメージを回転させたImageインスタンスを生成するメソッドです。

Imageインスタンス.rotate(角度)

引数に回転する角度を指定して呼び出すと、指定の角度だけイメージを回転させた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」という画像ファイルが新たに作成されます。

pillowのサンプル画像を回転
image_saved.jpg

これが処理済みのイメージファイルとなり、開いてみるとimage.jpgの画像が90度左回りに回転したものが保存されているのが分かります。

ポイント

イメージの回転はimageの「rotate」メソッドで行う。これはイメージを左回りに回転させる。

スポンサーリンク

イメージサイズの変更

イメージの大きさはImageインスタンスにある「resize」メソッドを呼び出します。

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に縮小したイメージが保存されます。

pillowのサンプル画像を縮小
img_saved.jpg

イメージの大きさはImageインスタンスのsizeプロパティに保管されています。
これはタプルになっていて、size[0]が横幅、size[1]が高さの値となります。

5行目でそれぞれの値を変数w,hに取り出し、6行目でこれらの値を4で割ってint型にキャストしたものをタプルに保管します。

7行目でこのsizeを使ってリサイズしています。
これで縦横が1/4に縮小されたイメージのimageインスタンスが変数img2に代入されるので、これをsaveメソッドで保存します。

ポイント

イメージの「resize」メソッドを使うと、イメージの大きさを自由に変更できる

スポンサーリンク

モノクロに変換

写真などのイメージは通常フルカラーで作成されていることが多いです。

Imageの「convert」メソッドでこれをモノクロにしたり、GIFなどで使われているパレットモード(色数の少ない画像)に変換したり出来ます。

Imageインスタンス.convert(モード)

引数にはモードを示す文字列を指定します。
いくつかモードがありますが、主に使う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」でモノクロ変換してみました

pillowのサンプル画像を1ビットモノクロ
image_saved_1.jpg
pillowのサンプル画像をグレースケール
image_saved_L.jpg

実行するとimage.jpgのイメージを「1ビットモノクロ」(上)と「グレースケール」(下)に変換しました。

ポイント

イメージのconvertメソッドを使うと、モノクロに変換することができる

スポンサーリンク

ポスタライズ・平均化・反転

PILには、Image以外のモジュールも用意されています。
イメージ処理で比較的よく利用されているものとしては「ImageOps」モジュールが挙げられます。

これは、イメージを様々に操作する関数をまとめたモジュールで、多くの機能がありますが、特によく使う関数をあげておきます。

ポスタライズはイメージを指定のビット数の色数で塗り分けることで、ポスターのような効果が得られます。

ImageOps.posterize(imageインスタンス, ビット数)

平均化は逆に全体のRGB各色の輝度を均していくもので、全体的に平板な印象のイメージに変わります。

ImageOps.equalize(imageインスタンス)

反転は輝度を逆にしたもので、写真のネガのようなイメージになります。

ImageOps.invert(imageインスタンス)

ではこちらも実施してみましょう

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)

実行した結果は以下です。

pillowのサンプル画像をポスタライズ
image_saved_p.jpg
pillowのサンプル画像を平均化
image_saved_e.jpg
pillowのサンプル画像を反転
image_saved_i.jpg

いずれもメソッドを呼び出すだけで簡単に作成できます。

ポイント

イメージのポスタライズ、平均化、反転は、ImageOpsの「posterize」「equalize」「invert」関数で行える

スポンサーリンク

セピア調にする

ImageOpsには「colorize」という関数も用意されていて、これはグレースケールイメージを特定の色調に変更するのに利用され、モノクロ写真をセピア調にするような処理に利用できます。

colorizeは3つの引数を設定するのが基本です。

第1引数は処理するイメージ画像で、その他の引数はblackとwhiteというキーワード引数です。

これらは黒と白のそれぞれに設定する色を示すもので、RBGの各色の輝度を0〜255の整数で表した値をタプルでまとめます。
例えば、赤なら(255,0,0)というように指定します。

ImageOps.colorize(imageインスタンス, black=タプル, white=タプル)

こちらも実施してみましょう。

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)とセピア調の色合いを設定します。

これで全体的にセピア調のイメージが出来上がります。

pillowのサンプル画像をセピア調
image_saved_c.jpg

ちなみにcolorizeは事前にグレースケールしたイメージが必要です、カラーのままのイメージをcolorizeに渡すと例外が発生しますので注意しましょう

スポンサーリンク

各ドットの輝度を操作する

イメージは1つ1つドットにRBGのそれぞれの値が設定されて色の表示が決まります。

この1つ1つのドットの値を操作するのがImageインスタンスの「point」というメソッドです。

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倍に変換されるようになります。

pillowのサンプル画像を輝度上げる
image_saved_point.jpg

ですので、輝度が高まり明るくなりました。

こういう具合にラムダ式の引数で値を増減することで、イメージ全体を明るくしたり暗くしたりできます。

ポイント

イメージのpointを使うと、イメージ全体の輝度を操作できる

スポンサーリンク

まとめ

今回は、Pythonでの外部ライブラリの画像編集のモジュールpillowの利用方法について学びました。

pillowはこの他にもたくさんの機能が用意されていますので、色々調べてみて実際に使ってみるのも良いかと思います。