import streamlit as st import tensorflow as tf from huggingface_hub import login from tensorflow.keras.models import load_model from transformers import AutoConfig, AutoModel, pipeline, Dinov2Model#, AutoProcessor, AutoModelForZeroShotImageClassification from PIL import Image import os import torch import cv2 import numpy as np import requests token = os.environ['token'] #login(token = st.secrets["HF_TOKEN"], new_session = False) st.set_page_config( page_title = 'Patacotrón', layout = 'wide', menu_items = { "About" : 'Proyecto ideado para la investigación de "Clasificación de imágenes de una sola clase con algortimos de Inteligencia Artificial".', "Report a Bug" : 'https://docs.google.com/forms/d/e/1FAIpQLScH0ZxAV8aSqs7TPYi86u0nkxvQG3iuHCStWNB-BoQnSW2V0g/viewform?usp=sf_link' } ) st.sidebar.write("contact@patacotron.tech") already_excuted = False cnn, vit, zero_shot, classic_ml = st.tabs(["CNN", "ViT", "Zero-Shot", "Machine Learning Clásico"]) def predict(_model_list, _weights, _img): y_gorrito = 0 raw_img = cv2.cvtColor(_img, cv2.COLOR_BGR2RGB) img = cv2.resize(_img, (IMAGE_WIDTH, IMAGE_HEIGHT)) for model, weight in zip(_model_list, _weights): y_gorrito += tf.cast(model(tf.expand_dims(img/255., 0)), dtype=tf.float32)*weight return [y_gorrito / sum(_weights), raw_img] def preprocess(file_uploader, module = 'cv2'): #makes the uploaded image readable img = np.frombuffer(uploaded_file.read(), np.uint8) if module == 'cv2': img = cv2.imdecode(img, cv2.IMREAD_COLOR) elif module == 'pil': img = Image.open(file_uploader) return img def multiclass_prediction(classifier, important_class): #made for hf zero-shot pipeline results score = (max([classifier[i]['score'] for i in range(len(classifier))])) labels = [predict['label'] for predict in classifier if score == predict['score']] for clase in classifier: if clase['label'] == important_class: class_score = clase['score'] return (labels[0] if len(labels) == 1 else labels, score, class_score) API_URL = "https://api-inference.huggingface.co/models" headers = {"Authorization": f"Bearer {st.secrets['token']}"} def query(data, models): #HF API response = requests.post(API_URL + "/" + model_name, headers=headers, data=data) if response.json()["error"] == "Internal Server Error": return -1 while "error" in response.json(): response = requests.post(API_URL + "/" + model_name, headers=headers, data=data) return response.json()[1]["score"] #.json @st.cache_resource def load_clip(): #processor = AutoProcessor.from_pretrained("openai/clip-vit-large-patch14-336") #model = AutoModelForZeroShotImageClassification.from_pretrained("openai/clip-vit-large-patch14-336") classifier = pipeline("zero-shot-image-classification", model = 'openai/clip-vit-large-patch14-336') return classifier with cnn: col_a, col_b, = st.columns(2) ultra_flag = None with col_a: st.title("Redes neuronales convolucionales") st.caption("Los modelos no están en orden de eficacia, sino en orden de creación.") current_dir = os.getcwd() root_dir = os.path.dirname(current_dir) # Join the path to the models folder DIR = os.path.join(current_dir, "models") models = os.listdir(DIR) common_root = r"/home/user/app/models/ptctrn_v" common_end = ".h5" model_dict = dict() for model in models: #preprocessing of strings so the name is readable in the multiselect bar model_dir = os.path.join(DIR, model) model_name = 'Patacotrón ' + model_dir.split(common_root)[-1].split(common_end)[0] model_dict[model_name] = model_dir #ultraversions = ['Patacotrón 1.5', 'Patacotrón 1.7', 'Patacotrón 1.8', 'Patacotrón 1.12', 'Patacotrón 1.12.2', 'Patacotrón 1.12.3'] #ultraversions = ['Patacotrón 1.5', 'Patacotrón 1.6', 'Patacotrón 1.12.2', 'Patacotrón 1.8', 'Patacotrón 1.12']#, 'Patacotrón 1.13.20', 'Patacotrón 1.13.38'] #['Patacotrón 1.5', 'Patacotrón 1.6', 'Patacotrón 1.7', 'Patacotrón 1.12'] # #ultra_button = st.checkbox('Ultra-Patacotrón (en construcción, no es la mejor versión)') #ultra_flag = False weight_list = [] #if ultra_button: # ultra_flag = True #weight_list = [3, 1, 4.5, 1, .8, 1] [.5, 1.75, 4, .5, 2] # weight_list = [2.5, 1.8, 1.5, 3.14, 2.2] #.2, 2] #[1, 2, 3, 2.5] # st.caption('Para Ultra-Patacotrón, este porcentaje no representa una a priori una probabilidad, sino la combinación ponderada de modelos con sesgos positivos y negativos, lo importante es que identifique correctamente el objeto.') # Create a dropdown menu to select the model model_choice = st.multiselect("Seleccione uno o varios modelos de clasificación", model_dict.keys()) threshold = st.slider('¿Cuál va a ser el límite donde se considere patacón? (el valor recomendado es de 75%-80%)', 0, 100, 50, key = 'threshold_convnet') selected_models = [] # Set the image dimensions IMAGE_WIDTH = IMAGE_HEIGHT = 224 executed = False with col_b: uploaded_file = st.file_uploader(key = 'conv_upload', label = 'Sube la imagen a clasificar',type= ['jpg','png', 'jpeg', 'jfif', 'webp', 'heic']) if st.button(key = 'convnet_button', label ='¿Hay un patacón en la imagen?'): if len(model_choice) < 1: #if (len(model_choice) > 0 and ultra_flag) or (len(model_choice) == 0 and ultra_flag is None): st.write('Debe elegir como mínimo un modelo.') elif uploaded_file is not None: img = preprocess(uploaded_file) #if ultra_flag: # with st.spinner('Cargando ultra-predicción...'): # if not executed: # ultraptctrn = [load_model(model_dict[model]) for model in ultraversions] # executed = True # final_weights = weight_list if len(weight_list) >= 1 else [1 for i in range(len(ultraptctrn))] # y_gorrito, raw_img = predict(ultraptctrn, final_weights, img) #else: with st.spinner('Cargando predicción...'): selected_models = [load_model(model_dict[model_name]) for model_name in model_choice if model_name not in selected_models] final_weights = weight_list if len(weight_list) >= 1 else [1 for i in range(len(selected_models))] y_gorrito, raw_img = predict(selected_models, final_weights, img) if round(float(y_gorrito*100)) >= threshold: st.success("¡Patacón Detectado!") else: st.error("No se considera que haya un patacón en la imagen") st.caption(f'La probabilidad de que la imagen tenga un patacón es del: {round(float(y_gorrito * 100), 2)}%') st.caption('Si los resultados no fueron los esperados, por favor, [haz click aquí](https://docs.google.com/forms/d/e/1FAIpQLScH0ZxAV8aSqs7TPYi86u0nkxvQG3iuHCStWNB-BoQnSW2V0g/viewform?usp=sf_link)') st.image(raw_img) else: st.write('Revisa haber seleccionado los modelos y la imagen correctamente.') with vit: col_a, col_b = st.columns(2) with col_a: st.title('Visual Transformers') st.caption('One class is all you need!') model_dict = { 'google/vit-base-patch16-224-in21k' : 'frncscp/patacoptimus-prime', 'facebook/dinov2-base' : 'frncscp/dinotron', 'facebook/convnext-large-224' : 'frncscp/pataconxt', 'microsoft/focalnet-small' : 'frncscp/focalnet-small-patacon', 'microsoft/swin-tiny-patch4-window7-224' : 'frncscp/patacoswin' } model_choice = st.multiselect("Seleccione un modelo de clasificación", model_dict.keys(), key = 'ViT_multiselect') uploaded_file = st.file_uploader(key = 'ViT_upload', label = 'Sube la imagen a clasificar',type= ['jpg','png', 'jpeg', 'jfif', 'webp', 'heic']) flag = False threshold = st.slider('¿Cuál va a ser el límite desde donde se considere patacón? (se recomienda por encima del 80%)', 0, 100, 80, key = 'threshold_vit') with col_b: if st.button(key = 'ViT_button', label ='¿Hay un patacón en la imagen?'): if len(model_choice) < 1: print('Recuerda seleccionar al menos un modelo de clasificación') elif uploaded_file is not None: with st.spinner('Cargando predicción...'): #y_gorritoo = query(uploaded_file.read(), model_dict[model_choice[0]]) #st.write(y_gorritoo) #if "facebook/dinov2-base" in model_choice: # #classifiers = [Dinov2Model.from_pretrained("frncscp/dinotron")] # classifiers = [pipeline("image-classification", model="frncscp/dinotron")] #else: classifiers = [pipeline("image-classification", model= model_dict[model_choice[i]], token = token) for i in range(len(model_choice))] #classifier = pipeline("image-classification", model= model_dict[model_choice[0]]) img = preprocess(uploaded_file, module = 'pil') models = [model_dict[model] for model in model_choice] #st.write(models) def vit_ensemble(classifier_list, img): y_gorrito = 0 for classifier in classifier_list: classifier = classifier(img) for clase in classifier: if clase['label'] == 'Patacon-True': y_gorrito += clase["score"] return y_gorrito / len(classifier_list) #models = [model_dict[i] for i in range(len(model_choice))] #st.write(type(models), models) #st.write(model_choice) #y_gorrito = 0 #y_gorritoo = query(uploaded_file.read(), model_choice[0])#[1]["score"] #i = -1 #st.write("loop iniciado") #for model in models: # i+=1 # st.write("y gorrito a cargar") # a = query(uploaded_file.read(), model) # if a == -1: # st.write("Los servidores se encuentrar caídos, intente más tarde") # st.write("query terminado") # y_gorritoo += a # st.write("y gorrito cargado") #y_gorritoo /= i #st.write(y_gorritoo) #st.write("loop terminado") #st.write("y gorrito calculado", len(model_choice)) #classifier = classifier(img) #for clase in classifier: # if clase['label'] == 'Patacon-True': # y_gorrito = clase["score"] #y_gorrito = classifier[0]["score"] y_gorrito = vit_ensemble(classifiers, img) # if round(float(y_gorrito * 100)) >= threshold: st.success("¡Patacón Detectado!") else: st.error("No se considera que haya un patacón en la imagen") st.caption(f'La probabilidad de que la imagen tenga un patacón es del: {round(float(y_gorrito * 100), 2)}%') st.image(img) else: st.write("Asegúrate de haber subido correctamente la imagen.") with zero_shot: col_a, col_b = st.columns(2) zsloaded = [] with col_a: st.title("Clasificación Zero-Shot") st.caption("Usando Clip de OpenAI") labels_for_classification = ["A yellow deep fried smashed plantain", "A yellow corn dough", "A stuffed fried dough", "Fried food", "Fruit", "Anything"] uploaded_file = st.file_uploader(key = 'ZS_upload', label = 'Sube la imagen a clasificar',type= ['jpg','png', 'jpeg', 'jfif', 'webp', 'heic']) with col_b: if st.button(key = 'ZS_button', label ='¿Hay un patacón en la imagen?'): if uploaded_file is not None: with st.spinner('Cargando el modelo (puede demorar hasta un minuto, pero después predice rápido)'): classifier = load_clip() with st.spinner('Cargando predicción...'): img = preprocess(uploaded_file, module = 'pil') zs_classifier = classifier(img, candidate_labels = labels_for_classification) label, _, y_gorrito = multiclass_prediction(zs_classifier, labels_for_classification[0]) if label == "A yellow deep fried smashed plantain": st.success("¡Patacón Detectado!") else: st.error("No se considera que haya un patacón en la imagen") st.caption(f'La probabilidad de que la imagen tenga un patacón es del: {round(float(y_gorrito * 100), 2)}%') st.image(img) else: st.write("Asegúrate de haber subido correctamente la imagen.") with classic_ml: st.write('Próximamente')