Sentinel-2 OptimizedUrban Density

UI Processor

El Índice Urbano (UI) permite detectar la densidad de las edificaciones urbanas mediante la respuesta térmica y de reflectancia.

Fundamentos Técnicos

Sentinel-2 Core

Similar al NDBI pero utilizando el SWIR-2 (B12). Valores más altos indican áreas de edificación más densas y compactas.

Banda Requerida 1

B12 (SWIR-2)

Longitud de onda central: 2190nm.

Banda Requerida 2

B08 (NIR)

Resolución: 10m.

Fórmula Matemática
UI = (SWIR2 - NIR) / (SWIR2 + NIR)

Interpretación de Densidad

Métricas de Edificación

> 0.3Densidad urbana alta (Centros metropolitanos)
0.1 a 0.3Densidad media (Zonas residenciales)
-0.1 a 0.1Áreas periurbanas o industriales
< -0.1Áreas no construidas / Rurales

Diferencia con NDBI

UI vs NDBI

Aunque ambos índices se utilizan para identificar áreas construidas, la diferencia fundamental radica en la banda del Infrarrojo de Onda Corta (SWIR) que utilizan:

NDBI (B11 / SWIR-1)

Ideal para mapeo general de áreas urbanas y superficies impermeables. Es muy efectivo para distinguir zonas construidas de vegetación densa.

UI (B12 / SWIR-2)

Más sensible a la reflectancia del concreto y asfalto en núcleos urbanos densos. Al usar una longitud de onda más larga (2190nm), reduce la confusión con suelos desnudos brillantes.

"En términos prácticos, el **UI** es la herramienta preferida para análisis de micro-densidad urbana, mientras que el **NDBI** es el estándar para la clasificación macro de áreas urbanas vs rurales."

Implementación

Python SDK / LayerProcessor

El procesador UI ofrece una resolución espectral superior para el análisis de núcleos urbanos compactos:

class UIProcessor(LayerProcessor):
    """
    Urban Index (UI).
    UI = (SWIR2 - NIR) / (SWIR2 + NIR) -> (B12 - B08)
    Used to detect urban density. Higher values indicate
    denser building areas.
    """
    @property
    def name(self) -> str:
        return "ui"

    @property
    def required_bands(self) -> list[str]:
        return ["B12", "B08"]

    def calculate(self, bands_data: dict) -> np.ndarray:
        swir2 = bands_data["B12"]
        nir = bands_data["B08"]

        np.seterr(divide='ignore', invalid='ignore')
        ui = (swir2 - nir) / (swir2 + nir)
        return ui