AfarX

A Rookie of R.

使用R提取图像主要颜色

前言

Recently, I was amazed by the fantastic art of data visualization created by Namier and Shirley. Namier showed her working process of Cardcaptor Sakura, and I read the passages as below :

Using the imager package in R, I loaded the images into R where each pixel was transformed into a multidimensional array of RGBA values. I converted that complex array into a more simple data frame of (number of pixels) * 3 (for r, g, and b value) size. To figure out which algorithm would cluster the pixel values into decent colors groups I tried several things. First I experimented with using different clustering techniques: from the standard K-means, to hierarchical clustering and even tSNE. But I also converted the RGB values of each pixel into other color spaces (where colors have different “distances” to each other and can thus result into different clustering results), using, amongst others, the colorspace package.
I often converted the results of each test into a bar chart such as below to see the color groups found. Eventually, I found that using Kmeans together with the colors converted to “Lab” visually gave the best fitting results.

I thought though I am not famliar with D3.js (so hard, but I want to acknowledge it one day, as it is so coooool!), I have a basis of using R. So, I want to try those two packages, ‘imager’ and ‘colorspace’, to select main colors from a targeted picture, and maybe draw a bar chart like Nadieh had done.

包的介绍

imager

支持的图像文件格式

imager by itself can only load images in png, jpeg and bmp format. Install ImageMagick for more. If you want to load videos, install ffmpeg.

图像文件储存格式

How images are represented?
Images are represented as 4D numeric arrays, which is consistent with CImg’s storage standard (it is unfortunately inconsistent with other R libraries, like spatstat, but converting between representations is easy). The four dimensions are labelled x,y,z,c. The first two are the usual spatial dimensions, the third one will usually correspond to depth or time, and the fourth one is colour.

代码

通过下面这段简单的函数,我们可以快速实现导入图片并提取主要颜色~

加载包

1
2
library('imager')
library('colorspace')

定义函数

Define Funciton

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
imtobar <- function(im,n){
# 缩放图片,加快运算速度
zoomim <- resize(im,round(width(im)/10),round(height(im)/10))

# 降低图片清晰度,加快运算速度
zoomim<- isoblur(zoomim,2)

# 将图片转换为colorspace中RGB格式的数据
u <- RGB(
as.data.frame(R(zoomim))$value,
as.data.frame(G(zoomim))$value,
as.data.frame(B(zoomim))$value
)

# 将RGB格式转化为其他格式,如LAB,HSV,HSL等,这里参考Namier,我们使用LAB格式
ulab <- as(u,"LAB")
# 将colorspace类型的数据转化为矩阵(用于下一步聚类)
uu <- as.matrix(ulab@coords)

# 使用K-means聚类法对颜色进行聚类
km <- kmeans(uu,n)

# 得到聚类中心
mainc <- km$centers

# 将聚类中心重新转化为RGB颜色,用于绘图
col <- hex(LAB(mainc))

# 将画图区域分为两块,左边绘制图像,右边生成颜色条形图(不显示坐标轴)
par(mfrow=c(1,2))
plot(im)
# 如果不以聚类大小作为高度,可以rep(1,n),直接生成五个等高矩形
# xaxt="n" 可以实现不显示坐标横轴,yaxt="n"同理
barplot(sort(as.numeric(km$size)),col = col,yaxt="n",xaxt="n")

}

运行并导出结果

只要我们之前将函数定义好,每次只需要跑下面这段就可以了,如果不需要导出,那么两句代码就OK了~

1
2
3
4
5
6
7
8
# 导入图片
im <- load.image('e1.png')
# 定义导出图片类型,高度及宽度
png(file="e1b.png",width=600,height=300)
# 提取主要颜色(用我们刚才定义的imtobar函数)
imtobar(im,5)
# 关闭导出
dev.off()

现在让我们用几张我爱豆周彦辰的图片来测试下效果:
e1b
e2b
e3b

Good!基本满足要求!

我们可以考虑把聚类后的size和cluster都输出到json文件,进行下一步可视化~
框架见:Hamilton characters #2

今天也是周彦辰的追星女孩~!


参考文献

  1. Quick-start of imager
    http://dahtah.github.io/imager/imager.html#quick-start
  2. 图像特征提取原理
    https://wenku.baidu.com/view/16d8b11cad02de80d4d840db.html
  3. 用Python提取图片主要颜色
    https://blog.csdn.net/u010196573/article/details/16846173
  4. 图像颜色提取
    (关于颜色提取的算法讲的很清楚,推荐!)
    https://codepen.io/zhaojun/post/cc
  5. 图片主题色提取算法小结
    https://xcoder.in/2014/09/17/theme-color-extract/
  6. JS HEX十六进制与RGB, HSL颜色的相互转换
    http://www.zhangxinxu.com/wordpress/2010/03/javascript-hex-rgb-hsl-color-convert/
  7. How to create RGB image from three matrices in R?
    https://stackoverflow.com/questions/11306075/how-to-create-rgb-image-from-three-matrices-in-r