PIL.UnidentifiedImageError: cannot identify image file <_io.BytesIO object

Viewed 10698

I am trying to train my model (Image classification) using Tensorflow. I keep getting an error when I try to run the following cell:

    hist = model.fit(
        train_generator, 
        epochs=100,
        verbose=1,
        steps_per_epoch=steps_per_epoch,
        validation_data=valid_generator,
        validation_steps=val_steps_per_epoch).history

Error is:

Epoch 1/100
27/31 [=========================>....] - ETA: 1s - loss: 0.7309 - acc: 0.6181
---------------------------------------------------------------------------
UnknownError                              Traceback (most recent call last)
<ipython-input-36-b1c104100211> in <module>
      2 val_steps_per_epoch = np.ceil(valid_generator.samples/valid_generator.batch_size)
      3 
----> 4 hist = model.fit(
      5     train_generator,
      6     epochs=100,

/opt/anaconda3/lib/python3.8/site-packages/tensorflow/python/keras/engine/training.py in fit(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, validation_batch_size, validation_freq, max_queue_size, workers, use_multiprocessing)
   1098                 _r=1):
   1099               callbacks.on_train_batch_begin(step)
-> 1100               tmp_logs = self.train_function(iterator)
   1101               if data_handler.should_sync:
   1102                 context.async_wait()

/opt/anaconda3/lib/python3.8/site-packages/tensorflow/python/eager/def_function.py in __call__(self, *args, **kwds)
    826     tracing_count = self.experimental_get_tracing_count()
    827     with trace.Trace(self._name) as tm:
--> 828       result = self._call(*args, **kwds)
    829       compiler = "xla" if self._experimental_compile else "nonXla"
    830       new_tracing_count = self.experimental_get_tracing_count()

/opt/anaconda3/lib/python3.8/site-packages/tensorflow/python/eager/def_function.py in _call(self, *args, **kwds)
    853       # In this case we have created variables on the first call, so we run the
    854       # defunned version which is guaranteed to never create variables.
--> 855       return self._stateless_fn(*args, **kwds)  # pylint: disable=not-callable
    856     elif self._stateful_fn is not None:
    857       # Release the lock early so that multiple threads can perform the call

/opt/anaconda3/lib/python3.8/site-packages/tensorflow/python/eager/function.py in __call__(self, *args, **kwargs)
   2940       (graph_function,
   2941        filtered_flat_args) = self._maybe_define_function(args, kwargs)
-> 2942     return graph_function._call_flat(
   2943         filtered_flat_args, captured_inputs=graph_function.captured_inputs)  # pylint: disable=protected-access
   2944 

/opt/anaconda3/lib/python3.8/site-packages/tensorflow/python/eager/function.py in _call_flat(self, args, captured_inputs, cancellation_manager)
   1916         and executing_eagerly):
   1917       # No tape is watching; skip to running the function.
-> 1918       return self._build_call_outputs(self._inference_function.call(
   1919           ctx, args, cancellation_manager=cancellation_manager))
   1920     forward_backward = self._select_forward_and_backward_functions(

/opt/anaconda3/lib/python3.8/site-packages/tensorflow/python/eager/function.py in call(self, ctx, args, cancellation_manager)
    553       with _InterpolateFunctionError(self):
    554         if cancellation_manager is None:
--> 555           outputs = execute.execute(
    556               str(self.signature.name),
    557               num_outputs=self._num_outputs,

/opt/anaconda3/lib/python3.8/site-packages/tensorflow/python/eager/execute.py in quick_execute(op_name, num_outputs, inputs, attrs, ctx, name)
     57   try:
     58     ctx.ensure_initialized()
---> 59     tensors = pywrap_tfe.TFE_Py_Execute(ctx._handle, device_name, op_name,
     60                                         inputs, attrs, num_outputs)
     61   except core._NotOkStatusException as e:

UnknownError:  UnidentifiedImageError: cannot identify image file <_io.BytesIO object at 0x7fc88d55c9a0>
Traceback (most recent call last):

  File "/opt/anaconda3/lib/python3.8/site-packages/tensorflow/python/ops/script_ops.py", line 249, in __call__
    ret = func(*args)

  File "/opt/anaconda3/lib/python3.8/site-packages/tensorflow/python/autograph/impl/api.py", line 620, in wrapper
    return func(*args, **kwargs)

  File "/opt/anaconda3/lib/python3.8/site-packages/tensorflow/python/data/ops/dataset_ops.py", line 891, in generator_py_func
    values = next(generator_state.get_iterator(iterator_id))

  File "/opt/anaconda3/lib/python3.8/site-packages/tensorflow/python/keras/engine/data_adapter.py", line 807, in wrapped_generator
    for data in generator_fn():

  File "/opt/anaconda3/lib/python3.8/site-packages/tensorflow/python/keras/engine/data_adapter.py", line 933, in generator_fn
    yield x[i]

  File "/opt/anaconda3/lib/python3.8/site-packages/keras_preprocessing/image/iterator.py", line 65, in __getitem__
    return self._get_batches_of_transformed_samples(index_array)

  File "/opt/anaconda3/lib/python3.8/site-packages/keras_preprocessing/image/iterator.py", line 227, in _get_batches_of_transformed_samples
    img = load_img(filepaths[j],

  File "/opt/anaconda3/lib/python3.8/site-packages/keras_preprocessing/image/utils.py", line 114, in load_img
    img = pil_image.open(io.BytesIO(f.read()))

  File "/opt/anaconda3/lib/python3.8/site-packages/PIL/Image.py", line 2943, in open
    raise UnidentifiedImageError(

PIL.UnidentifiedImageError: cannot identify image file <_io.BytesIO object at 0x7fc88d55c9a0>


     [[{{node PyFunc}}]]
     [[IteratorGetNext]] [Op:__inference_train_function_24233]

Function call stack:
train_function

I tried changing from loss='categorical_crossentropy' to loss='binary_crossentropy' but still the issue persists. I wish to train the model but the Epoch keeps getting stuck.

Edit:

The train generator function and where it is used is as follows:

IMAGE_SHAPE = (224, 224)
TRAINING_DATA_DIR = str(data_root)


datagen_kwargs = dict(rescale=1./255, validation_split=.20)
valid_datagen = tf.keras.preprocessing.image.ImageDataGenerator(**datagen_kwargs)
valid_generator = valid_datagen.flow_from_directory(
    TRAINING_DATA_DIR, 
    subset="validation", 
    shuffle=True,
    target_size=IMAGE_SHAPE
)

train_datagen = tf.keras.preprocessing.image.ImageDataGenerator(**datagen_kwargs)
train_generator = train_datagen.flow_from_directory(
    TRAINING_DATA_DIR, 
    subset="training",
    shuffle=True,
    target_size=IMAGE_SHAPE)


for image_batch, label_batch in train_generator:
  break
image_batch.shape, label_batch.shape

Output: ((32, 224, 224, 3), (32, 2))

print (train_generator.class_indices)

labels = '\n'.join(sorted(train_generator.class_indices.keys()))

with open('labels.txt', 'w') as f:
  f.write(labels)

Output: {'off': 0, 'on': 1}

4 Answers

There was an issue with one of the img that was causing an issue and was pointed out by @Lescurel. To view the img you can run the following:

import PIL
from pathlib import Path
from PIL import UnidentifiedImageError

path = Path("INSERT PATH HERE").rglob("*.jpeg")
for img_p in path:
    try:
        img = PIL.Image.open(img_p)
    except PIL.UnidentifiedImageError:
            print(img_p)

You can also do the same for png or other formats. If there is an issue with your image, it will list it as soon as you run it

Similar to @EverydayDeveloper, but using glob to hold all image path with class.

import PIL
from PIL import UnidentifiedImageError
import glob

imgs_ = glob.glob("/home/ubuntu/imageTrain_dobby/SKJEWELLERY/classification/dataset/jewellery_dataset/train/*/*.jpg")

for img in imgs_:
    try:
        img = PIL.Image.open(img)
    except PIL.UnidentifiedImageError:
        print(img)

I had the same issue when accessing a training dataset on an external hard drive on a mac. The flow_from_directory function returned more files than I had placed in the folders.

Moving the whole training dataset to the local drive resolved the issue.

I encountered the same error when attempting to call Image.open() but I was calling this function on bytes received from a flutter client application via a multipart request.

The problem was that I didn't include the filename argument on the client side:

MultipartFile.fromBytes('image', await image.readAsBytes(),
      filename: image.name)

After adding filename: image.name, Image.open was able to identify the image file.

Related