Derm-AI / app.py
Jedav's picture
Update app.py
8d96067 verified
import gradio as gr
import numpy as np
from PIL import Image
import tensorflow as tf
from transformers import pipeline
# =========================
# 🔥 MODELO LOCAL
# =========================
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"
}
# =========================
# 🔥 MODELO LIGERO (fallback)
# =========================
hf_model = pipeline("image-classification", model="nateraw/vit-base-beans")
# =========================
# 🧠 ABCDE SIN OPENCV
# =========================
def analizar_abcde(image):
img = np.array(image)
# A: Asimetría
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]))
# B: Bordes (simple)
bordes = np.std(img)
# C: Color
color_var = np.std(img)
# D: Tamaño relativo
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
# =========================
# 🔥 PREDICCIÓN
# =========================
def predict(image):
try:
image = image.convert("RGB")
# ===== MODELO LOCAL =====
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]
# ===== ABCDE =====
score_abcde = analizar_abcde(image)
# ===== HF fallback =====
hf = hf_model(image)
hf_conf = hf[0]["score"] * 100
# =========================
# 🧠 LÓGICA CLÍNICA
# =========================
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"
# 🔥 ANTI FALSOS POSITIVOS
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)}"
# =========================
# 🎯 INTERFAZ
# =========================
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()