File size: 3,006 Bytes
d6f8220
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b4ce3f4
d6f8220
 
b4ce3f4
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# from typing import Union

from fastapi import FastAPI, File, UploadFile, HTTPException
from PIL import Image
from io import BytesIO
import numpy as np
import tensorflow as tf
import cv2
from classnames import CLASSNAMES
import time

app = FastAPI()

interpreter = tf.lite.Interpreter(model_path="./model.tflite")
interpreter.allocate_tensors()
input_details = interpreter.get_input_details()[0]
output_details = interpreter.get_output_details()[0]


@app.get("/")
def home():
    return {
        "project": "Rotten - Healthy Fruit Classification",
        "author": "Ibrahim B. Oduola",
        "social handles": {
            "websites": "www.ioweb.pro",
            "x": "@diboworks",
            "linkedin": "https://www.linkedin.com/in/ibrahim-oduola/",
            "email": "ibrahim.oduola007@gmail.com"
        },
        "project description" : "This is a simple computer vision model trained on 14 fruits and vegetables. It predicts the status of the fruit or vegetable (i.e fresh or rotten). This is still in the beta version. Fruits it is trained on includes: Apple, Banana, Bellpepper, carrot, Cucumber, Grape, Guava, Jujube, Mango, Orange, Pomogranate, Potato, Strawberry and Tomato",
        "release date": "Sept. 30, 2025",
        "available endpoints" : [
            {
                "title": "",
                "url": '/classify/beta',
                "description": "make a post request to this endpoint. The body should contain a key ('foodimage') and the value should be the image file (png, jpg or jpeg)"
            }
        ]
        }


@app.post("/classify/beta")
def compute_inference(foodimage: UploadFile):

    # empty image upload is automatically handled

    if foodimage.filename.split(".")[-1] in ["jpg", "png", "jpeg"]:

        start_time = time.time()

        image = Image.open(BytesIO(foodimage.file.read()))
        image = np.array(image)
        image = cv2.resize(image, (256, 256))
        image = np.expand_dims(image, axis=0)
        # image = np.float32(image)

        interpreter.set_tensor(input_details["index"], image)
        interpreter.invoke()

        result = interpreter.get_tensor(output_details["index"])
        # the reult shape is [1, 28]

        execution_time = time.time() - start_time

        index = np.argmax(result, axis=1)
        score = result[:, index]
        percentage = (score[0][0] / 255) * 100
        
        food = CLASSNAMES[index[0]]
        foodname, status = food.split(",")

        return {
            "name": foodname,
            "health status": status,
            "confidence score": "{:.2f}%".format(percentage),
            "compute time": "{:.1f}s".format(execution_time)
            }
    else:
        # can als raise instead of returning it
        raise HTTPException(status_code=400, detail="uploaded file type not supported")


@app.on_event("startup")
async def show_routes():
    print("=== ROUTES LOADED ===")
    for route in app.router.routes:
        print(route.path, route.methods)