There seems to be several methods out there for reducing the colors in an image. I became interested in this after pondering how this is done in the excellent freeware program IrfanView. Unfortunately, their method is not described anywhere that I could find, but I imagine that it is something along the tree data structure collapse method that ImageMagick employes.
The biOps package employes the k-means clustering to arrive at a reduced number of colors. I find that while this method takes a bit longer, the results can actually look a lot better. Just for kicks, I imbedded the imgKMeans() function in another function called warholize() that replaces these reduced color levels with another set. It's definitly not a Warhol, but I still like the effect.
the function...
#this function reduces the colors in a jpeg file to k levels using #the biOps function imgKMeans() and replaces those colors with those #defined by the vector new.cols warholize <- function(filename,k=4,maxit=10,new.cols=NULL){ if(length(new.cols) != k) stop("length of new.cols must be equal to k") require(biOps) img <- imagedata(readJpeg(filename), type="rgb") img.red <- imgKMeans(img, k, maxit=maxit) col.names <- rgb(img.red[,,1],img.red[,,2],img.red[,,3],maxColorValue=255) col.unique <- unique(col.names) if(!is.null(new.cols) & is.character(new.cols)){ new.cols<-col2rgb(new.cols) dim.img <- dim(img) img.temp <- as.matrix(img) dim(img.temp) <- c(dim.img[1]*dim.img[2], dim.img[3]) col.num <- NA*1:length(col.names) for(i in 1:length(col.unique)){ temp <- which(col.names == col.unique[i]) col.num[temp] <- i } for(i in 1:3){ img.red[,,i] <- matrix(new.cols[i,col.num], dim.img[1], dim.img[2]) } } img.red }
...and the code to create the above image (original image from Wikimedia Commons)...
marilyn.warholized <- warholize("Marilyn_Monroe_in_The_Prince_and_the_Showgirl_trailer_cropped.jpg",k=3, new.cols=c("red", "blue", "white")) writeJpeg("marilyn.warholized.jpg",marilyn.warholized)
No comments:
Post a Comment