from fastapi import FastAPI, Request
from fastcore.transform import Transform
from fastapi.responses import HTMLResponse
from fastapi.middleware.cors import CORSMiddleware
from fastbook import *
from pydantic import BaseModel, Field
import urllib.request
import base64
from fastai.vision.widgets import *
from fastai.vision import *
from fastai.vision.all import *
from fastai.metrics import *
from fastai.data.external import *
from fastai.vision.all import *
import torchvision.transforms as transforms
import os
import pathlib
import base64
from pathlib import *
import PIL
from PIL import Image
from PIL import Image, ImageOps
from fastai.vision.all import *
import torchvision.transforms as transforms
import uvicorn
import asyncio
from pathlib import Path
class GrayscaleTransform(Transform):
def __init__(self):
pass
def encodes(self, img: PILImage):
return PIL.ImageOps.grayscale(img)
def get_fingers(fingers_path):
print('fingers path', fingers_path)
return []
def get_finger_label(finger_path: Path):
print('finger path', finger_path)
return ''
current_path = Path(os.getcwd())
print(f'Current path: {current_path}')
print('current_path', os.listdir(current_path))
print('current_path/data', os.listdir(current_path/'data'))
print('current_path/data/fingers', os.listdir(current_path/'data/fingers'))
fingers_path = Path(current_path/'data/fingers')
train_path = Path(fingers_path/'train')
test_path = Path(fingers_path/'test')
print('train_path', os.listdir(train_path))
print('test_path', os.listdir(test_path))
def get_fingers(fingers_path):
print('fingers path', fingers_path)
return []
def get_finger_label(finger_path: Path):
print('finger path', finger_path)
return ''
fingers: DataBlock = DataBlock(
blocks=(ImageBlock, CategoryBlock),
get_items=get_fingers,
splitter=RandomSplitter(valid_pct=0.2, seed=42),
get_y=get_finger_label,
item_tfms=Resize(128)
)
# Define the normalization transform
normalize_transform = Normalize.from_stats(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
# Define the image transformations
image_transforms = [RandomResizedCrop(128, min_scale=0.3), GrayscaleTransform]
processed_fingers = fingers.new(item_tfms=image_transforms, batch_tfms=[*aug_transforms(), normalize_transform])
# dls = processed_fingers.dataloaders(fingers_path)
# learn_inf: Learner = load_learner(current_path/'models/export.pkl')
# print(f'Bear Model successfully loaded: {learn_inf}')
print(f'Model file exists? ', Path(current_path/'models/fingers-2023-06-30-00_06_35.pkl').exists())
print(f'Stats ', os.lstat(current_path/'models/fingers-2023-06-30-00_06_35.pkl'))
finger_learn_inf: Learner = load_learner(current_path/'models/fingers-2023-06-30-00_06_35.pkl')
print(f'Finger Model successfully loaded: {finger_learn_inf}')
app = FastAPI()
## Full documentation on https://thiagoh-simple-predictor.hf.space/docs
## Usage
# curl -X GET 'https://thiagoh-simple-predictor.hf.space/?name=uia' -H "Content-Type: application/json"
origins = [
"http://thiagoh.github.io",
"https://thiagoh.github.io",
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/", response_class=HTMLResponse)
def read_root():
routes = app.routes
print(f'Routes: {routes}')
content = f"""
Some HTML in here
Here's the available routes in this app
{''.join(map(lambda e: f'- {e.path}
', routes))}
Navigation details
Navigate to https://thiagoh-simple-predictor.hf.space to hit the application. You can also curl
it
"""
return HTMLResponse(content=content, status_code=200)
@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
print(f'Printing this to the log stream', request.url)
response = await call_next(request)
return response
@app.get("/do-that")
def do_that(name: str = ""):
return {"action": 'do that'}
@app.get("/do-this")
def do_this(name: str = ""):
return {"action": 'do this'}
class Item(BaseModel):
imageUrl: Union[str, None] = Field(default=None, title="Url of an image", max_length=2400)
image_base64_bytes: Union[str, None] = None
class Prediction(BaseModel):
prediction: str
probability: float
imageEncodedBytes: Union[str, None] = None
@app.post("/display-image")
def display_image(item: Item):
if item.imageUrl:
with urllib.request.urlopen(item.imageUrl) as f:
decoded_bytes = f.read()
encoded_bytes = base64.b64encode(decoded_bytes)
else:
decoded_bytes = base64.b64decode(item.image_base64_bytes)
encoded_bytes = item.image_base64_bytes
# content = f"""
#
#
# Display Image
#
#
#
#
# """
# return HTMLResponse(content=content, status_code=200)
prediction, prediction_idx, probabilities = learn_inf.predict(PILImage.create(decoded_bytes))
probability: int = probabilities[prediction_idx]
print(f'Prediction: {prediction}; Probability: {probability:.04f}')
return Prediction(prediction=prediction, probability=probability, imageEncodedBytes=encoded_bytes)
@app.post("/predict", response_model=Prediction)
def predict(item: Item):
bytes = BytesIO(base64.b64decode(item.image_base64_bytes))
img = PILImage.create(bytes)
prediction, prediction_idx, probabilities = learn_inf.predict(img)
probability: int = probabilities[prediction_idx]
print(f'Prediction: {prediction}; Probability: {probability:.04f}')
return Prediction(prediction=prediction, probability=probability)
@app.get("/do-something-else/{person}")
def do_something_else(person: str):
return {"action": f'do something else with person {person}'}
@app.post("/predict-bear")
def predict_bear(item: Item):
if item.imageUrl:
with urllib.request.urlopen(item.imageUrl) as f:
decoded_bytes = f.read()
encoded_bytes = base64.b64encode(decoded_bytes)
else:
decoded_bytes = base64.b64decode(item.image_base64_bytes)
encoded_bytes = item.image_base64_bytes
prediction, prediction_idx, probabilities = learn_inf.predict(PILImage.create(decoded_bytes))
probability: int = probabilities[prediction_idx]
print(f'Prediction: {prediction}; Probability: {probability:.04f}')
return Prediction(prediction=prediction, probability=probability, imageEncodedBytes=encoded_bytes)
class InputItem(BaseModel):
imageUrl: Union[str, None] = Field(default=None, title="Url of an image", max_length=2400)
imageEncodedBytes: Union[str, None] = None
@app.post("/predict-finger")
def predict_finger(item: InputItem):
if item.imageUrl:
with urllib.request.urlopen(item.imageUrl) as f:
decoded_bytes = f.read()
encoded_bytes = base64.b64encode(decoded_bytes)
else:
decoded_bytes = base64.b64decode(item.imageEncodedBytes)
encoded_bytes = item.imageEncodedBytes
prediction, prediction_idx, probabilities = learn_inf.predict(PILImage.create(decoded_bytes))
probability: int = probabilities[prediction_idx]
print(f'Prediction: {prediction}; Probability: {probability:.04f}')
return Prediction(prediction=prediction, probability=probability, imageEncodedBytes=encoded_bytes)