9.10.5 EP09_05 🟠 Evaluación de Segmentación: IoU y Dice Pixel a Pixel
El Bloque 2 de la sección “Segmentación Semántica con Arquitectura U-Net” define, en pocas líneas, la función iou_mascaras, utilizada para medir la calidad de la línea base morfológica clásica (suavizado + Otsu + apertura) y, más adelante, de la propia U-Net entrenada. A diferencia del IoU del EP09_04 — calculado sobre cajas delimitadoras (regiones rectangulares descritas por cuatro números) —, el IoU de segmentación se calcula pixel a pixel: cada posición de la imagen se compara individualmente entre la máscara predicha y la máscara de referencia.
Se le ha encargado generalizar esta evaluación, implementando no solo el IoU pixel a pixel, sino también el coeficiente de Dice, otra métrica de superposición ampliamente utilizada en segmentación médica (incluso en la función perda_dice, mencionada en el mismo bloque del capítulo como base de la función de pérdida utilizada para entrenar la U-Net).
9.10.5.1 📋 Directrices de Implementación
Entrada: Leer las dimensiones \(H \times W\) de las máscaras.
Máscara predicha: Leer \(H\) líneas con \(W\) valores enteros (0 o 1) cada una — por ejemplo, la salida de una U-Net después de la umbralización en \(0{,}5\) sobre la sigmoide, como en el Bloque 4 del capítulo.
Máscara de referencia: Leer otras \(H\) líneas con \(W\) valores enteros (0 o 1) cada una — el ground truth.
Intersección y unión: Considerando cada píxel como perteneciente al objeto cuando su valor es diferente de cero, \[ \text{intersección} = \sum_{i,j} \mathbb{1}[P_{ij}=1 \wedge R_{ij}=1], \qquad \text{unión} = \sum_{i,j} \mathbb{1}[P_{ij}=1 \vee R_{ij}=1]. \]
IoU pixel a pixel: \[ \text{IoU} = \frac{\text{intersección}}{\text{unión}}. \]
Coeficiente de Dice: \[ \text{Dice} = \frac{2 \cdot \text{intersección}}{|P| + |R|}, \] donde \(|P|\) y \(|R|\) son el número total de píxeles de objeto en cada máscara.
Convención para máscaras vacías: si ambas máscaras no poseen ningún píxel de objeto (unión \(= 0\) y \(|P|+|R|=0\)), considere la correspondencia trivialmente perfecta: \(\text{IoU} = \text{Dice} = 1{,}0\).
Salida: Dos líneas,
IoU: X.XXXXyDice: X.XXXX, cada valor con 4 decimales.
9.10.5.2 📌 Restricciones Computacionales
- Cualquier valor no nulo cuenta como objeto: trate valores diferentes de \(0\) (no solo \(1\)) como pertenecientes a la máscara, replicando la comprobación
predita > 0utilizada eniou_mascarasen el capítulo. - Mismas dimensiones: las dos máscaras siempre poseen exactamente \(H \times W\) elementos.
- Convención de vacío: aplique la regla del ítem 7 solo cuando ambas máscaras estén totalmente vacías; si solo una está vacía, la intersección es \(0\) y el IoU/Dice resultante también será \(0\).
9.10.5.3 🧠 Fundamentación Teórica
| Elemento | Papel en la evaluación de segmentación |
|---|---|
| IoU pixel a pixel | Generaliza la métrica del EP09_04 para regiones de forma arbitraria — no solo rectángulos — comparando máscara predicha y referencia posición a posición |
| Coeficiente de Dice | Métrica relacionada con el IoU (siempre \(\text{Dice} \ge \text{IoU}\)), más sensible a pequeñas intersecciones y ampliamente utilizada como función de pérdida en segmentación (función perda_dice del capítulo) |
| Convención de máscaras vacías | Evita la división por cero y reconoce que “ningún objeto previsto, ningún objeto real” es, por definición, un acierto |
| Comparación clásico vs. U-Net | El capítulo usa exactamente este tipo de métrica para justificar, numéricamente, por qué la U-Net supera la línea base morfológica en escenarios de bajo contraste |
9.10.5.4 🧩 Métodos del morph.py que pueden ayudar
mm.readImg(h, w, dtype='uint8')— lee directamente cada máscara binaria \(h \times w\) de la entrada estándar (los valores \(0/1\) caben perfectamente en el tipo entero estándar).- La propia función
iou_mascaras, definida en el Bloque 2 de la sección de U-Net del capítulo (no forma parte delmorph.py, sino del código del capítulo), es la inspiración directa de este ejercicio — vale la pena releer esas pocas líneas antes de programar. - Para una extensión opcional (no exigida por este EP),
mm.connectedComponentsomm.label0(vistos en el contexto de análisis de componentes conexos) permitirían etiquetar cada nódulo individualmente y calcular el IoU por componente, en lugar de sobre la máscara completa.
9.10.5.5 📦 Especificación de Entrada y Salida (VPL)
Entrada:
- Línea 1: Enteros \(H\) y \(W\).
- Siguientes \(H\) líneas: \(W\) valores enteros (0 o 1) — máscara predicha.
- Siguientes \(H\) líneas: \(W\) valores enteros (0 o 1) — máscara de referencia.
Salida:
- Línea 1:
IoU: X.XXXX. - Línea 2:
Dice: X.XXXX.
Considere una máscara predicha con un cuadrado \(2\times2\) de píxeles activos y una referencia desplazada en una columna, superponiéndose en solo la mitad del área:
Predicha Referencia
0 0 0 0 0 0 0 0
0 1 1 0 0 0 1 1
0 1 1 0 0 0 1 1
0 0 0 0 0 0 0 0
Intersección \(=2\) píxeles, unión \(=6\) píxeles (\(4+4-2\)), por lo tanto \(\text{IoU}=2/6\approx0{,}3333\) y \(\text{Dice}=2\cdot2/(4+4)=0{,}5000\) — observe que el Dice es siempre igual o mayor que el IoU para la misma superposición.
9.10.5.6 📌 Ejemplos
| Entrada | Salida | Observación |
|---|---|---|
| 4 4 0 0 0 0 0 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 1 0 0 0 0 |
IoU: 0.3333 Dice: 0.5000 |
Máscaras \(4\times4\) con superposición parcial de 2 píxeles. |
%%writefile EP09_05.py
# Código Python en españolOverwriting EP09_05.py
TestSuite("EP09_05.py").run()✔️ EP09_05.cases ya existe en casos/
📋 4 caso(s) cargado(s) de casos/EP09_05.cases
🔍 Probando Python: EP09_05.py
⚠️ EP09_05.py: archivo vacío (menos de 3 líneas). Pruebas omitidas.