Spaces:
Sleeping
Sleeping
| # 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] | |
| 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)" | |
| } | |
| ] | |
| } | |
| 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") | |
| async def show_routes(): | |
| print("=== ROUTES LOADED ===") | |
| for route in app.router.routes: | |
| print(route.path, route.methods) | |