PIL.UnidentifiedImageError: cannot identify image file io.BytesIO object for deploying a PyTorch model in Flask

Question:

I have a Python-Flask application where I upload an image onto a server and perform predictions on a selected uploaded image using a dense-net model following this tutorial, which results in the following error: PIL.UnidentifiedImageError: cannot identify image file <_io.BytesIO object at 0x7f4ceb257950>

Here is my prediction route:

@app.route('/predict', methods=['POST'])
@login_required
def predict():
    if request.method == 'POST':

        filename = ""
        if len(request.form) == 0:
            flash("Please select a file to perform a prediction on")
            return redirect(url_for('index'))
        else:

            filename = request.form['file']
            filepath = os.path.join(app.config['UPLOAD_PATH'], 
                                     current_user.username, filename)
            
            file = open(filepath, 'rb')
            img_bytes = file.read()
            class_id, class_name = models.get_prediction(image_bytes=img_bytes)
            print(class_id, class_name)


    return render_template('predict.html', filename=filename)

models.py:

import io
import json
import os

from torchvision import models
import torchvision.transforms as transforms
from PIL import Image

imagenet_class_index = json.load(open('imagenet_class_index.json'))
model = models.densenet121(pretrained=True)
model.eval()

def transform_image(image_bytes):
    my_transforms = transforms.Compose([transforms.Resize(255),
                                        transforms.CenterCrop(224),
                                        transforms.ToTensor(),
                                        transforms.Normalize(
                                            [0.485, 0.456, 0.406],
                                            [0.229, 0.224, 0.225])])
    
    image = Image.open(io.BytesIO(image_bytes))
    return my_transforms(image).unsqueeze(0)

def get_prediction(image_bytes):
    tensor = transform_image(image_bytes=image_bytes)
    outputs = model.forward(tensor)
    _, y_hat = outputs.max(1)
    predicted_idx = str(y_hat.item())
    return imagenet_class_index[predicted_idx]

stack trace:

[2023-03-03 13:49:32,564] ERROR in app: Exception on /predict [POST]
Traceback (most recent call last):
  File "/mnt/c/Users/sahan/Desktop/Senior Year/CS 81a/Sahana-cs81a/venv/lib/python3.8/site-packages/flask/app.py", line 2525, in wsgi_app
    response = self.full_dispatch_request()
  File "/mnt/c/Users/sahan/Desktop/Senior Year/CS 81a/Sahana-cs81a/venv/lib/python3.8/site-packages/flask/app.py", line 1822, in full_dispatch_request        
    rv = self.handle_user_exception(e)
  File "/mnt/c/Users/sahan/Desktop/Senior Year/CS 81a/Sahana-cs81a/venv/lib/python3.8/site-packages/flask/app.py", line 1820, in full_dispatch_request        
    rv = self.dispatch_request()
  File "/mnt/c/Users/sahan/Desktop/Senior Year/CS 81a/Sahana-cs81a/venv/lib/python3.8/site-packages/flask/app.py", line 1796, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
  File "/mnt/c/Users/sahan/Desktop/Senior Year/CS 81a/Sahana-cs81a/venv/lib/python3.8/site-packages/flask_login/utils.py", line 290, in decorated_view        
    return current_app.ensure_sync(func)(*args, **kwargs)
  File "/mnt/c/Users/sahan/Desktop/Senior Year/CS 81a/Sahana-cs81a/cloudsystem/app.py", line 311, in predict
    class_id, class_name = models.get_prediction(image_bytes=img_bytes)
  File "/mnt/c/Users/sahan/Desktop/Senior Year/CS 81a/Sahana-cs81a/cloudsystem/models.py", line 25, in get_prediction
    tensor = transform_image(image_bytes=image_bytes)
  File "/mnt/c/Users/sahan/Desktop/Senior Year/CS 81a/Sahana-cs81a/cloudsystem/models.py", line 21, in transform_image
    image = Image.open(io.BytesIO(image_bytes))
  File "/mnt/c/Users/sahan/Desktop/Senior Year/CS 81a/Sahana-cs81a/venv/lib/python3.8/site-packages/PIL/Image.py", line 3283, in open
    raise UnidentifiedImageError(msg)
PIL.UnidentifiedImageError: cannot identify image file <_io.BytesIO object at 0x7f4c48b2ea40>

I have tried this with no success as well as ensuring that only valid file types (i.e. .png, .jpg) can be uploaded. I’ve also tried passing in the path name instead of file bytes, which results in a FileNotFoundError. I’ve double checked to make sure that the path is correct and the file does indeed exist in my local directory. Using OpenCV instead results in the same error as above. For now, I just want the prediction results to be printed in the terminal. Thank you!

Edit (1): Here are the first 20 bytes of image_bytes getting passed into PIL: b’xdexcfx13J5.pxf5xe5Qt9xd7xb5 xdax1dxab4xa0′

Edit (2): Since the bytes of the file don’t correspond to any image format, I tried to pass in the image path into Image.open() instead:

if os.path.isfile(filepath):
        print(filepath + " is a valid file from app.py")
class_id, class_name = models.get_prediction(filepath)

The print statement is printing the path, so I assume that the path being passed into models.get_prediction() is valid.

The transform_image() function now looks like this:

def transform_image(path):
    my_transforms = transforms.Compose([transforms.Resize(255),
                                        transforms.CenterCrop(224),
                                        transforms.ToTensor(),
                                        transforms.Normalize(
                                            [0.485, 0.456, 0.406],
                                            [0.229, 0.224, 0.225])])
    
    if os.path.isfile(path):
        print(path + " is a valid file from models.py")    
    image = Image.open(path)
    return my_transforms(image).unsqueeze(0)

Once again, the path of the inputted file is printing, so the file must exist within the path. However, I’m still getting the following error from Image.open(path): PIL.UnidentifiedImageError: cannot identify image file 'uploads/test/Cat03.jpg.

Asked By: sahana_s

||

Answers:

The issue was that a part of the image buffer was being read in a previously called function for image validation and as a result the image wasn’t being stored correctly. Removing the line of code reading the image buffer fixed the problem.

Answered By: sahana_s
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.