💡 OBJETIVOS DE LA ACTIVIDAD:

► Conocer las diferentes opciones de representación gráfica de imágenes de satélite con R.

► Practicar la exportación de imágenes gráficas generadas con R.

💡 MATERIALES PARA LA ACTIVIDAD:

Los materiales para el desarrollo de esta actividad son los mismos de la actividad pasada.

Imagen.

script_laboratorio_4_representación_gráfica.

INTRODUCCIÓN

En este capítulo se utilizan fundamentalmente las capacidades gráficas de los paquetes terra y RStoolbox, totalmente integradas con el sistema gráfico del paquete base de R.

Paquete terra

Es el paquete básico para la manipulación de imágenes ráster y para un análisis visual inmediato. La representación gráfica más básica de datos ráster se logra con la función plot() o con la función imagen(). Debe tenerse en cuenta que la primera sólo puede representar 100000 píxeles.

La función plot()[https://rspatial.github.io/terra/reference/plot.html] se acompaña de los siguientes argumentos para representar un objeto SpatRáster son los siguientes:

Argumento Descripción
col Vector de colores para representar los valores del ráster. Ejemplo: col = terrain.colors(100), col = gray.colors(256)
main Título de la imagen
xlab, ylab Etiquetas de los ejes
axes TRUE o FALSE, indica si se dibujan los ejes
legend TRUE o FALSE, para mostrar o no la leyenda
type Para objetos SpatVector, define el tipo de gráfico (“p”, “l”, “b”)
range Define el rango de valores a visualizar, ej. range = c(0, 255)
smooth Si TRUE, usa interpolación para suavizar la imagen en ráster con valores continuos
asp Relación de aspecto (proporción entre ejes X e Y)
maxcell Máximo número de celdas a visualizar (para mejorar rendimiento). Por defecto 500,000
levels Si TRUE, usa una paleta categórica (para datos discretos)
plg Si FALSE, oculta la barra de colores (leyenda)
pax Si FALSE, oculta los ejes de coordenadas
fun Función a aplicar antes de graficar, ej. fun = log
add Si TRUE, añade la imagen a un gráfico existente

Argumentos para SpatVector (Vectores)

Argumento Descripción
col Color de relleno de los polígonos o puntos
border Color del borde (para polígonos o líneas)
lwd Ancho de línea (lwd = 2 para hacerlas más gruesas)
lty Tipo de línea (1 = sólida, 2 = discontinua, etc.)
cex Tamaño de los puntos
pch Tipo de símbolo para puntos (pch = 16 para círculos)
add Si TRUE, añade el vector a un gráfico existente

Es conveniente revisar otros argumentos de la función plot() mediante páginas de ayuda como ?graphics::plot(), ?raster::plot(), ?par y ?axis.

Paquete RStoolbox.

El paquete Rstoolbox incluye como función principal la función ggR() para la visualización en profundidad de un objeto SpatRaster. Presenta una sintaxis derivada del paquete ggplot2 que se agregan en función de los intereses del investigador.

Argumentos fundamentales de la función ggR()
Argumentos fundamentales de la función ggR()

PASOS PREVIOS

Instalación de los paquetes necesarios para la actividad.

Primero se instalarán los paquetes básicos: terra y ggplot2

library(terra)
## Warning: package 'terra' was built under R version 4.3.3
## terra 1.8.21
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.3.3

A continuación debe instalarse el paquete RStoolbox. Su autor recomienda el siguiente método de instalación.

#install.packages("devtools")
#library(devtools)
# install_github("bleutner/RStoolbox")
library(RStoolbox)
## Warning: package 'RStoolbox' was built under R version 4.3.3
## This is version 1.0.0 of RStoolbox

Creación de carpetas y descarga de los ficheros necesarios.

La actividad debe comenzar identificando la carpeta con los datos e importar los ficheros necesario para el desarrollo de la práctica

setwd("D:/G174_2025/LABORATORIO_4_Visualizacion_imagenes/datos/")
getwd()
## [1] "D:/G174_2025/LABORATORIO_4_Visualizacion_imagenes/datos"

A continuación, se realiza una lista de los ficheros que existen en la carpeta datos.

lista <- list.files("D:/G174_2025/LABORATORIO_4_Visualizacion_imagenes/datos/",   
                   pattern = ".*band[1234567]\\.tif$",                                      
                   ignore.case=TRUE,                                            
                   full.names = TRUE)

En tercer lugar, esa lista permite importar los ficheros en forma de un objeto SpatRaster.

imagen_landsat <- rast(lista)
imagen_landsat
## class       : SpatRaster 
## dimensions  : 1545, 1480, 7  (nrow, ncol, nlyr)
## resolution  : 30, 30  (x, y)
## extent      : 549615, 594015, 4613355, 4659705  (xmin, xmax, ymin, ymax)
## coord. ref. : WGS 84 / UTM zone 29N (EPSG:32629) 
## sources     : LC82040312015193LGN00_sr_band1.tif  
##               LC82040312015193LGN00_sr_band2.tif  
##               LC82040312015193LGN00_sr_band3.tif  
##               ... and 4 more sources
## names       : LC820~band1, LC820~band2, LC820~band3, LC820~band4, LC820~band5, LC820~band6, ...

Como ya se ha señalado en ocasiones previas, la identificación de las bandas es complicada si se mantienen los nombres de los archivos originales, siendo conveniente su transformación en nombres de más fácil identificación.

names(imagen_landsat) <- gsub(pattern = "LC82040312015193LGN00_sr_band",    
                           replace ="B",                                         
                           x <- names(imagen_landsat))                          
imagen_landsat
## class       : SpatRaster 
## dimensions  : 1545, 1480, 7  (nrow, ncol, nlyr)
## resolution  : 30, 30  (x, y)
## extent      : 549615, 594015, 4613355, 4659705  (xmin, xmax, ymin, ymax)
## coord. ref. : WGS 84 / UTM zone 29N (EPSG:32629) 
## sources     : LC82040312015193LGN00_sr_band1.tif  
##               LC82040312015193LGN00_sr_band2.tif  
##               LC82040312015193LGN00_sr_band3.tif  
##               ... and 4 more sources
## names       : B1, B2, B3, B4, B5, B6, ...

REPRESENTACIÓN GRÁFICA DE UNA ÚNICA BANDA.

Con la función plot() del paquete terra.

La representación de una banda concreta requiere mencionar el número (de orden) de la banda utilizando la siguiente notación [[número de banda]], acompañado de algunos argumentos adicionales para mejorar la estética.

plot(imagen_landsat[[5]], 
     axe = TRUE,                              # Dibuja los ejes
     main = "Banda 5 Landsat",                # Título
     xlab ="Longitud", ylab="Latitud",        # Etiquetas de los ejes X e Y
     legend = TRUE)                           # Inclusión de una leyenda

Existe la función alternativa image pero es menos flexible y carece de leyenda.

image(imagen_landsat[[5]])

Esta función aplica por defecto una única paleta, pero ésta se puede cambiar. Por ejemplo, se puede representar gráficamente con una paleta de colores grises, cuya intensidad se escala proporcionalmente a los números digitales de las imágenes.

plot(imagen_landsat[[5]],                     # Representación de la 5ª imagen
     col = grey(0:100/100),                   # Colores, en este caso porcentajes de gris 
     axe = TRUE,                              # Dibuja los ejes
     main = "Banda 5 Landsat",                # Título
     xlab ="Longitud", ylab="Latitud",        # Etiquetas de los ejes X e Y
     legend = TRUE)                           # Inclusión de una leyenda

Existen diferentes posibilidades de representación. Por ejemplo, si la elaboración de gráficos es lenta o experimenta problemas de memoria (debido al gran volumen de datos) se puede incluir el argumento Maxpixels (por defecto es 5e+5) para reducir el número de píxeles a dibujar, aunque los resultados tienen una menor calidad, pudiéndose llegar, si se utiliza un número reducido de píxeles, a obtener escenas pixeladas:

plot(imagen_landsat[[5]],                     # Representación de la 5ª imagen
     col = grey(0:100/100),                   # Colores, en este caso porcentajes de gris 
     axe = TRUE,                              # Dibuja los ejes
     main = "Banda 5 Landsat",                # Título
     xlab ="Longitud", ylab="Latitud",        # Etiquetas de los ejes X e Y
     legend = TRUE, 
     maxpixels = 1e+05)
## Warning in plot.window(...): "maxpixels" is not a graphical parameter
## Warning in plot.xy(xy, type, ...): "maxpixels" is not a graphical parameter
## Warning in title(...): "maxpixels" is not a graphical parameter

La paleta de colores puede modificarse al establecer el nivel de transparencia en el 50% (argumento alpha = 0.5).

plot(imagen_landsat[[5]],                     # Representación de la 5ª imagen
     col = grey(0:100/100),                   # Colores, en este caso porcentajes de gris 
     alpha = 0.5,                             # Transparencia.
     axe = TRUE,                              # Dibuja los ejes
     main = "Banda 5 Landsat",                # Título
     xlab ="Longitud", ylab="Latitud",        # Etiquetas de los ejes X e Y
     legend = TRUE)

Otra posibilidad es utilizar paletas de colores como la “viridis”(https://search.r-project.org/CRAN/refmans/viridisLite/html/viridis.html), para mejorar la representación.

library(viridis)
## Warning: package 'viridis' was built under R version 4.3.2
## Loading required package: viridisLite
## Warning: package 'viridisLite' was built under R version 4.3.2
plot(imagen_landsat[[5]],                     # Representación de la 5ª imagen
     axe = TRUE,                              # Dibuja los ejes
     main = "Banda 5 Landsat",                # Título
     xlab ="Longitud", ylab="Latitud",        # Etiquetas de los ejes X e Y
     legend = TRUE,
     col= viridis_pal(option="D")(10))         # La option = "D" identifica la paleta "viridis" con 10 colores. 

🚧 PALETAS DE COLORES

La (página web)[https://developers.arcgis.com/javascript/latest/visualization/symbols-color-ramps/esri-color-ramps/] ofrece un conjunto de paletas de colores con sus respectivos códigos hexagesimales.

Con la función RStoolbox::ggR() del paquete Rstoolbox.

La función ggR() posee diferentes niveles de complejidad. La representación más sencilla podría ser la siguiente:

ggR(imagen_landsat, 5) + 
  theme_minimal()

O puede ser tan complejo como esta última imagen

ggR(imagen_landsat, 5, geom_raster = TRUE) + 
  ggtitle("Banda 5: Red") + 
  labs(x = "Longitud (m)", y = "Latitud (m)") + 
  theme(
    plot.title = element_text(hjust = 0.5, size = 20),                          # Título del gráfico, alineación centrado, tamaño de la fuente
    axis.title = element_text(size = 10),
    axis.text.x = element_text(size = 10, color = "black", face = "bold"),      # Tamaño de números en eje X
    axis.text.y = element_text(size = 10, color = "black", face = "bold"),      # Tamaño de números en eje Y
    panel.background = element_rect(fill = "white", color = "black"),  
    panel.grid.major = element_blank(),                                         # remove the grid lines from the plot: clean white background.
    panel.grid.minor = element_blank(),                                         # 
    legend.background = element_rect(fill = "lightgray", size = 0.5, linetype = "solid"),  # Apariencia del fondo de la leyenda 
    legend.key.size = unit(1, "cm"),                                            # Tamaño del rectángulo en el que se inserta la leyenda.
    legend.title = element_text(size = 15, face = "bold"),                      # Título (en negrita) de la leyenda.
    legend.text = element_text(size = 12),                                      # Valores (etiquetas) de la leyenda.
    legend.position = "right") +                                                 # Posición de la leyenda del lienzo.
  scale_fill_gradientn(name = "NDVI Values", 
                       colours = c("white", "darkgreen")) 
## Warning: The `size` argument of `element_rect()` is deprecated as of ggplot2 3.4.0.
## ℹ Please use the `linewidth` argument instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

En relación a la escala de colores, ésta puede optar por numerosas opciones, por ejemplo

ggR(imagen_landsat, 5, geom_raster = TRUE) + 
  ggtitle("**Banda 5: RED**") +
  theme(panel.background = element_rect(fill = "white", color = "red")) +           
  scale_fill_gradientn(colours=rainbow(100))

REPRESENTACIÓN GRÁFICA DE TODAS LAS BANDAS

Con la función plot() del paquete terra.

Constituye la manera más sencilla de representar algunas (por ejemplo, la sintaxis para las bandas 3, 4 y 5 sería imagen_landsat[[3:5]]) o todas las imágenes a la vez (sintaxis imagen_landsat. No hay necesidad de incluir un título, ya que el programa reconoce el nombre de cada banda de acuerdo a su posición.

plot(imagen_landsat[[3:5]],                   # Representación de todas las imágenes
     col = viridis_pal(option="D")(10),       # Colores
     axe = TRUE,                              # Dibuja los ejes
     cex.axis = 2.5,                          # Tamaño de la etiqueta con el título.
     xlab ="Longitud", ylab="Latitud",        # Etiquetas de los ejes X e Y
     legend = TRUE)

Con la función RStoolbox::ggR() del paquete Rstoolbox.

Con RStoolbox la representación simultánea de varias imágenes es más complicada, ya que no existe una función específica para ello. Una posible opción crear varios objetos gráficos con la función ggR() y combinarlas con el paquete patchwork.

library(patchwork)  
## Warning: package 'patchwork' was built under R version 4.3.3
## 
## Attaching package: 'patchwork'
## The following object is masked from 'package:terra':
## 
##     area
p3 <- ggR(imagen_landsat, 3, geom_raster = TRUE) + ggtitle("**Banda 3: BLUE**") + scale_fill_gradientn(colours=rainbow(100),limits = c(0, 7000))
p4 <- ggR(imagen_landsat, 4, geom_raster = TRUE) + ggtitle("**Banda 4: GREEN**") + scale_fill_gradientn(colours=rainbow(100),limits = c(0, 7000)) 
p5 <- ggR(imagen_landsat, 5, geom_raster = TRUE) + ggtitle("**Banda 5: RED**") + scale_fill_gradientn(colours=rainbow(100), limits = c(0, 7000))
p3 + p4 + p5 + plot_layout(ncol = 2, nrow = 2)

Una segunda opción es convertir la imagen ráster en dataframe y dibujarla con ggplot2(). Esta opción no es recomendable si la imagen ráster es muy pesada.

► Paso 1: convertir el raster a un dataframe

df <- as.data.frame(imagen_landsat,  xy = TRUE)                      # Convertir en data frame con coordenadas
df_long <- reshape2::melt(df, id.vars = c("x", "y"))                 # Formato largo para ggplot

► Paso 2: elaborar el gráfico con ggplot2() y definir facetas por capa

ggplot(df_long, aes(x = x, y = y, fill = value)) +
  geom_raster() +
  facet_wrap(~ variable) +  # Separa las imágenes por capa
  scale_fill_viridis_c() +  # Paleta de colores continua
  theme_minimal() +
  labs(title = "Visualización de Capas Ráster", fill = "Valor")

EXPORTACIÓN DE LA IMAGEN EN FORMATO GRÁFICO

Finalmente, es posible exportar la imagen con un formato gráfico, en este caso *.png.

png("D:/G174_2025/LABORATORIO_4_Visualizacion_imagenes/mi_imagen.png",                     # 
    width = 4, height = 4, units = "in", res = 300)                                        # Define la imagen a exportar
plot(imagen_landsat, 
     col= viridis_pal(option="D")(10), 
     main="Imagen")
dev.off()