Skip to content

Instantly share code, notes, and snippets.

@atbradley
Last active December 11, 2015 23:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save atbradley/4676470 to your computer and use it in GitHub Desktop.
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 .
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