はじめに
顔や物体の画像を判別するプログラムを作成しているとき、学習用に様々な画像データを利用します。
COCO2014、COCO2017などから学習用の画像データをダウンロードして、機械学習を実行すると、「画像データを読み込めない」のようなエラーメッセージが表示されることがあります。
エラーメッセージの例1
tensorflow.python.framework.errors_impl.InvalidArgumentError: Expected image (JPEG, PNG, or GIF), got empty file
[[{{node DecodeJpeg}}]]
エラーメッセージの例2
tensorflow.python.framework.errors_impl.InvalidArgumentError: Invalid JPEG data or crop window, data size 32768
[[{{node DecodeJpeg}}]] [Op:IteratorGetNext]
「画像データを読み込めない」が原因として考えられるのが、下記の2点です。
- ダウンロードの過程で画像データが破損した
- 元々の画像データが破損している
機械学習を行う環境によっては、実行に数時間掛かる場合があります。
私の環境では、1回の機械学習に数時間掛かるので、数時間経過したあとにエラーが発生すると、やる気が削がれます。
事前に学習用の画像データが適切な画像データなのかを確認するプログラムを作成しました。
プログラムの概要
下記URLを基にプログラムを作成しました。
python – Tensorflow: Error when trying transfer learning: Invalid JPEG data or crop window – Stack Overflow
画像データがJPEG形式となっているかを確認し、JPEG形式と確認できない画像データを削除します。
<JPEG形式として認識する方法>
JPEGファイルの構造は、大まかに表現すると下記の4つのデータ領域に分割できます。
- Start of Image(SOI)
- 4つのデータ領域の情報(セグメント)
- 画像データ
- End of Image(EOI)
それぞれの領域には、マーカーが設けられています。
1.と3.と4.のマーカーの有無を確認することで、JPEG形式となっているかを確認します。
プログラム
7行目に確認する画像フォルダを指定します。
from struct import unpack
from tqdm import tqdm
import os
import glob
# 画像フォルダのパスを指定する
images = glob.glob(r'C:\tmp\train2014\*')
class JPEG:
def __init__(self, image_file):
with open(image_file, 'rb') as f:
self.img_data = f.read()
def decode(self):
'''
JPEGファイルの構造は、大まかに表現すると4つのデータ領域に分割できる。
1.Start of Image(SOI)
2.4つのデータ領域の情報(セグメント)
3.画像データ
4.End of Image(EOI)
decode関数では、1.と3.と4.のマーカーの有無を確認する
:return:
'''
data = self.img_data
while (True):
marker, = unpack(">H", data[0:2])
# Start of Image(SOI)を確認する
if marker == 0xffd8:
data = data[2:]
# End of Image(EOI)を確認する
elif marker == 0xffd9:
return
# Start of Scan(このマーカ以降が画像データ)を確認する
elif marker == 0xffda:
data = data[-2:]
else:
lenchunk, = unpack(">H", data[2:4])
data = data[2 + lenchunk:]
if len(data) == 0:
break
bads = []
for img in tqdm(images):
# 画像を読み込む
image = JPEG(img)
try:
# 画像がJPEG形式となっているかを確認する
image.decode()
except:
# 画像データを確認して、JPEG形式となっていない画像をbadsに代入する
bads.append(img)
print('削除する画像', bads)
for name in bads:
# JPEG形式となっていない画像データを削除する
os.remove(name)
実行結果
プログラムを実行する前に、動作に必要なライブラリをインストールしておきます。
pip install tqdm
COCO2014のtrain2014.zip内の画像データには、破損している画像データが含まれていました。COCO2014を確認した結果は下記の通りです。
> python.exe check-jpeg.py
100%|██████████| 82783/82783 [06:30<00:00, 212.10it/s]
削除する画像 ['C:\\tmp\\train2014\\COCO_train2014_000000167126.jpg']
削除した画像データをフォトアプリで表示しようとしても、正常に表示することができませんでした。
コメント