gypti gypti - 1 month ago 6
R Question

Show a grid of equally spaced images with layout() and display()

I want to create a grid of 9 images with equal spacing between them. Until now I managed to get something to work with

par()
and
layout()
.

layout(matrix(1:9, widths=rep(lcm(4),9), heights=rep(lcm(3),9))

for (i in 1:9) {
imNew <- readImage(img_ar[i])
EBImage::display(imNew, method="raster")
}


gives me this

no spcaing in between individual images

while using par:

layout(matrix(1:9, widths=rep(lcm(4),9), heights=rep(lcm(3),9))

for (i in 1:9) {
imNew <- readImage(img_ar[i])
EBImage::display(imNew,method="raster")
}


gives me this:

vertical spacing

I also tried different options for
par()
like
oma
,
mai
and
mar
but these didn't change the spacing in between the individual images. What I like to have is an equal distance between the individual images like this:

result

Could anyone help me please?

Answer

You can use your original idea to separate images by including additional empty rows and columns in your layout, as in the following example. Note, however, that in order to achieve equal horizontal and vertical spacing you will need to tweak the device dimensions.

library(EBImage)

# load sample image
img <- readImage(system.file("images", "sample-color.png", package="EBImage"))

# downsample to reduce memory consumption and for faster processing
img <- resize(img, 192)

# build the layout matrix with additional separating cells
nx <- 4 # number of images in a row
ny <- 3 # number of images in a column

cols <- 2*nx-1
rows <- 2*ny-1
m <- matrix(0, cols, rows)
m[2*(1:nx)-1, 2*(1:ny)-1] <- 1:(nx*ny)
m <- t(m)

# relative spacing
pad <- .1

w <- rep(1, cols)
w[!(1:cols)%%2] <- pad
h <- rep(1, rows)
h[!(1:rows)%%2] <- pad * dim(img)[1L]/dim(img)[2L]

layout(m, widths = w, heights = h)

layout.show(nx*ny)

for (i in 1:(nx*ny)) {
  display(img, method="raster")
}

enter image description here

You can actually use display() on an image stack to show individual frames in a grid arrangement by setting all=TRUE.

## construct sample image stack
img_stack <- combine(replicate(nx*ny, img, simplify=FALSE))

display(img_stack, method="raster", all=TRUE)

enter image description here

Until now, however, it was not possible to add spacing between the frames. To facilitate this, I've added an argument to display() specifying the padding. This new feature is available in the development version of EBImage, which can be obtained from GitHub devtools::install_github("aoles/EBImage").

The padding can be provided as a fraction of frame dimensions (positive numbers <1) or in pixels (numbers >=1). Additionally, you can have different horizontal and vertical separation by providing a vector, e.g. padding = (10, 20) will separate the columns by 10px, and the rows by 20px.

display(img_stack, method="raster", all=TRUE, padding=.1)

enter image description here

Finally, a different approach which might be sometimes useful is to construct one big composite image with tile. Note the additional border around the whole grid.

## tiled composite image
img_tiles <- tile(img_stack, nx=nx, lwd=20, fg.col="white", bg.col="white")    

display(img_tiles, method="raster")

enter image description here