Spaces:
Sleeping
Sleeping
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}') | |
# APP | |
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 ...') | |
def header(): | |
gr.Markdown(f'# User: {config.get("restaurant_name", "Proppos")}', render=True) | |
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): | |
# MAIN TAB TO PREDICT | |
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") | |
## Patient ID searcher. | |
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) | |
## Patient ID searcher. Uncomment if needed | |
# with gr.Accordion(open=False): | |
# eater_id = gr.Textbox(label='Patient Identification', placeholder='Searching Patient ID') | |
# | |
# current_eater_id = {'value': None} | |
# @gr.on(inputs=im, outputs=eater_id) | |
# def search_eater_id(image): | |
# d = []#decode(image) | |
# default_value = None | |
# current_value = current_eater_id['value'] or default_value | |
# new_value = d[0].data if d else default_value | |
# # If it is really a new value different from the default one, change it. | |
# final_value = new_value if new_value != default_value else current_value | |
# current_eater_id['value'] = final_value | |
# return final_value | |
# eater_id = None | |
b = gr.Button('PRESS TO PREDICT') | |
b.click(fn=predict_app, inputs=[im, eater_id], outputs=gr.Info()) # add eater id to input if needed | |
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) | |
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) | |