|
|
import gradio as gr |
|
|
from pyzbar.pyzbar import decode |
|
|
from lambdas import upload_models, predict |
|
|
import base64 |
|
|
from io import BytesIO, StringIO |
|
|
from PIL import Image |
|
|
import pandas as pd |
|
|
import os.path |
|
|
import numpy as np |
|
|
from datetime import datetime, timedelta |
|
|
from descriptions import prefer_frontal_cam_html, docu_eng, docu_cat, css_image_aspect_ratio |
|
|
|
|
|
DEBUG = True |
|
|
|
|
|
config = {'possible_shifts': {'No shifts': 0}, 'possible_modes': ["waste"]} |
|
|
|
|
|
|
|
|
def login(username, password) -> bool: |
|
|
if os.path.isfile('credentials.csv'): |
|
|
df = pd.read_csv('credentials.csv') |
|
|
else: |
|
|
s = os.environ.get('CREDENTIALS') |
|
|
df = pd.read_csv(StringIO(s)) |
|
|
|
|
|
if not len(df): |
|
|
return False |
|
|
df = df.replace({np.nan: None}) |
|
|
|
|
|
for idx, row in df.iterrows(): |
|
|
if row['username'] == username and row['password'] == password: |
|
|
restaurant_id = int(row['restaurant_id']) |
|
|
restaurant_name = str(row['restaurant_name']) |
|
|
mode = 'waste' |
|
|
possible_modes = str(row.get('modes')).split(':') |
|
|
possible_shifts = {i.split(':')[0]: int(i.split(':')[1]) for i in str(row.get('shifts')).split('-')} \ |
|
|
if row.get('shifts') else {'no shift': None} |
|
|
|
|
|
config_aux = {'restaurant_id': restaurant_id, |
|
|
'restaurant_name': restaurant_name, |
|
|
'mode': mode, |
|
|
'possible_modes': possible_modes, |
|
|
'possible_shifts': possible_shifts, |
|
|
} |
|
|
config.clear() |
|
|
config.update(config_aux) |
|
|
|
|
|
return True |
|
|
return False |
|
|
|
|
|
|
|
|
def start_app(shift_id, mode, date): |
|
|
try: |
|
|
config_aux = {'date': date, |
|
|
'shift_id': shift_id, |
|
|
'mode': mode, |
|
|
'possible_shifts': {'No shifts': 0}, |
|
|
'possible_modes': ["waste"]} |
|
|
config.update(config_aux) |
|
|
gr.Info('Loading models. This may take a while') |
|
|
status_code, r = upload_models(**config) |
|
|
if status_code in (201, 200, 204): |
|
|
config.update(r) |
|
|
gr.Info('Models Correctly Loaded. Ready to predict') |
|
|
tab_id = 1 |
|
|
else: |
|
|
raise gr.Error(f'Error loading the models: {r}') |
|
|
except Exception as e: |
|
|
raise gr.Error(f'Error Uploading the models. \n {e}') |
|
|
return gr.Tabs(selected=tab_id, visible=True) |
|
|
|
|
|
|
|
|
def predict_app(image, patient_id=None): |
|
|
gr.Info('Predicting ...') |
|
|
buffered = BytesIO() |
|
|
image.save(buffered, format='JPEG') |
|
|
b64image = base64.b64encode(buffered.getvalue()).decode('utf-8') |
|
|
status_code, r = predict(b64image=b64image, |
|
|
patient_identifier=patient_id, |
|
|
**config) |
|
|
if status_code in (200, 201, 204): |
|
|
gr.Info('Prediction Successful') |
|
|
else: |
|
|
raise gr.Error(f'Error predicting {r}') |
|
|
|
|
|
|
|
|
|
|
|
with (gr.Blocks(head=prefer_frontal_cam_html, css=css_image_aspect_ratio) as block): |
|
|
with gr.Tabs() as tabs: |
|
|
with gr.Tab(label='Welcome', id=0) as welcome_tab: |
|
|
gr.Info('Loading ...') |
|
|
|
|
|
|
|
|
@gr.render() |
|
|
def header(): |
|
|
gr.Markdown(f'# User: {config.get("restaurant_name", "Proppos")}', render=True) |
|
|
|
|
|
|
|
|
@gr.render() |
|
|
def render_dropdowns(): |
|
|
shift_dropdown = gr.Dropdown(label='Meal/Apat/Comida', |
|
|
value=list(config["possible_shifts"].items())[0], |
|
|
choices=tuple(config["possible_shifts"].items())) |
|
|
mode_dropdown = gr.Dropdown(label='Mode', |
|
|
value=config['possible_modes'][0], |
|
|
choices=config["possible_modes"]) |
|
|
|
|
|
days = [datetime.today().strftime('%Y-%m-%d'), |
|
|
(datetime.now() - timedelta(days=1)).strftime('%Y-%m-%d')] |
|
|
date_chooser = gr.Dropdown(choices=days, label='Date/Data/Fecha', value=days[0]) |
|
|
|
|
|
start_button = gr.Button(value='START ▶️') |
|
|
start_button.click(fn=start_app, inputs=[shift_dropdown, mode_dropdown, date_chooser], outputs=tabs) |
|
|
|
|
|
|
|
|
gr.Markdown(""" * Do you have any doubt? Please, see the documentation tab. \n |
|
|
* Tienes alguna duda? Consulta la pestaña de documentación |
|
|
* Tens un dubte? Consulta la pestanya de documentació. """) |
|
|
|
|
|
logout_button = gr.Button(link='/logout', value='Logout / Exit ↩', size='sm') |
|
|
|
|
|
with gr.Tab(label='📷 Capture', id=1): |
|
|
|
|
|
gr.Markdown(f""" 1. Click to Access Webcam |
|
|
2. Press the red button to start recording |
|
|
3. Place the tray so it is centered in the displayed image and |
|
|
4. Press the grey button 'PRESS TO PREDICT' |
|
|
""") |
|
|
im = gr.Image(sources=['webcam'], |
|
|
mirror_webcam=False, |
|
|
type='pil', |
|
|
show_share_button=False, |
|
|
show_download_button=False, |
|
|
height='720px', width='1280px', min_width=0, |
|
|
elem_id="image-container") |
|
|
|
|
|
|
|
|
|
|
|
with gr.Accordion(open=False): |
|
|
def get_barcode_from_image(image): |
|
|
if not image: |
|
|
raise gr.Error('No image has been taken yet') |
|
|
d = decode(image) |
|
|
if not d: |
|
|
raise gr.Error('Cannot find a barcode on the Image') |
|
|
barcode = d[0].data.decode('utf8') if d else None |
|
|
return barcode |
|
|
get_barcode_button = gr.Button('Get Patient ID (Barcode) from Image') |
|
|
eater_id = gr.Textbox(label='Patient ID', interactive=True, value=None, |
|
|
placeholder='Write the patient id or take a photo') |
|
|
get_barcode_button.click(fn=get_barcode_from_image, inputs=[im], outputs=eater_id) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
b = gr.Button('PRESS TO PREDICT') |
|
|
b.click(fn=predict_app, inputs=[im, eater_id], outputs=gr.Info()) |
|
|
clear = gr.Button('Clear Image') |
|
|
clear.click(fn=lambda: None, outputs=im) |
|
|
|
|
|
with gr.Tab(label='ℹ️ Status', id=2): |
|
|
gr.Markdown(' Press the button to see the status of the Application and technical information') |
|
|
load_status_button = gr.Button('Load Status') |
|
|
status_json = gr.Json(label='Status') |
|
|
load_status_button.click(fn=lambda: config, outputs=status_json) |
|
|
|
|
|
with gr.Tab(label='📄 Documentation', id=3): |
|
|
choices = [('ENG 🇬🇧', docu_eng), ('CAT', docu_cat)] |
|
|
c = gr.Radio(label='Select the language', choices=choices) |
|
|
|
|
|
|
|
|
@gr.render() |
|
|
def display_docu(): |
|
|
d = gr.Markdown(docu_eng) |
|
|
c.change(fn=lambda x: x, inputs=c, outputs=d) |
|
|
|
|
|
|
|
|
block.launch(show_api=False, auth=login) |
|
|
|