0

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 on 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 by the API.

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>
Luleo_Primoc
  • 75
  • 1
  • 12
  • Does this answer your question? [How to send a base64 encoded image to a FastAPI backend?](https://stackoverflow.com/questions/64788970/how-to-send-a-base64-encoded-image-to-a-fastapi-backend) – Chris Oct 23 '22 at 08:11

1 Answers1

0

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))


Phuong Vu
  • 527
  • 4
  • 16
  • So I actually tried that before and it gave me this error: INFO: ::1:6918 - "POST /prediction_page HTTP/1.1" 422 Unprocessable Entity. I tried to look in the swagger UI for something useful but nada – Luleo_Primoc Sep 17 '21 at 03:09
  • If you're testing on swagger UI so the request content type should be `multipart/form-data` as expected. Try `async def prediction_form(*, dogcat_img: UploadFile = File(...)):` – Phuong Vu Sep 17 '21 at 03:16
  • Yeah tried that, still getting un-processable entity... – Luleo_Primoc Sep 18 '21 at 16:18