Overlay data onto background image
I recently figured out how easy it was to use a background image and map data on top of it using Tableau Public. Here is the process from their website. As you can see, it is fairly straightforward, and you simply tell the software what image you want to use and how to define the coordinates.
Is the process as straightforward in R? What would be the best approach?
Solution 1:
JPEG
For jpeg images, you can use read.jpeg()
from the rimage
package.
eg :
anImage <- read.jpeg("anImage.jpeg")
plot(anImage)
points(my.x,my.y,col="red")
...
By setting par(new=T) before the next plot command, you can construct complete plots over a background picture. (see ?par
and further down)
PNG
PNG images you can upload using readPNG
from the png
package. With readPNG
, you need the rasterImage
command to plot (see also the help files). On Windows, one has to get rid of the alpha channel, as Windows cannot cope with per-pixel alphas up to now. Simon Urbanek was so kind as to point out this solution :
img <- readPNG(system.file("img", "Rlogo.png", package="png"))
r = as.raster(img[,,1:3])
r[img[,,4] == 0] = "white"
plot(1:2,type="n")
rasterImage(r,1,1,2,2)
GIF
For gif files, you can use read.gif
from caTools
. Problem is that this is rotating the matrix, so you have to adjust it :
Gif <- read.gif("http://www.openbsd.org/art/puffy/ppuf600X544.gif")
n <- dim(Gif$image)
image(t(Gif$image)[n[2]:1,n[1]:1],col=Gif$col,axes=F)
To plot over this image, you have to set the par correctly, eg :
image(t(Gif$image)[n[2]:1,n[1]:1],col=Gif$col,axes=F)
op <- par(new=T)
plot(1:100,new=T)
par(op)
Solution 2:
For a JPEG image you can use the jpeg library and ggplot2 library.
Usually I found useful to have the axis graduated in pixel and the vertical axis going positive in the downward direction and the picture keeping its original aspect ratio. So I can feed R directly with the output produced by computer vision algorithm, for example the algorithm can detect the bullet hole and extract the hole coordinates from a shooting target picture and then R can plot a 2D histogram using the target image as background.
My code is based on code by baptiste found at https://stackoverflow.com/a/16418186/15485
library(ggplot2)
library(jpeg)
img <- readJPEG("bersaglio.jpg") # http://www.tiropratico.com/bersagli/forme/avancarica.jpg
h<-dim(img)[1] # image height
w<-dim(img)[2] # image width
df<-data.frame(x=rnorm(100000,w/1.99,w/100),y=rnorm(100000,h/2.01,h/97))
plot(ggplot(df, aes(x,y)) +
annotation_custom(grid::rasterGrob(img, width=unit(1,"npc"), height=unit(1,"npc")), 0, w, 0, -h) + # The minus is needed to get the y scale reversed
scale_x_continuous(expand=c(0,0),limits=c(0,w)) +
scale_y_reverse(expand=c(0,0),limits=c(h,0)) + # The y scale is reversed because in image the vertical positive direction is typically downward
# Also note the limits where h>0 is the first parameter.
coord_equal() + # To keep the aspect ratio of the image.
stat_bin2d(binwidth=2,aes(fill = ..density..)) +
scale_fill_gradient(low = "dark red", high = "red")
)
df<-data.frame(x=rnorm(100000,100,w/70),y=rnorm(100000,400,h/100))
plot(ggplot(df, aes(x,y)) +
annotation_custom(grid::rasterGrob(img, width=unit(1,"npc"), height=unit(1,"npc")), 0, w, 0, -h) + # The minus is needed to get the y scale reversed
scale_x_continuous(expand=c(0,0),limits=c(0,w)) +
scale_y_reverse(expand=c(0,0),limits=c(h,0)) + # The y scale is reversed because in image the vertical positive direction is typically downward
# Also note the limits where h>0 is the first parameter.
coord_equal() + # To keep the aspect ratio of the image.
stat_bin2d(binwidth=2,aes(fill = ..density..)) +
scale_fill_gradient(low = "dark red", high = "red")
)