CC56

CC56: 567収束までに達成したい56リスト

Day-107 Pythonの高速画像処理ライブラリLyconが速い

何ヶ月か前にTwitterのタイムラインに流れてきたのですが、それっきり話題を聞かないので検証してみることにしました。

ちなみに、個人的に普段使って慣れているのは、癖が少なくて扱いやすい scikit-image です。 (OpenCVはBGRがデフォルトなので基本的に避けたいですし、PILは癖が強めなのであまり好きではないです)

高速の画像処理ライブラリを使うモチベは、もちろん Kaggle です。 特に画像の読み込みが速いと、時間短縮に直結するので個人的に嬉しいです。

Lyconとは

C++で書かれたPython用の軽量画像処理ライブラリらしいです。 PyPI にあるので pip install ですぐに使えます。(一応依存関係も気にしなきゃいけないかも)

github.com

性能の割にスターが控えめな気がする。

試しに使ってみる

多少の実戦を仮定して、Kaggle の Notebook 上で画像読み込みの速度を比較してみることにします。 Colaboratory だと、計算用のサーバーと保存用のサーバーの場所が別で、外部の遅延要素があるという噂を耳にしたので今回は除外しました。

まずは、Lycon を Notebook にインストールします。!pip install lycon でOK。

!pip install lycon
import lycon

# 今回ついでに使うやつ
import numpy as np
from skimage import io

次に、関数を2つ作ります。1つ目は、適当なダミー画像を生成、保存する make_random_images。2つ目は、関数を受け取ってその関数で画像を読み込む read_images です。読み込みテストなので値は返しません。

def make_random_images(amount=1000, shape=[224, 224], ext="png"):
    """
    amount: 保存するダミー画像の数
    shape: 保存する画像のサイズ [縦, 横]。3チャンネルで保存
    ext: 拡張子
    """
    for i in range(amount):
        randomsquare = np.random.rand(shape[0], shape[1], 3)
        io.imsave(f'output_{str(i).zfill(4)}.{ext}', randomsquare)
        
def read_images(load_func, amount=1000, ext="png"):
    """
    load_func: 画像読み込みの関数
    amount: 読み込む画像の数
    ext: 拡張子
    """
    for i in range(amount):
        img = load_func(f'output_{str(i).zfill(4)}.{ext}')
        
make_random_images(amount=1000, shape=[224, 224], ext="png")

ダミー画像は、画像やっている人なら想像できると思うんですが、こんな感じの虚無が生成されます。

f:id:hyper-pigeon:20200722223710p:plain

↑GANで失敗するとよく出るトラウマ画像っぽい。

話を戻すと、あとは、試しに read_images に画像読み込みの関数を投げれば比較できます。

今回は png 形式、画像数はほどほどの 1,000枚 でやってみましょう。

Lycon のほう ↓

%%time
read_images(lycon.load, amount=1000, ext="png")

scikit-image のほう ↓

%%time
read_images(io.imread, amount=1000, ext="png")

結果はこんな感じです。

f:id:hyper-pigeon:20200722223604p:plain
KaggleのNotebookによる結果

Lycon の方が倍近く速いですね。224x224 のカラー画像 1,000枚 あたり 1.3秒 の差が出るので、同条件下なら10万枚くらいで差が顕著になって、数百万枚あたりから時間単位で差がつく感じですね。

ちなみに、jpg 形式でもやってみたのですが、同じく倍近く高速化できていることが確認できました。

ベンチマークに関して

Lycon の Readme には既に以下のようなベンチマークがあります。

f:id:hyper-pigeon:20200722224920p:plain
LyconのReadmeに書いてあるベンチマークのスクショ(現在)

この条件下の png 読み込みだと、4.3倍近く差が出ることになっていますが、こちらの条件では2倍程度に収まりました。 もしかしたら、大きい画像を一気に読み込む場合、もっと差が出るのかもしれません。

何事も実戦に近い条件だと、好条件のベンチマークとは結果が乖離してしまうことは念頭に置いておきたいですね。 そこそこ気になったものは気軽に触ってみる精神が大事かもしれません。

おわりに

Lycon は軽量で使いやすかったです。 インストールも難しくないので、skimage の代用として即戦力になると思います。

読み込み、書き込み とかの基本機能は Lycon に任せて、残りは tf.image とか torchvision.transforms に投げるのがいい感じの組み合わせかな。

こういう実験は余裕があるときにサクサク進めておくと、後の自分が楽になるのでいいですね。