| 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) |
|
|