How to convert categorial raster to mapped RGB values in R?

Viewed 42

How do we convert a single band categorial raster to a three-dimensional RGB array?

Lets say we want to define the color per value(category) and get an RGB array with corresponding decimal RGB values.

E.g. in the example below how would I get rgb_array given r and myCol?

library(raster)
# sample raster
r <- raster(ncol=4, nrow=4)
r[] <- c(rep(1, 8), rep(2, 8))

# plot 1=red, 2=blue
myCol = c("red", "blue")
plot(r, col=myCol)

# rgb_array is the desired output, but how to get it programatically from r?
red_band <- c(rep(255, 8), rep(0, 8))
green_band <- c(rep(0, 8), rep(0, 8))
blue_band <- c(rep(0, 8), rep(255, 8))
rgb_array <- array(c(red_band, green_band, blue_band), dim= c(4, 4, 3))
2 Answers

As categorical is mentioned, start with a single layer categorical raster:

library(terra)

set.seed(0)
m <- rast(nrows=10, ncols=10)
values(m) <- sample(3, ncell(m), replace=TRUE)
# just to show setting categories
cls <- data.frame(id=1:3, cover=c("forest", "water", "urban"))
levels(m) <- cls

gives us a categorical raster. At this point it seems like we'd want to break this into 3 layers.


m1_1 <- ifel(m == 1, m + 250, m + 20)
m1_2 <- ifel(m == 2, m + 250, m + 20)
m1_3 <- ifel(m == 3, m + 250, m + 20)
m1_123_arr <- array(data=c(m1_1, m1_2, m1_3), dim = c(10,10,3))
m1_123_rast <- rast(m1_123_arr)
names(m1_123_rast) <- c('forest', 'water', 'urban')
RGB(m1_123_arr) <- c(3,1,2)
plotRGB(m1_123_rast, mar = c(2,2,2,2))

enter image description here

But probably best to go with Robert's approach.

You can do this with terra::subst.

Example data

library(terra)
#terra 1.6.21
x <- rast(ncol=4, nrow=4, vals=c(rep(1, 8), rep(2, 8)))

Solution

from <- 1:2
to <-  t(col2rgb(c("red", "blue")))
r <- subst(x, from, to, names=c("red", "green", "blue"))
plotRGB(r)

You can also use terra::colorize for that. But thanks to your question I found a bug in that method so you need to use "terra" version 1.6-21 or higher. That is currently the development version that you can install like this: install.packages('terra', repos='https://rspatial.r-universe.dev')

Set the color table that matches the values with a color, and use colorize.

coltab(x) <- data.frame(value=1:2, col=c("red", "blue"))
 
rgb <- colorize(x, "rgb")
rgb
#class       : SpatRaster 
#dimensions  : 4, 4, 3  (nrow, ncol, nlyr)
#resolution  : 90, 45  (x, y)
#extent      : -180, 180, -90, 90  (xmin, xmax, ymin, ymax)
#coord. ref. : +proj=longlat +datum=WGS84 +no_defs 
#source      : memory 
#colors RGB  : 1, 2, 3 
#names       : red, green, blue 
#min values  :   0,     0,    0 
#max values  : 255,     0,  255 

And now you can do

plot(rgb)

To get the equivalent to plot(x) (because x has a color-table)

Related