LoloSemper commited on
Commit
35bfd06
·
verified ·
1 Parent(s): 261a7ba

Upload 2 files

Browse files

AI-based skin cancer lesion classifier using a Vision Transformer (ViT) model fine-tuned on the HAM10000 dataset. Upload a dermatological image and receive a detailed risk report with probabilities for 7 common lesion types. For educational and research use only.

Files changed (2) hide show
  1. main.py +160 -0
  2. requirements.txt +6 -0
main.py ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from transformers import ViTFeatureExtractor, ViTForImageClassification
3
+ from PIL import Image
4
+ import matplotlib.pyplot as plt
5
+ import numpy as np
6
+ import gradio as gr
7
+ import io
8
+ import base64
9
+
10
+ MODEL_NAME = "ahishamm/vit-base-HAM-10000-sharpened-patch-32"
11
+ feature_extractor = ViTFeatureExtractor.from_pretrained(MODEL_NAME)
12
+ model = ViTForImageClassification.from_pretrained(MODEL_NAME)
13
+ model.eval()
14
+
15
+ CLASSES = [
16
+ "Queratosis actínica / Bowen", # 0
17
+ "Carcinoma células basales", # 1
18
+ "Lesión queratósica benigna", # 2
19
+ "Dermatofibroma", # 3
20
+ "Melanoma maligno", # 4
21
+ "Nevus melanocítico", # 5
22
+ "Lesión vascular" # 6
23
+ ]
24
+ RISK_LEVELS = {
25
+ 0: {'level': 'Moderado', 'color': '#ffaa00', 'weight': 0.6},
26
+ 1: {'level': 'Alto', 'color': '#ff4444', 'weight': 0.8},
27
+ 2: {'level': 'Bajo', 'color': '#44ff44', 'weight': 0.1},
28
+ 3: {'level': 'Bajo', 'color': '#44ff44', 'weight': 0.1},
29
+ 4: {'level': 'Crítico', 'color': '#cc0000', 'weight': 1.0},
30
+ 5: {'level': 'Bajo', 'color': '#44ff44', 'weight': 0.1},
31
+ 6: {'level': 'Bajo', 'color': '#44ff44', 'weight': 0.1}
32
+ }
33
+
34
+ def analizar_lesion_vit_web(img):
35
+ inputs = feature_extractor(img, return_tensors="pt")
36
+ with torch.no_grad():
37
+ outputs = model(**inputs)
38
+ probs = outputs.logits.softmax(dim=-1).cpu().numpy()[0]
39
+ pred_idx = int(np.argmax(probs))
40
+ pred_clase = CLASSES[pred_idx]
41
+ confianza = probs[pred_idx]
42
+ cancer_risk_score = sum(probs[i] * RISK_LEVELS[i]['weight'] for i in range(7))
43
+ melanoma_risk = probs[4]
44
+ bcc_risk = probs[1]
45
+ precancer_risk = probs[0]
46
+ benign_total = sum(probs[i] for i in [2,3,5,6])
47
+
48
+ colors_bars = [RISK_LEVELS[i]['color'] for i in range(7)]
49
+ fig, ax = plt.subplots(figsize=(8,3))
50
+ ax.bar(CLASSES, probs*100, color=colors_bars)
51
+ ax.set_title("Probabilidad por tipo de lesión")
52
+ ax.set_ylabel("Probabilidad (%)")
53
+ ax.set_xticklabels(CLASSES, rotation=45, ha='right')
54
+ ax.grid(axis='y', alpha=0.2)
55
+ plt.tight_layout()
56
+ buf = io.BytesIO()
57
+ plt.savefig(buf, format="png")
58
+ plt.close(fig)
59
+ buf.seek(0)
60
+ img_bytes = buf.getvalue()
61
+ img_b64 = base64.b64encode(img_bytes).decode("utf-8")
62
+ html_chart = f'<img src="data:image/png;base64,{img_b64}" style="max-width:100%"/>'
63
+
64
+ urgency = ""
65
+ recommendation = ""
66
+ timeframe = ""
67
+ if cancer_risk_score > 0.6:
68
+ urgency = "🚨 <b>CRÍTICO</b>"
69
+ recommendation = "Derivación INMEDIATA a oncología dermatológica"
70
+ timeframe = "En 24-48 horas máximo"
71
+ elif cancer_risk_score > 0.4:
72
+ urgency = "⚠️ <b>ALTO RIESGO</b>"
73
+ recommendation = "Consulta urgente con dermatólogo especialista"
74
+ timeframe = "En 1 semana máximo"
75
+ elif cancer_risk_score > 0.2:
76
+ urgency = "📋 <b>RIESGO MODERADO</b>"
77
+ recommendation = "Evaluación dermatológica programada"
78
+ timeframe = "En 2-4 semanas"
79
+ else:
80
+ urgency = "✅ <b>BAJO RIESGO</b>"
81
+ recommendation = "Seguimiento de rutina"
82
+ timeframe = "En 3-6 meses"
83
+
84
+ informe = f"""
85
+ <div style="font-family:sans-serif; max-width:700px; margin:auto">
86
+ <h2>🏥 INFORME DE ANÁLISIS DERMATOLÓGICO CON IA</h2>
87
+ <b>📊 Diagnóstico principal:</b> {pred_clase}<br>
88
+ <b>🎯 Confianza del modelo:</b> {confianza:.1%}<br>
89
+ <b>📈 Score de riesgo oncológico:</b> {cancer_risk_score:.1%}<br>
90
+ <br>
91
+ <b>⚠️ Análisis de riesgo detallado:</b><br>
92
+ &emsp;🔴 Melanoma maligno: {melanoma_risk:.1%}<br>
93
+ &emsp;🟠 Carcinoma células basales: {bcc_risk:.1%}<br>
94
+ &emsp;🟡 Lesión pre-cancerosa: {precancer_risk:.1%}<br>
95
+ &emsp;🟢 Lesiones benignas: {benign_total:.1%}<br>
96
+ <br>
97
+ <b>🩺 Evaluación clínica:</b><br>
98
+ &emsp;{urgency}<br>
99
+ &emsp;💡 Recomendación: {recommendation}<br>
100
+ &emsp;⏰ Plazo: {timeframe}<br>
101
+ <br>
102
+ <b>🔍 Características analizadas:</b><br>
103
+ """
104
+ if melanoma_risk > 0.3:
105
+ informe += "• ⚠️ Posibles irregularidades sugestivas de melanoma<br>• 🔍 Asimetría o variación de color detectada<br>"
106
+ if bcc_risk > 0.25:
107
+ informe += "• 🔍 Características compatibles con carcinoma basocelular<br>"
108
+ if precancer_risk > 0.25:
109
+ informe += "• 🔍 Posible queratosis actínica (lesión pre-maligna)<br>"
110
+ if benign_total > 0.6:
111
+ informe += "• ✅ Características predominantemente benignas<br>"
112
+
113
+ informe += "<br><b>📊 Diagnósticos diferenciales (ordenados por probabilidad):</b><ul>"
114
+ sorted_indices = np.argsort(probs)[::-1]
115
+ for i, idx in enumerate(sorted_indices):
116
+ marker = "🎯" if i==0 else f"{i+1}."
117
+ prob_bars = int(probs[idx] * 30)
118
+ bar_visual = "█" * prob_bars + "░" * (30 - prob_bars)
119
+ risk_indicator = ("🔴" if idx in [1,4] else "🟡" if idx==0 else "🟢")
120
+ informe += f"<li>{marker} {risk_indicator} {CLASSES[idx]} — {probs[idx]:.1%} <code>{bar_visual}</code></li>"
121
+ informe += "</ul>"
122
+
123
+ informe += """
124
+ <br>
125
+ <b>📋 Información técnica:</b><br>
126
+ • Modelo: ViT-Base (HAM10000, sharpened)<br>
127
+ • Precisión validada: 83.7%<br>
128
+ • Preprocesamiento: Optimizado para dermatoscopia<br>
129
+ • Clases detectadas: 7 tipos de lesiones cutáneas<br>
130
+ <br>
131
+ <b>📝 Notas clínicas:</b><br>
132
+ """
133
+ if confianza < 0.7:
134
+ informe += "• ⚠️ Confianza moderada - considerar segunda opinión<br>"
135
+ if cancer_risk_score > 0.3:
136
+ informe += "• 🩺 Documentar evolución con fotografías seriadas<br>"
137
+ informe += "• 📏 Regla ABCDE: Evaluar Asimetría, Bordes, Color, Diámetro, Evolución<br>"
138
+
139
+ informe += """
140
+ <br><hr>
141
+ <b>⚕️ ADVERTENCIA MÉDICA</b><br>
142
+ • Este análisis es una HERRAMIENTA DE APOYO diagnóstico.<br>
143
+ • NO sustituye la evaluación clínica de un dermatólogo.<br>
144
+ • Ante cualquier duda, consulte con un profesional médico.<br>
145
+ • La decisión terapéutica final corresponde al médico tratante.<br>
146
+ </div>
147
+ """
148
+ return informe, html_chart
149
+
150
+ demo = gr.Interface(
151
+ fn=analizar_lesion_vit_web,
152
+ inputs=gr.Image(type="pil", label="Sube una imagen de la lesión"),
153
+ outputs=[gr.HTML(label="Informe detallado"), gr.HTML(label="Gráfico de barras")],
154
+ title="Detector de Cáncer de Piel IA (HAM10000, ViT)",
155
+ description="Sube una imagen dermatológica y obtén un informe detallado generado por IA (ViT-HAM10000, accuracy ~83.7%)",
156
+ flagging_mode="never"
157
+ )
158
+
159
+ if __name__ == "__main__":
160
+ demo.launch()
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ torch
2
+ transformers
3
+ pillow
4
+ matplotlib
5
+ numpy
6
+ gradio