3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

load_img,imreadの画像読み込み時間の違い

Last updated at Posted at 2023-01-21

学習時間を少しでも短くしたい

トレーニングの時間は少しでも短くしたいですよね。
画像処理をしていて、画像の読み込みにかかる時間ってどれくらいなの?
というのを常々疑問に思っていたのですが、ちゃんと調べることはずっとしていませんでした。

load_img,imreadの画像の読み込み時間の違い

ほんとうはよくあるサンプルプログラムみたいに全部メモリに読み込んでおいてそれを処理できればいいんですがmnistじゃあるまいし実際に使う画像を全部乗っけられるようなメモリはなかなか取れません。
tensorflow , kerasを使ってる人だと load_imgを使ってる人もいるんじゃないかと思います。自分もはじめの頃に勉強した本がこれだったのでほぼずっとload_imgを使ってきていました。でもopencvにもimreadというのがあります。どっちがどれくらい速いの?
(@2023.1.22 PILの計測を追加しました)

実験

画像を1000枚読み込んで、ちょっとだけ加工(リサイズ、白黒化)する処理をして計測しました。
自分の場合白黒化する必要があったのでそれも計測に入れました。
計測に使った環境はgoogle colabのcpuです。
元画像はだいたいですが、長辺が1024の画像です。

import os

YDIRS = [ "./images" ] #適宜画像ファイルのあるディレクトリを指定

filePaths = []

for imgDir in YDIRS:

    fileList = os.listdir( imgDir )
    fileList.sort()
    
    for fileName in fileList:
        
        filePath = os.path.join( imgDir,fileName )
        
        filePaths.append( filePath )
    
imgNum = len( filePaths )
print( "imgNum="+str(imgNum))

こんな感じでファイルのパスを集めて

#load_imgで読むのにかかる時間

import time
from tensorflow.keras.utils import load_img

tfromEpo = time.perf_counter()

for i in range(1000):

  filePath = filePaths[i]

  img = load_img( filePath,target_size=(512,512))

  if i % 100 == 0:
    print( f"\r{i+1}/{imgNum}",end="" )

ttoEpo = time.perf_counter()
tdEpo = ttoEpo - tfromEpo

print( f" -- elapsed {tdEpo:.04f} sec." )

こんな感じで計測します。
目的サイズは512x512としました。

処理内容

load_img後のグレースケール化は自前の処理で、

imreadのほうは

ary = cv2.imread(filePath, cv2.IMREAD_GRAYSCALE)
aryX = cv2.resize(ary,(512,512),interpolation=cv2.INTER_LINEAR)

こんな感じです。
imreadはリサイズの補間オプションがあるのでそれの違いも調べました。

1000枚の画像を前処理で512x512に白黒でリサイズ化しておいたものをpngのテンポラリファイルとして保存しておいて読むこむのも計測しました。

要するにload_imgでもimreadでもPILでも最終的に512x512の白黒画像を1000枚、メモリに展開するのに掛かる時間を計測しました。

計測結果

load_img/imread/PIL 処理 時間(秒)
load_img 読み込みのみ 14.7785
load_img グレースケール化 16.1188
imread INTER_NEAREST 6.6793
imread INTER_LINEAR 7.0711
imread INTER_CUBIC 7.5854
imread INTER_AREA 9.1466
imread INTER_LANCZOS4 10.9502
imread 前処理したファイル(png)の読み込み 3.3909
PIL openのみ 0.0808
PIL open + img_to_array + cv2.resize(INTER_LINEAR) 17.9979
PIL open + conver('L')でグレー化+img_to_array+cv2.resize(INTER_LINEAR) 16.6866

結論

思っていた以上にload_imgが遅いことがわかりました。
補間については、AREA LANCZOS4はそれなりに重い処理のようです。
前処理しておいたものを読み込む仕組みに変えると倍以上に速くなっているところをみるとimreadを使った場合でもresizeは決して軽い処理ではないと言えそうです。

PILはopenだけだと激速ですが、ちょっとなにか処理すると途端に速度が低下しload_img以下になりました。なれてないもので使い方に間違いがあるのかもしれませんが、openだけだとほんとにファイルを開くだけなのだと思われます。

自分の場合は画像は70000枚くらいでしたので、大雑把にload_imgでグレースケール化してると15x70/60=17.5で1エポックごとに17分以上も画像の読み込み→白黒化に使っていたことになります。
もしこれを前処理したものをimreadする形式に変えたとすると3x70/60=3.5で1エポックごとに14分も高速化できることになります。

14分x100epoch=1400
1400/60=23.3333...

100epoch処理したとするとまる1日近くの違いになることになります。
全く馬鹿になりませんね。

@2023.1.22 PIL追加。計測の精度向上

3
3
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
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?