Python3+Pillowで画像圧縮をしてみました!

目次

はじめに

WordPressで画像圧縮に迫られていたので 今回はPython+Pillowを用いての画像圧縮についてまとめました. 今回はその備忘録です.

WordPressにあげる際の画像圧縮については今度にします.

Python+Pillowをインストールする

Pythonのインストール

Pythonのインストールはこちらの記事をご覧ください.

現在作成中ですm(_ _)m

Pillowのインストール

PillowはHomebrewではインストールできない(2020/07/07現在で確認済)ようなので, Pythonのパッケージ管理ツールpipを用いてインストールしていきます.

pip3 install Pillow

でインストールできます. ターミナルで,

Successfully installed Pillow-*.*.*

まで出ればインストールは成功です.

いよいよ画像を圧縮してみます

Pillowの基本的な使い方

いよいよ画像を読み込んでいきます. 今回は,

JPEGイメージ, 33,053,274 バイト(ディスク上の33.1 MB)

この画像は圧縮されたものです

の写真で圧縮の様子を確認してみます.

from PIL import Image, ImageFilter
image = Image.open('sample./jpg')

で画像の読み込みが行えます. また, 今回は必要ありませんが,

print(image.format, image.size, image.mode)

で読み込んだ画像のフォーマット, 大きさ(幅, 高さ), モードを取得できます. 他のメタ情報を取得することも可能です. 肝心の圧縮はresizeでLanczos関数による方法を用います.

resize_img = image.resize((8000 , 5333), Image.LANCZOS) 
resize_img.save("sample_pillow.JPG")
image_pillow = Image.open('sample_pillow.jpg')
print(image_pillow.format, image_pillow.size, image_pillow.mode)

これで画像の大きさを変えずに圧縮ができました. また, 画像の大きさを変える場合,

from PIL import Image, ImageFilter
image = Image.open('sample_g.jpg')

print(image.format, image.size, image.mode)

resize_img = image.resize((2560 , 1707), Image.LANCZOS) 

resize_img.save("sample_pillow.JPG")
image_pillow = Image.open('sample_pillow.jpg')

print(image_pillow.format, image_pillow.size, image_pillow.mode)

を「sample.py」で保存し,

python3 sample.py

とすれば, 2560×1707の大きさになります.

リサイズの方式は指定でき, デフォルトではNEARESTになります. 以下, 簡単にその違いを書いておきます.

Filter説明Downscaling qualityUpscaling qualityPerformance
NEARESTニアレストネイバー法. 最近傍補間.
BOXBOX近似.
BILINEARバイリニア法. 線形近似補間.
HAMMING線形近似より少し鮮明?
BICUBICバイキュービック法. 3次近似補間.
LANCZOSランツォシュ関数を用いた補間.
星の評価は https://pillow.readthedocs.io/en/4.0.x/handbook/concepts.html#filters からの抜粋です.

簡単にいうと, 下にいくほど処理に時間はかかりますが, クオリティはよくなります.

Pillowを用いて圧縮の違いを比較してみよう

では, 実際に5種類の圧縮をしてその違いを比較してみます. 次のようなコードで比較しました.

from PIL import Image, ImageFilter
image = Image.open('sample_original.jpg')

# 大きさを1/4にする
wid = 2000
hei = 1333

# 処理
resize_img1 = image.resize((wid, hei), Image.NEAREST) 
resize_img2 = image.resize((wid, hei), Image.BOX) 
resize_img3= image.resize((wid, hei), Image.BILINEAR) 
resize_img4 = image.resize((wid, hei), Image.HAMMING) 
resize_img5 = image.resize((wid, hei), Image.BICUBIC) 
resize_img6 = image.resize((wid, hei), Image.LANCZOS) 

# 出力
resize_img1.save("sample_pillow.NEAREST.jpg")
resize_img2.save("sample_pillow_BOX.jpg")
resize_img3.save("sample_pillow_.BILINEAR.jpg")
resize_img4.save("sample_pillow_HAMMING.jpg")
resize_img5.save("sample_pillow_BICUBIC.jpg")
resize_img6.save("sample_pillow_LANCZOS.jpg")

実際に, 出力された画像の情報を見てみると以下のようになっていました.

これらをまとめると,

Filter大きさサイズオリジナルからの圧縮率
オリジナル8000 × 533333,053,274 byte(33.1 MB)– – –
プレビューでサイズ変更したもの2000 × 13333,132,489 byte(3.1 MB)-90.5 %
NEAREST2000 × 1333767,900 byte(786 KB)-97.7 %
BOX2000 × 1333605,679 byte(655 KB)-98.2 %
BILINEAR2000 × 1333534,069 byte(537 KB)-98.4 %
HAMMING2000 × 1333587,263 byte(590 KB)-98.2 %
BICUBIC2000 × 1333589,326 byte(590 KB)-98.2 %
LANCZOS2000 × 1333616,727 byte(618 KB)-98.1 %

となります. つまり,

・プレビューでサイズを変更すると約1/10
・Pyton+Pillowを用いて圧縮すると約1/50

となることがわかりました.

Pierrotのアイコン画像Pierrot

これは数字のマジックですね. 比較している元の画像はそもそも大きさも全然違います. 本来であれば大きさを変えた3.1MBとと比べてどれくらい減ったか調べるべきです. 今回はブログなのであえて誇張させた表現を使ってますが, 騙されてはいけません. 笑.

当然, 元々の画像や変更する画像サイズによっていろいろ変わりますので, 今回の状況下での数値に過ぎません.

拡大してみると同じ圧縮でも質の違いが明確です. 特に, LANCZOSでの圧縮は見事です.

Pillowによる比較
左から順に, プレビューで大きさだけ変えたもの, NEAREST, LANCZOS

おわりに

ご覧いただいたように, Pythonは数多くのライブラリが用意されていますので, 画像圧縮自体はそれほど難しいものではありません. 上の結果だけを見れば,

Python+Pillowの場合, LANCZOS方式で圧縮する

方法が一番よいです.

また, PythonはPillow以外にもOpenCVなど画像圧縮ライブラリがあります.

誰もが利用できるよう, app化したいですが, それはまた別の機会にします.

コメント

コメントする

目次
閉じる