酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

Python で指定したディレクトリを再起的に調べていき、画像が破損している場合にファイルを削除する

Python で指定したディレクトリに含まれる画像が破損している場合に当該の画像ファイルを削除する方法を紹介する。

はじめに

Google Colab での TensorFlow を使った転移学習時に以下のエラーが発生した。

/usr/local/lib/python3.9/dist-packages/tensorflow/python/eager/execute.py in quick_execute(op_name, num_outputs, inputs, attrs, ctx, name)
     50   try:
     51     ctx.ensure_initialized()
---> 52     tensors = pywrap_tfe.TFE_Py_Execute(ctx._handle, device_name, op_name,
     53                                         inputs, attrs, num_outputs)
     54   except core._NotOkStatusException as e:

InvalidArgumentError: Graph execution error:

Input is empty.
     [[{{node decode_image/DecodeImage}}]]
     [[IteratorGetNext]] [Op:__inference_train_function_17834]

InvalidArgumentError: Graph execution error:DecodeImage から、画像ファイルの読み込みに失敗したのだろうかと疑った。具体的にどの画像ファイルが壊れているのかわからなかったが、画像が壊れている理由には心当たりがある。

Google Colab ではストレージの代わりとして Google Drive を利用する。機械学習させるために 160GB を超える大量の画像ファイルを Google Drive へアップロードしている。あまりにも大量だったからなのか、ファイルの保存(アップロード)時に画像ファイルが破損してしまったのだろう。

Google Drive へのアップロード時の問題に関しては以下のエントリに書いている。

blog.ch3cooh.jp

壊れた画像がデータセットに含まれているからエラーが発生するのだろうとアタリはつけたが、具体的に壊れているファイル名が分からず、画像ファイル数も多く検証が困難である。

Python で指定したディレクトリに含まれる画像が破損している場合に当該の画像ファイルを削除することにした。

指定したディレクトリを再起的に調べていき、画像が破損している場合にファイルを削除する

指定したディレクトリを再起的に調べていき、画像が破損している場合にファイルを削除するためには考えるべきことが二つある。

  • 画像ファイルの検証はどうするのか?
  • 画像ファイルを削除するにはどうするのか?

前者に関しては PIL (Python Imaging Library) の Image#verify() が使える。後者に関しては os.remove() でファイル削除ができる。

import os
from PIL import Image

def verify_images_recursive(directory):
    for root, dirs, files in os.walk(directory):
        for file in files:
            file_path = os.path.join(root, file)
            try:
                img = Image.open(file_path)
                img.verify()
            except Exception as e:
                print(f"エラー: {e}")
                os.remove(file_path)

dir_path = '/content/drive/MyDrive/colab_data/dataset'
verify_images_recursive(dir_path)

エラーを検出すると、例外が投げられて以下のようなメッセージとともに当該の画像ファイルを削除する。

エラー: cannot identify image file '/content/drive/MyDrive/colab/dataset/xxxxx/yyyyy.JPEG'