How do you pass in an image through a template and use a model to predict with FastAPI?
Question Description: I am trying to create a machine learning web application. I have an HTML page that takes in an image (jpg or png) and I am loading my model into the API to predict the image and output results. The lines under the prediction function of FastAPI have worked in a separate file but I think something is wrong with the data format that is taken in b
from starlette.responses import RedirectResponse from fastapi.staticfiles import StaticFiles from fastapi import FastAPI, Form from tensorflow.keras import preprocessing from keras.models import load_model import numpy as np import uvicorn app = FastAPI() app.mount("/Templates", StaticFiles(directory="Templates"), name="Templates") model_dir = 'F:\\Saved-Models\\Dog-Cat-Models\\First_Generation_dog_cat_optuna.h5' model = load_model(model_dir) @app.get('/') async def index(): return RedirectResponse(url="/Templates/index.html") @app.post('/prediction_page') async def prediction_form(dogcat_img: bytes = Form(...)): pp_dogcat_image = preprocessing.image.load_img(dogcat_img, target_size=(150, 150)) pp_dogcat_image_arr = preprocessing.image.img_to_array(pp_dogcat_image) input_arr = np.array([pp_dogcat_image_arr]) prediction = np.argmax(model.predict(input_arr), axis=-1) print(prediction) if __name__ == '__main__': uvicorn.run(app, host='localhost', port=8000)
The error I get:
FileNotFoundError: [Errno 2] No such file or directory: b'cat.83.jpg'
It shouldn’t need a full path because the image is getting passed through the webpage right? I have also tried UploadFile instead of bytes and got this error:
INFO: ::1:6918 - "POST /prediction_page HTTP/1.1" 422 Unprocessable Entity
Edit: HTML Code:
<form action="/prediction_page" method="post"> <label for="image-upload" class="custom-file-upload">Select Image:</label> <input type="file" id="image-upload" name="dogcat_img"><br> <input class="custom-submit-button" type="submit"> </form>

Expert Answer
Use async def prediction_form(dogcat_img: bytes = File(...)):
if you want to get bytes data.
In your case: pp_dogcat_image = preprocessing.image.load_img(dogcat_img, target_size=(150, 150))
seem this line will load a file from local file path. So i suggest you use UploadFile
type instead of bytes. And your function be like:
# ...
from fastapi import File, UploadFile
# ...
async def prediction_form(dogcat_img: UploadFile = File(...)):
# ...
pp_dogcat_image = preprocessing.image.load_img(dogcat_img.file_name, target_size=(150, 150))