EstevezAlvarez
QGIS Segmentación Geoinformación PostGIS

Segmentación de datos espaciales: conceptos y aplicación

Segmentar no es lo mismo que clasificar. La segmentación agrupa píxeles en objetos coherentes antes de asignarles una etiqueta, produciendo resultados más limpios y analizables. Esta guía cubre los conceptos, los algoritmos y su aplicación en QGIS y PostGIS.

Imagen raster (píxeles individuales) segmentar Segmentos (objetos) (regiones homogéneas) Vegetación Urbano Agua Suelo desnudo cada píxel tratado por separado objetos con atributos estadísticos
La segmentación agrupa píxeles espectralmente similares y espacialmente contiguos en objetos coherentes, pasando del análisis píxel a píxel al análisis orientado a objetos.

¿Qué es segmentar y por qué importa?

En análisis raster tradicional, cada píxel se clasifica de forma independiente. Esto produce resultados con «sal y pimienta»: píxeles aislados mal clasificados en medio de una región homogénea. La segmentación resuelve esto agrupando primero los píxeles en segmentos — regiones contiguas y espectralmente similares — y luego trabajando con esos objetos.

La diferencia es conceptual: en lugar de clasificar «este píxel es bosque», clasificas «este objeto de 2.3 ha con NDVI medio 0.72 y forma compacta es bosque denso». Los objetos resultantes son vectorizables, tienen atributos estadísticos (media, desviación, forma) y son mucho más útiles para análisis territorial.

Segmentación de imagen vs. segmentación de datos tabulares

El término segmentación aparece en dos contextos distintos en datos espaciales:

Imagen GeoTIFF multibanda Segmentación MeanShift SLIC / FELZ Atributos media, std, área forma, NDVI Clasificación por objeto RF / SVM Vectorizar polígonos GeoPackage PostGIS análisis espacial exportar, reportar
Pipeline OBIA (Object-Based Image Analysis): segmentación → extracción de atributos → clasificación por objeto → vectorización → carga en PostGIS.

Algoritmos comunes

Segmentación en QGIS con Orfeo Toolbox

Orfeo Toolbox (OTB) es la suite de teledetección de CNES, integrable como proveedor de algoritmos en QGIS.

  1. Instala OTB desde otb.orfeo-toolbox.org y configura el proveedor en QGIS → Opciones → Proveedores → OTB.
  2. Ve a Procesos → Caja de herramientas → OTB → Segmentation → Segmentation (otb).
  3. Selecciona la imagen de entrada y el algoritmo (meanshift).
  4. Ajusta los parámetros: Spatial radius (radio espacial, px), Range radius (tolerancia espectral), Min region size (tamaño mínimo de segmento).
  5. El resultado es un raster de etiquetas donde cada valor entero identifica un segmento.

Segmentación con Python (rasterio + scikit-image)

import numpy as np
import rasterio
from rasterio.features import shapes
from skimage.segmentation import slic
from skimage.color import label2rgb
import geopandas as gpd
from shapely.geometry import shape

# Cargar imagen multibanda
with rasterio.open("imagen_sentinel.tif") as src:
    imagen = src.read()         # (bandas, filas, cols)
    transform = src.transform
    crs = src.crs

# Reordenar a (filas, cols, bandas) para scikit-image
img = np.moveaxis(imagen[:3], 0, -1).astype(float)
# Normalizar 0-1
img = (img - img.min()) / (img.max() - img.min())

# Segmentación SLIC
# n_segments: número aproximado de superpíxeles
# compactness: balance forma/espectro (mayor = más compacto)
segmentos = slic(img, n_segments=500, compactness=10, sigma=1, start_label=1)

print(f"Segmentos generados: {segmentos.max()}")

# Calcular estadísticas por segmento (media de cada banda)
from skimage.measure import regionprops_table
import pandas as pd

stats = regionprops_table(
    segmentos,
    intensity_image=img[:, :, 0],  # banda 1 (Rojo)
    properties=["label", "area", "mean_intensity", "bbox"]
)
df_stats = pd.DataFrame(stats)
print(df_stats.head())
# Vectorizar segmentos a polígonos GeoPackage
mask = segmentos.astype(np.int32)
poligonos = []
for geom, valor in shapes(mask, transform=transform):
    poligonos.append({"geometry": shape(geom), "seg_id": int(valor)})

gdf = gpd.GeoDataFrame(poligonos, crs=crs)

# Unir estadísticas
gdf = gdf.merge(df_stats.rename(columns={"label": "seg_id"}), on="seg_id", how="left")

# Guardar
gdf.to_file("segmentos.gpkg", driver="GPKG")
print(f"Guardados {len(gdf)} segmentos")

Segmentación vectorial con PostGIS

Para datos vectoriales (puntos de muestreo, parcelas, registros catastrales), PostGIS permite clusterizar por proximidad espacial con ST_ClusterDBSCAN o ST_ClusterKMeans:

-- Agrupar parcelas en clusters por proximidad (DBSCAN)
-- eps: distancia máxima en metros, minpoints: mínimo de vecinos
SELECT
    id_parcela,
    ST_ClusterDBSCAN(geom, eps := 100, minpoints := 5)
        OVER () AS cluster_id,
    geom
FROM parcelas
WHERE municipio = 'Sevilla';

-- Calcular área total y centroide por cluster
SELECT
    cluster_id,
    COUNT(*)                          AS n_parcelas,
    SUM(ST_Area(geom))                AS area_total_m2,
    ST_Centroid(ST_Collect(geom))     AS centroide
FROM (
    SELECT id_parcela, geom,
        ST_ClusterDBSCAN(geom, 100, 5) OVER () AS cluster_id
    FROM parcelas
    WHERE municipio = 'Sevilla'
) t
WHERE cluster_id IS NOT NULL
GROUP BY cluster_id
ORDER BY area_total_m2 DESC;

Cuándo usar cada enfoque