Let's draw a Pikachu in R!

Tue, Jan 25, 2022 3-minute read r

 

I have always been trying to do something fun with R not just for work. As I like drawing, I did some diggings online to check if it’s even possible to make drawings in R. Though R is powerful in data visualization, making graffiti is a different story. So far, the closest answer I could find is to use the package EBImage, which is dedicated to image processing and analysis. The package has an amazing function that can capture the mouse clicks on an image and record the corresponding coordinates. It reminds me of a game that I often played when I was a kid. I was not good at drawing at that time and tried to mimic other paintings, the way I did was to put a transparent paper on top of the picture, made strokes along the lines, then a perfect copy was done. I followed the same idea when drawing in R, first make mouse clicks along the silhouette of objects in an image and record the coordinates, then make use of the plot functions in R to connect the dots. Voila! Here is the Pikachu made in R!

Below is the R code applied to make the drawing. It’s also a good chance for me to review the basic R plot functions. Though they are now overshadowed by the popular ggplot functions, I still need to use them sometimes here or there in the projects, and they can be more convenient than ggplot functions in some cases.

## install package EBImage
# if (!requireNamespace("BiocManager", quietly = TRUE))
#   install.packages("BiocManager")
# BiocManager::install("EBImage")

## load library
library("EBImage")
## read in image
img <- readImage(files = "pikachu.png")

## get pikachu body points
## image will show up in the plot panel, click to select the points
## esc to exit
display(img, method="raster")
p_body <- locator()

## get pikachu eyes points
display(img, method="raster")
p_eye <- locator()

## get pikachu pupil points
display(img, method="raster")
p_pupil <- locator()

## get pikachu nose points
display(img, method="raster")
p_nose <- locator()

## get pikachu mouth points
display(img, method="raster")
p_mouth <- locator()

## get pikachu earband points
display(img, method="raster")
p_ear <- locator()
display(img, method="raster")
p_earpoint <- locator()
## save(p_body, p_eye, p_pupil, file = "pikachu.rda")

## this will be used to add image to plot
require(png)
addimg<-readPNG("pikachu.png")

## the upper and lower position of bander
bander <- seq(50,250, length = 300)
bander_up <- -(0.05*u-7)^2+60
bander_down <- -(0.05*u-7)^2+5

## draw pikachu!
## plot the body
plot(p_body$x, -p_body$y, type="o", cex = 0.1, pch = 5, ylim = c(-300, 50),
     asp = 1, # make a 1:1 ratio
     xlab = "", ylab = "", 
     axes = FALSE # no axises
     )
## fill in the bandar in yellow
polygon(c(bander, rev(bander)), c(bander_up ,rev(bander_down)), col = "yellow", bg="white")
## add the eyes
points(p_eye$x, -p_eye$y, type ="p", pch = 16, cex = 2)
points(p_pupil$x, -p_pupil$y, type ="p", pch = 21, cex = 1, col = "white", bg = "white")
## add the nose
points(p_nose$x, -p_nose$y, type ="p", pch = 21, cex = 0.2, col = "black")
## add the mouth
lines(p_mouth$x, -p_mouth$y, type ="o", pch = 21, cex = 0.1, col = "black")
## add the earband
points(p_ear$x, -p_ear$y, type ="p", pch = 16, cex = 1.5, col = "red")
points(p_earpoint$x, -p_earpoint$y, type ="p", pch = 16, cex = 1.2, col = "yellow")
## add the text
text(x=155, y=20, labels =c("I'm made in R"), srt = 0, col = "black")
## add arrow
arrows(0, -200, 50, -150, length = 0.1, code = 2)
## add the image
rasterImage(addimg,-100,-300, 0, -200)