LoginSignup
1
0

Pythonライブラリ、画像読み込み速度比較

Last updated at Posted at 2023-04-08

はじめに

最近、大量の高画質な画像を処理するようになり、読み込み速度すら気になってきました。
そこで、主な画像読み込み関数が含まれるPythonライブラリを使用して、読み込み度比較をします。

ネットの海を探したら、速度比較は出てくるのですが、画像の拡張子ごとで比較しているものがなかったので、画像拡張子含めて時間を計測してみたいと思います。できれば、PNGが早く読み込めるライブラリがあるといいな。

使用するライブラリ

Library Version
OpenCV *1 4.5.5
Pillow 9.0.1
Scikit-image 0.20.0
matplotlib 3.7.1
imageio 2.27.0
torchvision *2 0.15.1+cu118
Lycon *2 0.2.0

*1 OpenCVは、ソースコートを色々なオプションをオンにしてビルドして使用しているので、pipなどで入れると速度が違う可能性があります
*2 対応しているJPEGとPNGのみ計測します

使用するPCのスペック

項目 スペック
CPU 12th Gen Intel® Core™ i7-12700 × 20
Memory 32GB
GPU GeForce RTX 3080
OS Ubuntu 22.04 LTS
Python 3.10.6
Numpy 1.24.2

比較する画像

比較する画像は、スマートフォンで撮影したJPEG画像(4032x2272)をGIMPで他の拡張子にエクスポートして、作成しました。
※写っているのはホロライブのグッズです。

DSC_3407.JPG

比較する画像拡張子の一覧はこちら。

拡張子 圧縮 上図のサイズ
bmp 無圧縮 27.5MB
jpg 非可逆圧縮 3.4MB
png 可逆圧縮 11.6MB
tiff 無圧縮 27.5MB

各拡張子の違いについては、下記のサイトを参照してください。

速度比較コード

画像を10, 100, 1000, 2000, 3000回と連続で読み込みます。
OpenCV以外の読み込みに関しては、画像読み込み後にOpenCVで扱えるフォーマットに変換するまでを読み込み時間とします。

test.py
# coding:utf-8

import time
import numpy as np
import cv2
from PIL import Image
import matplotlib.image as mpimg
import skimage.io as io
import imageio
import tensorflow as tf
import lycon
import pandas as pd
from torchvision.io import read_image

def imreader(method:str, img_name):
    img = None
    if method is "opencv":
        img = cv2.imread(img_name)
    elif method is "pillow":
        buf = np.array(Image.open(img_name), dtype=np.uint8)
        img = cv2.cvtColor(buf, cv2.COLOR_RGB2BGR)
    elif method is "matplot":
        buf = mpimg.imread(img_name)
        img = cv2.cvtColor(buf, cv2.COLOR_RGB2BGR)
    elif method is "skimage":
        buf = io.imread(img_name)
        img = cv2.cvtColor(buf, cv2.COLOR_RGB2BGR)
    elif method is "imageio":
        buf = imageio.v2.imread(img_name)
        img = cv2.cvtColor(buf, cv2.COLOR_RGB2BGR)
    elif method is "keras":
        buf = tf.keras.utils.load_img(img_name)
        buf = tf.keras.utils.img_to_array(buf)
        img = cv2.cvtColor(buf, cv2.COLOR_RGB2BGR)
    elif method is 'lycon':
        if '.png' in img_name or '.JPG' in img_name:
            buf = lycon.load(img_name)
            img = cv2.cvtColor(buf, cv2.COLOR_RGB2BGR)
    elif method is "torch":
        if '.png' in img_name or '.JPG' in img_name:
            buf1 = read_image(path=img_name)
            buf2 = buf1.permute(1, 2, 0).to('cpu').detach().numpy().copy()
            img = cv2.cvtColor(buf2, cv2.COLOR_RGB2BGR)
    return img

def main():

    libraries = ["torch", "lycon"] #["opencv", "pillow", "matplot", "skimage", "imageio", "lycon"]
    read_num  = [10, 20, 1000, 2000, 3000]
    extension = ['tiff', 'png', 'JPG', 'bmp']
    img_name = "data/DSC_3407"

    index_list = [f"{_exe}:{_method}" for _method in libraries for _exe in extension]

    df = pd.DataFrame(index=index_list, columns=read_num)

    # 画像拡張子別
    for _exe in extension:
        _name = f"{img_name}.{_exe}"
        # ライブラリ
        for _method in libraries:
            # 読み込み回数
            for r in read_num:
                st = time.time()
                for i in range(r):
                    img = imreader(_method, _name)
                et = time.time()
                outstr = f"{_exe} {_method}  {r:4d}: {(et-st):.2f}[s]"
                print(outstr)
                df.loc[f"{_exe}:{_method}", r] = (et -st)
    
    df.sort_index(inplace=True)
    df.to_csv('output.csv')
    print(df.to_markdown())

if __name__=="__main__":
    main()

結果

各読み込み回数ごとの実測値を表にまとめます。単位は、秒です。

Extension library 読み込み回数-> 10 100 1000 2000 3000
tiff skimage tiff 0.10 0.87 8.68 17.42 26.25
pillow tiff 0.27 2.74 27.39 54.71 82.13
opencv tiff 0.13 1.24 12.31 24.68 37.21
matplot tiff 0.28 2.83 28.36 56.74 84.94
imageio tiff 0.10 0.89 8.84 17.61 26.47
png skimage png 2.22 22.40 223.75 447.92 670.06
pillow png 2.24 22.33 223.79 453.66 680.40
opencv png 1.86 18.39 184.40 367.79 550.46
matplot png 2.65 26.69 266.39 532.85 798.22
imageio png 2.27 22.94 229.66 459.87 690.42
torchvison png 2.00 3.85 190.83 379.48 572.58
Lycon png 1.90 3.72 184.89 368.64 554.95
jpg skimage jpg 0.58 5.85 58.38 116.24 175.22
pillow jpg 0.55 5.50 55.16 110.82 165.92
opencv jpg 0.41 4.05 40.22 80.53 120.98
matplot jpg 0.59 5.84 58.36 116.68 175.12
imageio jpg 0.59 5.94 58.96 117.98 177.08
torchvison jpg 0.38 0.77 38.27 76.60 114.81
Lycon jpg 0.38 0.75 37.46 74.95 111.14
bmp skimage bmp 0.31 2.92 29.16 58.87 89.01
pillow bmp 0.36 3.63 31.80 57.59 86.39
opencv bmp 0.08 0.62 6.03 12.02 18.10
matplot bmp 0.30 3.03 30.19 60.40 90.56
imageio bmp 0.30 2.99 29.64 58.76 92.12

3000回の読み込みの比較

太字が各拡張子ごとの最速のライブラリ

library tiff png jpg bmp
skimage 26.25 670.06 175.22 89.01
pillow 82.13 680.40 165.92 86.39
opencv 37.21 550.46 120.98 18.10
matplot 84.94 798.22 175.12 90.56
imageio 26.47 690.42 177.08 92.12
torchvison ----- 572.58 114.81 -----
Lycon ----- 554.95 111.14 -----

tiff

tiffは、scikit-imageとimageioの勝利でした。
OpenCVよりも速いのが驚きでした。

tiff_graph.png

PNG

pngはOpenCVが圧勝するかと思いきや、Lyconがほぼ同じぐらいの速度を出しています。
PNGの読み込み速度は、ここが限界なのかもしれません。

png_graph.png

JPEG(jpg)

JPEGはなんと、Lyconが優勝でした。さすが高速化ライブラリですね。
torchvisionも速いので、学習系で使用する際はtorchvisionで読み込んで使った方が、変換処理が必要ない分だけ更に速いかもしれません。

jpg_graph.png

Bitmap(bmp)

Bitmapは、OpenCVが優勝でした。他のライブラリはそれほど差がない結果となりました。

bmp_graph.png

結論

  • OpenCVをビルドして使用するのがほぼ最強
  • LyconはPNG,JPEGの読み込みではかなり使える
  • torchvisionも速いので、学習系ではtorchvisionを使用する方が速い可能性あり

参考サイト

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0