| import gradio as gr |
| import numpy as np |
| from PIL import Image |
| import tensorflow as tf |
| from transformers import pipeline |
|
|
| |
| |
| |
| model = tf.keras.models.load_model("modelo_derm_real.h5") |
|
|
| clases = ["carcinoma", "fibroma", "melanoma", "nevo", "precancer", "queratosis", "vascular"] |
|
|
| map_clinico = { |
| "carcinoma": "Carcinoma basocelular", |
| "fibroma": "Fibroma", |
| "melanoma": "Melanoma", |
| "nevo": "Nevo benigno", |
| "precancer": "Lesión precancerosa", |
| "queratosis": "Queratosis", |
| "vascular": "Lesión vascular" |
| } |
|
|
| |
| |
| |
| hf_model = pipeline("image-classification", model="nateraw/vit-base-beans") |
|
|
| |
| |
| |
| def analizar_abcde(image): |
| img = np.array(image) |
|
|
| |
| h, w, _ = img.shape |
| izquierda = img[:, :w//2] |
| derecha = np.fliplr(img[:, w//2:]) |
| min_w = min(izquierda.shape[1], derecha.shape[1]) |
| asimetria = np.mean(np.abs(izquierda[:, :min_w] - derecha[:, :min_w])) |
|
|
| |
| bordes = np.std(img) |
|
|
| |
| color_var = np.std(img) |
|
|
| |
| diametro = max(h, w) |
|
|
| score = 0 |
|
|
| if asimetria > 20: |
| score += 1 |
| if bordes > 40: |
| score += 1 |
| if color_var > 50: |
| score += 1 |
| if diametro > 300: |
| score += 1 |
|
|
| return score |
|
|
| |
| |
| |
| def predict(image): |
| try: |
| image = image.convert("RGB") |
|
|
| |
| img = image.resize((224, 224)) |
| arr = np.array(img)/255.0 |
| arr = np.expand_dims(arr, axis=0) |
|
|
| pred = model.predict(arr, verbose=0)[0] |
| idx = np.argmax(pred) |
| confianza = float(pred[idx]) * 100 |
| dx = clases[idx] |
| dx_clinico = map_clinico[dx] |
|
|
| |
| score_abcde = analizar_abcde(image) |
|
|
| |
| hf = hf_model(image) |
| hf_conf = hf[0]["score"] * 100 |
|
|
| |
| |
| |
| if score_abcde >= 3: |
| diagnostico = "Sospechoso de malignidad" |
| riesgo = "🔴 ALTO" |
| elif score_abcde == 2: |
| diagnostico = dx_clinico |
| riesgo = "🟠 MODERADO" |
| else: |
| diagnostico = "Nevo benigno" |
| riesgo = "🟢 BAJO" |
|
|
| |
| if dx_clinico in ["Melanoma", "Carcinoma basocelular"] and score_abcde < 3: |
| diagnostico = "Nevo benigno" |
| riesgo = "🟢 BAJO" |
|
|
| return f""" |
| 🏥 INFORME DERM-IA PRO |
| |
| Diagnóstico: {diagnostico} |
| Confianza modelo: {round(confianza,2)}% |
| IA base: {round(hf_conf,2)}% |
| |
| ABCDE score: {score_abcde}/4 |
| Riesgo: {riesgo} |
| |
| 🩺 Conducta: |
| - 🔴 Biopsia urgente |
| - 🟠 Dermatoscopia |
| - 🟢 Seguimiento |
| |
| ⚠ Apoyo clínico. |
| """ |
|
|
| except Exception as e: |
| return f"❌ ERROR:\n{str(e)}" |
|
|
|
|
| |
| |
| |
| with gr.Blocks(theme=gr.themes.Soft()) as demo: |
| gr.Markdown("# 🧠 Derm-IA Clínico PRO") |
| gr.Markdown("### IA dermatológica (estable + sin errores)") |
|
|
| with gr.Row(): |
| img = gr.Image(type="pil") |
| out = gr.Textbox(lines=15) |
|
|
| btn = gr.Button("🔍 Analizar") |
| btn.click(fn=predict, inputs=img, outputs=out) |
|
|
| demo.launch() |