赤橙黄绿青蓝紫
谁持彩练当空舞
颜色识别并不是一件难事,难的是他的使用场景
如果识别的是这样的纯色那便丝毫不用讲,毕竟颜色是有标准的表示形式的,rgb就是其中的一种
那如果是这样的呢
如果你需要面对的问题是识别一套服装或者其他物体的颜色信息,以此来判定他的颜色风格。那么这个问题就值得斟酌一下了。
严格来说上面那两张图片不算是严格意义上来讲的服装,用服装材质来形容或许更贴切一点。
就我看来,在系统层面用颜色来表达服装是个伪命题。
因为能影响颜色的东西实在太多了。
图片角度,或因为拍摄视角,或因为光影效果,或是因为其他种种原因都是有可能导致系统对服装颜色风格的识别出现偏差。
例如,一件笼罩在阴影下纯白色衣服,他所对应的rgb颜色就有可能是灰色甚至偏黑。
纹理角度,如豹纹,碎花类的衣物仅仅区分颜色显然是不合适的。
再比如一件白色的衣服但是他却在胸前印了一只超大的小猪佩奇,那么整件衣服的颜色识别下来可能出现粉红色面积大于白色的结果。
还有一些材质较为独特的衣物,如镂空衣物,这种衣物在图片上的颜色呈现效果极可能是阴影或者内搭的颜色面积盖过衣服本身。
所以对于衣服进行风格上的区分仅仅用颜色是不够的。
但是如果抛开纹理图案或是材质的因素,那么本文讲述的内容还是具有参考意义的。
那么颜色识别要怎么入手呢!easy先颜色后识别
颜色
颜色是一切的开头,没有颜色还识别个什么。
首先解决的问题是取出颜色,从哪儿取呢!图片呗,图片是由像素点组成的,核心思想是通过图片的长宽遍历出图片的所有像素点,再并取得对应像素点的颜色信息。
java中取颜色不是难事,加载图像并将其转为BufferedImage对象就可以很容易的取出rgb颜色信息。
RGB颜色
rgb颜色是三个十进制数组成,最大值为255,最小值为0,如:rgb(255,0,0)
排列组合一下,你就会发现rgb颜色的组成可能性多的令人头皮发麻。
所以若想对颜色进行识别并区分就必须定义一个标准,就是告诉系统什么值代表什么颜色,比如在某值到某值之内均为蓝色等等。
那么我们现在面临问题有两个,一是如何定义一个行之有效的颜色标准,而是如何更简洁的操作rgb数值,同时对三个数字进行范围划分太过繁琐。
或许是漫不经心又或许是天注定,我找到了这样的一个东西
我从html的相关资料中找到了这样的一份标准颜色表
参考链接http://www.w3school.com.cn/html/html_colors.asp
这看起来是个好东西,所以我们就拿来主义一下吧!
可能有人会问色块上那一串串乱七八糟的字符是什么
熟悉css的人可能一眼就看出来了,这就是rgb,这是rgb的十六进制表现形式,比起十进制这种形式显然身段更为优美
他们之间的换算规则如下
颜色的事情搞定了接下来就该考虑识别了
识别
既然有了标准那么识别的原则就是颜色归类,将不再标准中的颜色处理成符合标准的颜色
怎么处理呢!
仔细观察上面的色块及对应的rgb值,你会发现一个有意思的现象,颜色表上的颜色是从小到大排列的,且每个色块之间的差值的固定的33(十进制是51)
不管是r,g,还是b他们只有6种值,分别是"00","33","66","99","cc","ff"。这六个值和"33"(十进制是51)的倍数关系分别为0,1,2,3,4,5
通过数值和倍数关系我们可以设计一种计算规则
将倍数与标准色值进行一一对应
0代表"00"
1代表"33"
2代表"66"
3代表"99"
4代表"cc"
5代表"ff"
在十进制范畴内,将一个十进制数除以51得出倍数关系,再通过这个倍数关系取得该十进制数所对应的标准色值
以255为例,255/51=5。5的对应色值即为"ff"
当然255是个特例,因为255本身就是就是一个标准色值。在遇到非标准色值时,我的原则是离谁近就归谁。
以128为例,128/51=2.327......,这个时候使用四舍五入大法得出倍数是2对于色值就是"66"。
当然如果嫌这种方式绕,也可直接将十进制转为十六进制,在与标准色值比对。
好了,标准有了,方法也有了接下来就该敲代码了
首先定义标准数据(这里所有常量方法均以static修饰,没什么特别原因,这是我写样例时的习惯)
接下来封装两个方法用于十进制和十六进制的互转
接下来关键方法,将十进制形式rgb转为符合标准颜色的十六进制字符串形式
再写一个工具方法,将BufferedImage 的getRGB方法的返回值转为rgb数组
核心方法都有了接下来该走流程了
首先取得某个路径下的图片,并将其转变为BufferedImage 形式顺便做一下压缩
这里使用了一个小工具Thumbnails一个方便实用的图片处理用具
详细请参考https://www.jianshu.com/p/ad8af8214e60
注意这里是size(100,100)并不是强制压缩,而是以最长边为基准的等比压缩。
定义一个map用于存储每个颜色所对应的像素数量
接下来就可以遍历取色了,这里不需要每个像素都遍历,隔一个像素取一个就可以了
到这一步我们就知道了这张图片一共有几个颜色且每个颜色共有多少个像素
接下来我们要做的就是取出所占比例最多的五种颜色
但是我们的colorCount是以颜色为key数量为value的。这样不方便排序。
那么我们就坐一个简单的操作,把colorCount的key跟value互换一下位置,再用一个集合存储数量信息,方便排序。
但是这么做的问题就是所占像素数量相同颜色信息在存储的时候会覆盖,这里我选择忽略这个问题,因为这种情况很少。
好了,代码写完,该跑几个案例了
网友评论