1. Introducción

Este cuaderno presenta un procedimiento para acceder y procesar imágenes satelitales de Sentinel-2 con el objetivo de calcular índices de vegetación para un área de estudio determinada.

Para la obtención de las imágenes se utilizarán herramientas basadas en STAC (SpatioTemporal Asset Catalog), un sistema que permite organizar y consultar información espacial y temporal de diferentes fuentes de datos satelitales.

La librería rstac facilita la búsqueda y descarga de imágenes mediante catálogos STAC, permitiendo seleccionar datos según ubicación geográfica, fecha de adquisición y características específicas de las imágenes.

La librería gdalcubes permite trabajar con colecciones de imágenes satelitales mediante estructuras de datos multidimensionales, facilitando el procesamiento de información espacial a través del tiempo.

En este cuaderno se utilizarán imágenes del satélite Sentinel-2, disponibles mediante el catálogo público de AWS (Amazon Web Services), las cuales serán utilizadas para analizar las características de la vegetación mediante índices espectrales.

Adicionalmente, se empleará la librería terra para la lectura y procesamiento de datos ráster, y tmap para la representación cartográfica de los resultados obtenidos.

2. Configuración del entorno

Antes de iniciar el procesamiento de las imágenes satelitales, es necesario preparar el entorno de trabajo mediante la instalación y carga de las librerías requeridas. Estas herramientas contienen funciones específicas para la consulta de datos satelitales, el procesamiento de imágenes ráster, el análisis espacial y la visualización de los resultados obtenidos.

2.1 Limpieza del entorno de trabajo

La función rm(list = ls()) permite eliminar todos los objetos almacenados en la memoria temporal de R. Esta práctica permite iniciar el análisis en un entorno limpio, evitando posibles conflictos con objetos generados durante sesiones anteriores.

rm(list=ls())

2.2 Instalación de librerías

Antes de iniciar el procesamiento de las imágenes satelitales, es necesario instalar las librerías que serán utilizadas durante el análisis. Estas librerías contienen funciones específicas para la consulta de imágenes Sentinel-2, procesamiento de datos espaciales, manejo de información ráster y visualización de resultados.

La instalación de los paquetes se realiza mediante la función install.packages(). Este procedimiento solo debe realizarse la primera vez que se utilizan estas herramientas en el equipo.

Se recomienda ejecutar estas instrucciones desde la consola de R y no directamente desde el cuaderno, para evitar problemas durante la ejecución del análisis.

# install.packages("rstac")
# install.packages("tidyterra")
# install.packages("gdalcubes")
# install.packages("stars")
# install.packages("mapview")
# install.packages("tmap")

Una vez instaladas las librerías, estas deben ser cargadas al entorno de trabajo mediante la función library(). Esta función permite activar los paquetes y utilizar las funciones que contienen durante el desarrollo del análisis.

library(rstac)
library(tidyterra)
library(gdalcubes)
library(stars)
library(mapview)
library(tmap)

3. Definición y lectura del área de interés (AOI)

El área de interés (AOI) corresponde al municipio de Riosucio, Chocó, seleccionado por presentar la mayor producción agrícola del departamento según las Evaluaciones Agropecuarias Municipales (UPRA, 2025).

La geometría del municipio fue almacenada en un archivo GeoJSON, el cual será utilizado para consultar y procesar las imágenes satelitales correspondientes al área de estudio.

3.1 Lectura del archivo GeoJSON

La función st_read() de la librería sf permite cargar archivos vectoriales en R como objetos espaciales para realizar análisis geográficos.

Antes de leer el archivo, se puede verificar su ubicación mediante la función list.files().

list.files("datos")
##  [1] "20250617_BaseAgricola20192024.xlsx"
##  [2] "Choco"                             
##  [3] "Chocó.gpkg"                        
##  [4] "choco_buffer.gpkg"                 
##  [5] "choco_ciudades.gpkg"               
##  [6] "choco_curvas_nivel.cpg"            
##  [7] "choco_curvas_nivel.dbf"            
##  [8] "choco_curvas_nivel.prj"            
##  [9] "choco_curvas_nivel.shp"            
## [10] "choco_curvas_nivel.shx"            
## [11] "choco_elevacion.tif"               
## [12] "choco_elevacion.tif.aux.xml"       
## [13] "choco_elevacion_z10.tif"           
## [14] "choco_municipios.gpkg"             
## [15] "choco_municipios_MAGMA.gpkg"       
## [16] "choco_municipios_UTM18N.gpkg"      
## [17] "choco_rangos_elevacion.cpg"        
## [18] "choco_rangos_elevacion.dbf"        
## [19] "choco_rangos_elevacion.prj"        
## [20] "choco_rangos_elevacion.shp"        
## [21] "choco_rangos_elevacion.shx"        
## [22] "choco_relieve.tif"                 
## [23] "choco_relieve.tif.aux.xml"         
## [24] "choco_relieve.txt"                 
## [25] "choco_rios.gpkg"                   
## [26] "choco_vias.gpkg"                   
## [27] "Ciudades de Colombia.gpkg"         
## [28] "Ciudades de Santander.gpkg"        
## [29] "Ciudades del mundo"                
## [30] "COL_adm"                           
## [31] "COL_adm2.cpg"                      
## [32] "COL_adm2.csv"                      
## [33] "COL_adm2.dbf"                      
## [34] "COL_adm2.prj"                      
## [35] "COL_adm2.shp"                      
## [36] "COL_adm2.shx"                      
## [37] "COL_alt_tif"                       
## [38] "COL_msk_alt_tif"                   
## [39] "COL_msk_cov_tif"                   
## [40] "COL_rds"                           
## [41] "COL_wat"                           
## [42] "Colombia"                          
## [43] "map.geojson"                       
## [44] "Santander"                         
## [45] "Tierra"

El archivo GeoJSON se carga mediante la función st_read():

riosucio <- sf::st_read("datos/map.geojson")
## Reading layer `map' from data source 
##   `D:\Geomatica Basica (Gr 2)\GB2\Proyecto2\datos\map.geojson' 
##   using driver `GeoJSON'
## Simple feature collection with 1 feature and 1 field
## Geometry type: POLYGON
## Dimension:     XY
## Bounding box:  xmin: -77.13902 ymin: 7.413948 xmax: -77.09111 ymax: 7.457553
## Geodetic CRS:  WGS 84

El resultado muestra la información espacial del archivo cargado, incluyendo el tipo de geometría y el sistema de coordenadas utilizado. En este caso se espera una geometría tipo POLYGON correspondiente al límite del municipio y un sistema de referencia geográfico WGS84.

4. Consulta de imágenes Sentinel-2

Las imágenes Sentinel-2 se consultan mediante la API STAC, la cual permite acceder a colecciones de datos satelitales utilizando una ubicación geográfica y un rango de fechas.

La función stac_search() permite buscar imágenes Sentinel-2 disponibles para el área de interés y periodo seleccionado. En este caso se utilizará la colección Sentinel-2 L2A COGs, que contiene imágenes corregidas atmosféricamente.

4.1 Conexión y búsqueda de imágenes

Primero se establece la conexión con el catálogo STAC de AWS y posteriormente se realiza la búsqueda utilizando los límites espaciales del municipio de Riosucio y el periodo de análisis.

s <- stac("https://earth-search.aws.element84.com/v0")

items <- s |>
  stac_search(
    collections = "sentinel-s2-l2a-cogs",
    bbox = c(
      st_bbox(riosucio)["xmin"],
      st_bbox(riosucio)["ymin"],
      st_bbox(riosucio)["xmax"],
      st_bbox(riosucio)["ymax"]
    ),
    datetime = "2025-01-01/2025-12-31",
    limit = 60
  ) |>
  post_request()

items
## ###Items
## - matched feature(s): 52
## - features (52 item(s) / 0 not fetched):
##   - S2C_18NTP_20251211_0_L2A
##   - S2B_18NTP_20251206_0_L2A
##   - S2C_18NTP_20251201_0_L2A
##   - S2B_18NTP_20251126_1_L2A
##   - S2A_18NTP_20251123_0_L2A
##   - S2C_18NTP_20251121_0_L2A
##   - S2B_18NTP_20251116_0_L2A
##   - S2C_18NTP_20251111_0_L2A
##   - S2B_18NTP_20251106_1_L2A
##   - S2C_18NTP_20251101_0_L2A
##   - ... with 42 more feature(s).
## - assets: 
## AOT, B01, B02, B03, B04, B05, B06, B07, B08, B09, B11, B12, B8A, info, metadata, overview, SCL, thumbnail, visual, WVP
## - item's fields: 
## assets, bbox, collection, geometry, id, links, properties, stac_extensions, stac_version, type

El resultado muestra la disponibilidad de imágenes Sentinel-2 para el área de interés. Se encontraron 52 escenas correspondientes al periodo consultado, todas disponibles para su procesamiento. Además, se presentan las bandas espectrales y la información asociada a cada imagen.

4.2 Rango temporal de las imágenes disponibles

Para conocer el periodo cubierto por las imágenes obtenidas, se extraen las fechas de adquisición de la primera y última escena disponible.

range(sapply(items$features, function(x) {
  x$properties$datetime
}))
## [1] "2025-06-04T15:41:26Z" "2025-12-11T15:41:14Z"

Las escenas Sentinel-2 disponibles para el área de estudio corresponden al periodo comprendido entre el 04 de junio de 2025 y el 11 de diciembre de 2025.

Para identificar las fechas de adquisición de las imágenes seleccionadas, se extrae la fecha de la primera y última escena almacenada en el objeto items.

5. Creación de la colección Sentinel-2

La respuesta obtenida desde STAC contiene la información de las imágenes disponibles, pero es necesario convertirla en una colección compatible con gdalcubes para realizar operaciones posteriores sobre las imágenes satelitales.

La función stac_image_collection() permite crear esta colección utilizando las escenas obtenidas previamente y seleccionar las bandas necesarias para el análisis.

5.1 Conversión de imágenes STAC a colección Sentinel-2

Para el cálculo del NDVI se utilizarán principalmente las bandas del rojo (B04) y del infrarrojo cercano (B08). Sin embargo, se cargan bandas adicionales junto con la capa de clasificación de superficie (SCL) para facilitar el procesamiento y filtrado de las imágenes.

assets <- c(
  "B01","B02","B03","B04","B05","B06",
  "B07","B08","B8A","B09","B11","SCL"
)

s2_collection <- stac_image_collection(
  items$features,
  asset_names = assets,
  property_filter = function(x) {
    x[["eo:cloud_cover"]] < 20
  }
)

La colección generada contiene las imágenes Sentinel-2 que cumplen con el filtro de nubosidad establecido.

s2_collection
## Image collection object, referencing 3 images with 12 bands
## Images:
##                       name      left      top   bottom
## 1 S2B_18NTP_20251106_1_L2A -77.72241 8.138354 7.140824
## 2 S2B_18NTP_20250828_0_L2A -77.72241 8.138354 7.140824
## 3 S2A_18NTP_20250706_0_L2A -77.72241 8.138354 7.140824
##       right            datetime        srs
## 1 -76.72251 2025-11-06T15:41:01 EPSG:32618
## 2 -76.72251 2025-08-28T15:41:07 EPSG:32618
## 3 -76.72251 2025-07-06T15:41:24 EPSG:32618
## 
## Bands:
##    name offset scale unit nodata image_count
## 1   B01      0     1                       3
## 2   B02      0     1                       3
## 3   B03      0     1                       3
## 4   B04      0     1                       3
## 5   B05      0     1                       3
## 6   B06      0     1                       3
## 7   B07      0     1                       3
## 8   B08      0     1                       3
## 9   B09      0     1                       3
## 10  B11      0     1                       3
## 11  B8A      0     1                       3
## 12  SCL      0     1                       3

Se creó una colección de imágenes Sentinel-2 aplicando un filtro de cobertura nubosa inferior al 20 %. De las escenas disponibles para el área de estudio, se seleccionaron 3 imágenes con menor presencia de nubes, correspondientes a julio, agosto y noviembre de 2025, las cuales serán utilizadas para el procesamiento y análisis de vegetación.

6. Creación y procesamiento del cubo de datos

Una vez creada la colección Sentinel-2, se utiliza la librería gdalcubes para organizar las imágenes en un cubo de datos espacio-temporal.

Un cubo de datos permite integrar las dimensiones espacial y temporal de las imágenes satelitales, facilitando el análisis de cambios en la vegetación a través del tiempo.

6.1 Definición del área y sistema de referencia

Primero se obtiene la extensión espacial del área de interés y se transforma al sistema de coordenadas proyectado utilizado para el procesamiento.

riosucio_box <- st_bbox(riosucio)

riosucio_b9377 <- st_bbox(
  st_transform(riosucio, "EPSG:9377")
)

La transformación a coordenadas proyectadas permite trabajar con unidades métricas, necesarias para definir la resolución espacial del cubo.

6.2 Creación del cubo de datos

Se configura el procesamiento paralelo y se define la estructura del cubo mediante la función cube_view().

gdalcubes_options(parallel = 8)

v <- cube_view(
   srs = "EPSG:9377",
  dx = 10,
  dy = 10,
  dt = "P1M",
  aggregation = "median",
  resampling = "average",
  extent = list(
    t0 = "2025-01-01",
    t1 = "2025-12-31",
    left = riosucio_b9377["xmin"],
    right = riosucio_b9377["xmax"],
    top = riosucio_b9377["ymax"],
    bottom = riosucio_b9377["ymin"]
  )
)

v
## A data cube view object
## 
## Dimensions:
##                low             high count pixel_size
## t       2025-01-01       2025-12-31    12        P1M
## y 2379357.11155677 2384147.11155677   479         10
## x 4543093.04288399 4548353.04288399   526         10
## 
## SRS: "EPSG:9377"
## Temporal aggregation method: "median"
## Spatial resampling method: "average"

El cubo de datos fue creado correctamente para el área de estudio. La extensión espacial fue ajustada ligeramente por gdalcubes para que coincidiera con la resolución espacial definida de 10 metros.

El cubo integra la información espacial y temporal de las imágenes Sentinel-2 mediante una agregación mensual utilizando la mediana, reduciendo la influencia de valores extremos como nubes o píxeles con información no válida.

7. Visualización del cubo de datos

Antes de calcular índices de vegetación, se realiza una visualización inicial de las imágenes Sentinel-2 mediante composiciones RGB.

La composición de color natural utiliza las bandas visibles rojo, verde y azul (B04, B03, B02), permitiendo observar la superficie de forma similar a una imagen convencional.

7.1 Composición de color natural (RGB 4-3-2)

raster_cube(s2_collection, v) |>
  select_bands(c("B02","B03","B04")) |>
  reduce_time(c("median(B02)", "median(B03)", "median(B04)")) |>
  plot(rgb = 3:1, zlim = c(0,2500))

La imagen obtenida permite identificar las principales coberturas del área de estudio mediante una representación visual similar al color real.

7.2 Composición en falso color (RGB 8-11-4)

La composición en falso color utiliza la banda del infrarrojo cercano (B08) junto con bandas del infrarrojo de onda corta (B11) y rojo (B04). Esta combinación permite resaltar diferencias en la cobertura vegetal y condiciones de la superficie.

raster_cube(s2_collection, v) |>
  select_bands(c("B04","B11","B08")) |>
  reduce_time(c("median(B04)", "median(B11)", "median(B08)")) |>
  plot(rgb = 3:1, zlim = c(0,4500))

La composición falso color facilita la identificación de áreas con mayor respuesta de la vegetación, siendo una base para el cálculo posterior de índices como el NDVI.

8. Descarga y almacenamiento de datos

Los datos del cubo Sentinel-2 son procesados aplicando una máscara basada en la banda de clasificación de escena (SCL), con el objetivo de reducir la influencia de nubes y sombras. Posteriormente, las imágenes resultantes se almacenan en formato GeoTIFF para su análisis posterior.

tutorialDir <- path.expand("./riosucio/")

if (!file.exists(file.path(tutorialDir, "Riosucio_10")))
{
  s2.mask <- image_mask("SCL", values = c(3,8,9))
  
  gdalcubes_options(
    parallel = 8,
    ncdf_compression_level = 0
  )
  
  raster_cube(
    s2_collection,
    v,
    mask = s2.mask
  ) |>
    write_tif(file.path(tutorialDir, "Riosucio_10.tif"))
}

Luego para revisar los archivos:

list.files("riosucio", recursive = TRUE)
##  [1] "Riosucio_10.tif/cube_47301b7d7df22025-01-01.tif"
##  [2] "Riosucio_10.tif/cube_47301b7d7df22025-02-01.tif"
##  [3] "Riosucio_10.tif/cube_47301b7d7df22025-03-01.tif"
##  [4] "Riosucio_10.tif/cube_47301b7d7df22025-04-01.tif"
##  [5] "Riosucio_10.tif/cube_47301b7d7df22025-05-01.tif"
##  [6] "Riosucio_10.tif/cube_47301b7d7df22025-06-01.tif"
##  [7] "Riosucio_10.tif/cube_47301b7d7df22025-07-01.tif"
##  [8] "Riosucio_10.tif/cube_47301b7d7df22025-08-01.tif"
##  [9] "Riosucio_10.tif/cube_47301b7d7df22025-09-01.tif"
## [10] "Riosucio_10.tif/cube_47301b7d7df22025-10-01.tif"
## [11] "Riosucio_10.tif/cube_47301b7d7df22025-11-01.tif"
## [12] "Riosucio_10.tif/cube_47301b7d7df22025-12-01.tif"
## [13] "Riosucio_10.tif/cube_473046c130e72025-01-01.tif"
## [14] "Riosucio_10.tif/cube_473046c130e72025-02-01.tif"
## [15] "Riosucio_10.tif/cube_473046c130e72025-03-01.tif"
## [16] "Riosucio_10.tif/cube_473046c130e72025-04-01.tif"
## [17] "Riosucio_10.tif/cube_473046c130e72025-05-01.tif"
## [18] "Riosucio_10.tif/cube_473046c130e72025-06-01.tif"
## [19] "Riosucio_10.tif/cube_473046c130e72025-07-01.tif"
## [20] "Riosucio_10.tif/cube_473046c130e72025-08-01.tif"
## [21] "Riosucio_10.tif/cube_473046c130e72025-09-01.tif"
## [22] "Riosucio_10.tif/cube_473046c130e72025-10-01.tif"
## [23] "Riosucio_10.tif/cube_473046c130e72025-11-01.tif"
## [24] "Riosucio_10.tif/cube_473046c130e72025-12-01.tif"
## [25] "Riosucio_10.tif/cube_47305990767e2025-01-01.tif"
## [26] "Riosucio_10.tif/cube_47305990767e2025-02-01.tif"
## [27] "Riosucio_10.tif/cube_47305990767e2025-03-01.tif"
## [28] "Riosucio_10.tif/cube_47305990767e2025-04-01.tif"
## [29] "Riosucio_10.tif/cube_47305990767e2025-05-01.tif"
## [30] "Riosucio_10.tif/cube_47305990767e2025-06-01.tif"
## [31] "Riosucio_10.tif/cube_47305990767e2025-07-01.tif"
## [32] "Riosucio_10.tif/cube_47305990767e2025-08-01.tif"
## [33] "Riosucio_10.tif/cube_47305990767e2025-09-01.tif"
## [34] "Riosucio_10.tif/cube_47305990767e2025-10-01.tif"
## [35] "Riosucio_10.tif/cube_47305990767e2025-11-01.tif"
## [36] "Riosucio_10.tif/cube_47305990767e2025-12-01.tif"
## [37] "Riosucio_10.tif/cube_473060b825d62025-01-01.tif"
## [38] "Riosucio_10.tif/cube_473060b825d62025-02-01.tif"
## [39] "Riosucio_10.tif/cube_473060b825d62025-03-01.tif"
## [40] "Riosucio_10.tif/cube_473060b825d62025-04-01.tif"
## [41] "Riosucio_10.tif/cube_473060b825d62025-05-01.tif"
## [42] "Riosucio_10.tif/cube_473060b825d62025-06-01.tif"
## [43] "Riosucio_10.tif/cube_473060b825d62025-07-01.tif"
## [44] "Riosucio_10.tif/cube_473060b825d62025-08-01.tif"
## [45] "Riosucio_10.tif/cube_473060b825d62025-09-01.tif"
## [46] "Riosucio_10.tif/cube_473060b825d62025-10-01.tif"
## [47] "Riosucio_10.tif/cube_473060b825d62025-11-01.tif"
## [48] "Riosucio_10.tif/cube_473060b825d62025-12-01.tif"
## [49] "Riosucio_10.tif/cube_473061cf7a752025-01-01.tif"
## [50] "Riosucio_10.tif/cube_473061cf7a752025-02-01.tif"
## [51] "Riosucio_10.tif/cube_473061cf7a752025-03-01.tif"
## [52] "Riosucio_10.tif/cube_473061cf7a752025-04-01.tif"
## [53] "Riosucio_10.tif/cube_473061cf7a752025-05-01.tif"
## [54] "Riosucio_10.tif/cube_473061cf7a752025-06-01.tif"
## [55] "Riosucio_10.tif/cube_473061cf7a752025-07-01.tif"
## [56] "Riosucio_10.tif/cube_473061cf7a752025-08-01.tif"
## [57] "Riosucio_10.tif/cube_473061cf7a752025-09-01.tif"
## [58] "Riosucio_10.tif/cube_473061cf7a752025-10-01.tif"
## [59] "Riosucio_10.tif/cube_473061cf7a752025-11-01.tif"
## [60] "Riosucio_10.tif/cube_473061cf7a752025-12-01.tif"
## [61] "Riosucio_10.tif/cube_47307e8161df2025-01-01.tif"
## [62] "Riosucio_10.tif/cube_47307e8161df2025-02-01.tif"
## [63] "Riosucio_10.tif/cube_47307e8161df2025-03-01.tif"
## [64] "Riosucio_10.tif/cube_47307e8161df2025-04-01.tif"
## [65] "Riosucio_10.tif/cube_47307e8161df2025-05-01.tif"
## [66] "Riosucio_10.tif/cube_47307e8161df2025-06-01.tif"
## [67] "Riosucio_10.tif/cube_47307e8161df2025-07-01.tif"
## [68] "Riosucio_10.tif/cube_47307e8161df2025-08-01.tif"
## [69] "Riosucio_10.tif/cube_47307e8161df2025-09-01.tif"
## [70] "Riosucio_10.tif/cube_47307e8161df2025-10-01.tif"
## [71] "Riosucio_10.tif/cube_47307e8161df2025-11-01.tif"
## [72] "Riosucio_10.tif/cube_47307e8161df2025-12-01.tif"

9. Cálculo y visualización del NDVI

El índice de vegetación de diferencia normalizada (NDVI) permite evaluar la presencia y condición de la vegetación mediante la relación entre las bandas roja (B04) e infrarrojo cercano (B08) de Sentinel-2.

Los valores del NDVI varían entre -1 y 1, donde valores altos representan mayor presencia y vigor vegetal, mientras que valores bajos o negativos corresponden a superficies con poca o ninguna vegetación.

f <- "riosucio/Riosucio_10.tif/cube_47301b7d7df22025-11-01.tif"

riosucio_s2 <- terra::rast(f)

La imagen seleccionada corresponde a una escena Sentinel-2 procesada para noviembre de 2025, utilizada para el cálculo del índice de vegetación.

# Definición de bandas
red <- riosucio_s2[[4]]
nir <- riosucio_s2[[8]]

# Cálculo del NDVI
ndvi <- (nir - red) / (nir + red)

ndvi
## class       : SpatRaster
## size        : 479, 526, 1  (nrow, ncol, nlyr)
## resolution  : 10, 10  (x, y)
## extent      : 4543093, 4548353, 2379357, 2384147  (xmin, xmax, ymin, ymax)
## coord. ref. : MAGNA-SIRGAS 2018 / Origen-Nacional (EPSG:9377)
## source(s)   : memory
## varname     : cube_47301b7d7df22025-11-01
## name        :       B08
## min value   : -0.698765
## max value   :  0.920921

El resultado corresponde a un raster de NDVI calculado a partir de las bandas roja (B04) e infrarrojo cercano (B08) de Sentinel-2. La imagen presenta una resolución espacial de 10 m y valores de NDVI entre -0.69 y 0.92, evidenciando la variabilidad espacial de la cobertura vegetal dentro del área de estudio.

tm_shape(ndvi) +
  tm_raster(
    col_palette = "RdYlGn",
    style = "cont",
    title = "NDVI"
  ) +
  tm_layout(
    main.title = "NDVI Sentinel-2 - Riosucio, Chocó - Noviembre 2025"
  )
## 
## ── tmap v3 code detected ─────────────────────────────────────
## [v3->v4] `tm_raster()`: instead of `style = "cont"`, use
## col.scale = `tm_scale_continuous()`.
## [v3->v4] `tm_raster()`: migrate the argument(s) related to
## the legend of the map variable `col` namely 'title' to
## 'col.legend = tm_legend(<HERE>)'
## [tm_raster()] Argument `col_palette` unknown.
## [v3->v4] `tm_layout()`: use `tm_title()` instead of
## `tm_layout(main.title = )`

La distribución espacial del NDVI permite identificar diferencias en la cobertura vegetal del área analizada. Los valores positivos elevados representan zonas con mayor actividad fotosintética y presencia de vegetación densa, mientras que los valores cercanos a cero o negativos pueden estar asociados a superficies con menor cobertura vegetal, agua, suelo expuesto o presencia de nubes.

ndvi_palette <- colorNumeric(
  palette = c("red", "yellow", "green"),
  domain = c(-1, 1),
  na.color = "transparent"
)

map <- leaflet() %>%
  addProviderTiles(
    "Esri.WorldImagery",
    group = "Esri Satellite"
  ) %>%
  setView(
    lng = -77.115,
    lat = 7.435,
    zoom = 13
  ) %>%
  addRasterImage(
    x = ndvi,
    colors = ndvi_palette,
    opacity = 0.6,
    group = "NDVI"
  ) %>%
  addLegend(
    pal = ndvi_palette,
    values = c(-1,1),
    title = "NDVI",
    position = "bottomright"
  )

map

10. Cálculo e interpretación del NDVI

En esta sección se calcula el índice NDVI para dos fechas de adquisición de imágenes Sentinel-2, con el fin de comparar la respuesta de la cobertura vegetal en diferentes momentos del año.

10.1 NDVI – Julio de 2025

Para esta fecha se calcula el índice NDVI a partir de las bandas roja (B04) e infrarrojo cercano (B08) de una imagen Sentinel-2, con el fin de evaluar el estado de la cobertura vegetal del área de estudio.

f <- "riosucio/Riosucio_10.tif/cube_473060b825d62025-07-01.tif"

riosucio_s2 <- terra::rast(f)

Las bandas espectrales correspondientes al rojo e infrarrojo cercano se utilizan para calcular el índice NDVI.

# Definición de bandas
red <- riosucio_s2[[4]]
nir <- riosucio_s2[[8]]

# Cálculo del NDVI
ndvi <- (nir - red) / (nir + red)

ndvi
## class       : SpatRaster
## size        : 479, 526, 1  (nrow, ncol, nlyr)
## resolution  : 10, 10  (x, y)
## extent      : 4543093, 4548353, 2379357, 2384147  (xmin, xmax, ymin, ymax)
## coord. ref. : MAGNA-SIRGAS 2018 / Origen-Nacional (EPSG:9377)
## source(s)   : memory
## varname     : cube_473060b825d62025-07-01
## name        :       B08
## min value   : -0.383081
## max value   :  0.896586

El resultado corresponde a un raster de NDVI calculado para julio de 2025. La imagen presenta una resolución espacial de 10 m y valores de NDVI entre -0.38 y 0.90, reflejando la variabilidad de la cobertura vegetal en el área de estudio.

tm_shape(ndvi) +
  tm_raster(
    col.scale = tm_scale_continuous(
      values = c("red", "yellow", "green")
    ),
    col.legend = tm_legend(
      title = "NDVI"
    )
  ) +
  tm_title(
    "NDVI Sentinel-2 - Riosucio, Chocó - Julio 2025"
  )

La distribución espacial del NDVI permite identificar diferencias en la cobertura vegetal del área de estudio. Los tonos verdes representan zonas con mayor cobertura y vigor de la vegetación, los amarillos indican una cobertura vegetal intermedia y los rojos corresponden principalmente a superficies con escasa o nula vegetación, cuerpos de agua, sombras o nubosidad.

10.2 NDVI – Noviembre de 2025

Para esta fecha se calcula el índice NDVI a partir de las bandas roja (B04) e infrarrojo cercano (B08) de una imagen Sentinel-2, con el fin de evaluar el estado de la cobertura vegetal del área de estudio.

f <- "riosucio/Riosucio_10.tif/cube_47301b7d7df22025-11-01.tif"

riosucio_s2 <- terra::rast(f)

Las bandas espectrales correspondientes al rojo e infrarrojo cercano se utilizan para calcular el índice NDVI.

# Definición de bandas
red <- riosucio_s2[[4]]
nir <- riosucio_s2[[8]]

# Cálculo del NDVI
ndvi <- (nir - red) / (nir + red)

ndvi
## class       : SpatRaster
## size        : 479, 526, 1  (nrow, ncol, nlyr)
## resolution  : 10, 10  (x, y)
## extent      : 4543093, 4548353, 2379357, 2384147  (xmin, xmax, ymin, ymax)
## coord. ref. : MAGNA-SIRGAS 2018 / Origen-Nacional (EPSG:9377)
## source(s)   : memory
## varname     : cube_47301b7d7df22025-11-01
## name        :       B08
## min value   : -0.698765
## max value   :  0.920921

El resultado corresponde a un raster de NDVI calculado para noviembre de 2025. La imagen presenta una resolución espacial de 10 m y valores de NDVI entre -0.70 y 0.92, reflejando la variabilidad de la cobertura vegetal en el área de estudio.

tm_shape(ndvi) +
  tm_raster(
    col.scale = tm_scale_continuous(
      values = c("red", "yellow", "green")
    ),
    col.legend = tm_legend(
      title = "NDVI"
    )
  ) +
  tm_title(
    "NDVI Sentinel-2 - Riosucio, Chocó - Noviembre 2025"
  )

10.3 Comparación temporal

La comparación del NDVI entre julio y noviembre de 2025 permite identificar cambios en la cobertura vegetal del área de estudio. En ambas fechas predominan los tonos verdes, lo que indica la presencia de vegetación con buen vigor. Sin embargo, en la imagen de noviembre se observan más áreas con tonos rojos, asociadas principalmente a cuerpos de agua, sombras o nubosidad, lo cual también se refleja en un valor mínimo de NDVI más bajo (-0.70) en comparación con julio (-0.38). A pesar de estas diferencias, ambas fechas presentan valores máximos superiores a 0.89, evidenciando una cobertura vegetal densa y saludable en gran parte del área analizada.

Bibliografía

Lizarazo, I. (2026). Accessing time series of Sentinel-2 imagery. RPubs.
https://rpubs.com/ials2un/sentinel2_ts

UPRA. (2025). Evaluaciones Agropecuarias Municipales (EVA): Microanálisis del departamento del Chocó. Unidad de Planificación Rural Agropecuaria.