Enrique
Enrique

Reputation: 10117

How to plot an RGB image using the image() function from a 3D array?

I have an array with dimension (28,28,3) height, width, depth. Each depth is one of the RGB channels. The values are between 0 and 1.

I want to use the image() function to plot the image. The z argument is a matrix. How can I convert the array into a matrix in order to be able to plot?

My final goal is to have something like this but with color images.

Upvotes: 1

Views: 2555

Answers (3)

Robert Hijmans
Robert Hijmans

Reputation: 47051

With the raster package you can do

R <- matrix(rep(sin(seq(0, 2*pi, length.out = 31))^2, length.out = 900), nrow = 30)
G <- matrix(rep(cos(seq(0, 2*pi, length.out = 15))^2, length.out = 900), nrow = 30)
B <- matrix(rep(sin(seq(pi, 2*pi, length.out = 30))^2, length.out = 900), nrow = 30)

my_img <- c(R, G, B)
dim(my_img) <- c(30, 30, 3)

library(raster)
b <- brick(my_img)
crs(b) <- "+proj=tmerc"
plotRGB(b, scale=1)
# or
plotRGB(b, scale=1, interpolate=TRUE)

Upvotes: 0

Allan Cameron
Allan Cameron

Reputation: 173793

The problem with graphics::image is that it will not plot your 3D array as a colour image. It plots a matrix as a heatmap.

Let's take a colorful patterned image:

R <- matrix(rep(sin(seq(0, 2*pi, length.out = 31))^2, length.out = 900), nrow = 30)
G <- matrix(rep(cos(seq(0, 2*pi, length.out = 15))^2, length.out = 900), nrow = 30)
B <- matrix(rep(sin(seq(pi, 2*pi, length.out = 30))^2, length.out = 900), nrow = 30)

my_img <- c(R, G, B)
dim(my_img) <- c(30, 30, 3)

Now if I plot this with raster as @IanCampbell suggests, I get my desired image:

plot(raster::as.raster(my_img))

enter image description here

whereas if I plot one layer (here the red channel) using image, I get a heatmap:

image(R)

enter image description here

If you really want to use image, then you would have to average all your layers, but then you lose colour information, and still get a heat map:

image((R + B + G)/3)

enter image description here

So the bottom line is that if you want to plot a colour image, then image is not the function you are looking for. There are lots of ways to plot multiple colour images in a single R window, so saying that you have to use image because you need to plot a grid of images just isn't true.

For example:

grid.arrange(rasterGrob(my_img),   rasterGrob(1-my_img),
             rasterGrob(1-my_img), rasterGrob(my_img), ncol = 2)

enter image description here

Upvotes: 3

Ian Campbell
Ian Campbell

Reputation: 24770

One approach is with rasterImage

set.seed(3)
data <- replicate(4,array(data = runif(28*28*3,0,1),
                          dim = c(28,28,3)), simplify = FALSE)

par(mfrow=c(2, 2), mar=c(0, 0, 3, 0))
sapply(seq_along(data), function(x){
  plot.new()
  rasterImage(data[[x]], xleft = 0, xright = 1,
            ytop = 0, ybottom = 1, interpolate = FALSE)
  title(paste0("Plot ",x))
})

enter image description here

Upvotes: 4

Related Questions