Shepard Fairey-fy images using k-means!

Want to learn how to turn

to

This is how:

# Code derived from that presented at Columbia University's STAT W4240
k.means.to.image <- function(im.mat, K, palette) {
  # image im.mat, number of clusters K # coerce image into matrix
  orig.dim <- dim(im.mat)
  new.im <- im.mat
  dim(new.im) <- c(orig.dim[1]*orig.dim[2],3)
  k.list <- kmeans(new.im,K) # Do K means!
  str(k.list)
  out.im <- mat.or.vec(orig.dim[1]*orig.dim[2],3)
  palette = col2rgb(palette) / 255
  
  # FIRST, FIND the average color that was mapped to k
  tmp <- aaply(k.list$centers, 1, each(min, max))
  lightness <- aaply(tmp, 1, mean)
  re_lit <- rank(lightness)
  
  for (k in 1:K){
      out.im[(k.list$cluster==k),1] <- palette['red', K + 1 - re_lit[[k]]]
      out.im[(k.list$cluster==k),2] <- palette['green', K + 1 - re_lit[[k]]]
      out.im[(k.list$cluster==k),3] <- palette['blue', K + 1 - re_lit[[k]]]}
  # Re-coerce new image to original size
  dim(out.im) <- orig.dim
  return(out.im)
}
 
require(jpeg); require(plyr)
## Loading required package: jpeg
## Loading required package: plyr
pic <- readJPEG("headshot.jpg")
shep_palette <- c("#FFF1C4", "#C2D8C5", "#60989B", "#00415D", "#E31C23")
writeJPEG(k.means.to.image(pic, 4, shep_palette), "shep_headshot.jpg")
## List of 9
##  $ cluster     : int [1:1004544] 4 4 4 4 4 4 4 4 4 4 ...
##  $ centers     : num [1:4, 1:3] 0.482 0.662 0.233 0.854 0.397 ...
##   ..- attr(*, "dimnames")=List of 2
##   .. ..$ : chr [1:4] "1" "2" "3" "4"
##   .. ..$ : NULL
##  $ totss       : num 174682
##  $ withinss    : num [1:4] 1304 2237 1431 1614
##  $ tot.withinss: num 6586
##  $ betweenss   : num 168097
##  $ size        : int [1:4] 111327 147347 137699 608171
##  $ iter        : int 3
##  $ ifault      : int 0
##  - attr(*, "class")= chr "kmeans"