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'\xde\xcf\x13J5.p\xf5\xe5Qt9\xd7\xb5 \xda\x1d\xab4\xa0'
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
.