Last active
December 11, 2015 23:28
-
-
Save atbradley/4676470 to your computer and use it in GitHub Desktop.
R functions for reading images and analyzing colors in images. Demo at http://www.nottamuntown.com/2013/02/reading-images-in-r.html .
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
library(reshape) | |
library(ggplot2) | |
library(ReadImages) | |
ccodes <- read.csv('http://sandbox.adamtbradley.com/colors/') | |
#From http://is-r.tumblr.com/post/36586614678 | |
#Read an image from the web and shape it into a data.frame. | |
#codeColors() uses this--I don't call it directly. | |
imageLoader <- function(f) { | |
download.file(f, "tempPicture.jpg", mode = "wb") # Stash image locally | |
readImage <- read.jpeg("tempPicture.jpg") | |
longImage <- melt(readImage) | |
rgbImage <- reshape(longImage, timevar = "X3", | |
idvar = c("X1", "X2"), direction = "wide") | |
rgbImage$X1 <- -rgbImage$X1 | |
return(rgbImage) | |
} | |
#Use imageLoader() to grab an image, then do some | |
#postprocessing--rename the columns, get each pixel's | |
#RGB color code, round each color to its nearest websafe | |
#equivalent then figure out what simple color name | |
#describes each pixel. | |
codeColors <- function(image_url) { | |
#TODO: some kind of caching. | |
img <- imageLoader(image_url) | |
#img$X1 = -img$X1 | |
colnames(img) <- c('Y', 'X', 'R', 'G', 'B') | |
img$rgb <- rgb(img$R, img$G, img$B) | |
#Round each pixel color to the nearest "websafe" color. | |
img$rounded <- rgb(round(img$R/2, 1)*2, | |
round(img$G/2, 1)*2, | |
round(img$B/2, 1)*2) | |
codes <- data.frame(colorID=sub('#', '', img$rounded)) | |
codes <- join(codes, ccodes, 'colorID') | |
img$code <- codes$colorCode | |
img | |
} | |
#Make a url to an Amazon product image. | |
amzImage <- function(asin) { | |
sprintf('http://images.amazon.com/images/P/%s.01.LZ', asin) | |
} | |
#Shortcut to code a book cover by ISBN. | |
codeCover <- function(isbn) { | |
codeColors(amzImage(isbn)) | |
} | |
#Plot an image. img is the output of codeImage() or codeCover() | |
plotImage <- function(img, type="colors", min.pct.cols=.2, max.num.cols=F) { | |
if ( type == 'orig' ) { | |
with(img, plot(X, Y, col=rgb, | |
asp=1, pch='.', | |
ann=F, bty='n', | |
xaxt='n', yaxt='n')) | |
} | |
if ( type == 'rounded' ) { | |
with(img, plot(X, Y, col=rounded, | |
asp=1, pch='.', | |
ann=F, bty='n', | |
xaxt='n', yaxt='n')) | |
} | |
if ( type == 'code' ) { | |
#Remember that img$code is a factor. | |
with(img, plot(X, Y, col=as.character(code), | |
asp=1, pch='.', | |
ann=F, bty='n', | |
xaxt='n', yaxt='n')) | |
} | |
if ( type == 'colors' ) { | |
tmpimg <- imageColors(img) | |
plotImageColors(tmpimg, min.pct.cols, max.num.cols) | |
} | |
} | |
#Summarize a data.frame output from codeImage(). | |
#Used by plotImageColors() | |
imageColors <- function(img) { | |
outp <- summary(img$code) | |
data.frame(color=names(outp), count=outp, stringsAsFactors=FALSE) | |
} | |
#Called by plotImage(type='colors') | |
plotImageColors <- function(img, min.pct.cols=.2, max.num.cols=F) { | |
col_theme <- theme( | |
legend.position="none", | |
axis.title.x = element_blank(), | |
panel.background = element_rect(fill="white"), | |
axis.line = element_line(color="#000000"), | |
panel.grid.major.y = element_line(color="#CCCCCC"), | |
panel.grid.minor.y = element_line(color="#EEEEEE"), | |
panel.grid.major.y = element_blank(), | |
panel.grid.minor.y = element_blank() | |
) | |
if ( is.numeric(min.pct.cols) ) { | |
#Ignore colors that are only a tiny fraction of the image. | |
img <- img[img$count > (sum(img$count)*(min.pct.cols/100)),] | |
} | |
if ( is.numeric(max.num.cols) ) { | |
img <- img[order(img$count, decreasing=T),] | |
img <- img[1:max.num.cols,] | |
img <- img[order(img$color),] | |
} | |
fillscale = rgb(t(col2rgb(img$color)), maxColorValue=255) | |
#A better brown. | |
fillscale[img$color=='brown'] = '#4c2722' | |
#A darker grey. | |
fillscale[img$color=='grey'] = '#888888' | |
#Put a grey line around the white bar so we can see it. | |
linescale = fillscale | |
linescale[linescale=='#FFFFFF'] = '#999999' | |
plt <- ggplot(img) + col_theme + | |
ylab("Number of Pixels") + | |
geom_bar(aes(color, count, fill=color, | |
colour=color), | |
stat="identity") + | |
scale_fill_manual(values=fillscale) + | |
scale_colour_manual(values=linescale) | |
plt | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment