美文网首页
Java实现 提取图片主体颜色

Java实现 提取图片主体颜色

作者: 郭彦超 | 来源:发表于2020-07-01 11:50 被阅读0次

网上关于图片颜色识别的案例很少,能够直接拿来使用并产生很好效果的就更少,而且识别准确度差别很大;现在很多设计类网站为了降低用户筛选图片的难度都会提供图片颜色筛选的功能,如pixabay;再有我们经常使用的淘宝、唯品会这类电商app中颜色筛选也随处可见;易企秀作为一家专业的营销设计平台,这种技术能力也是不可或缺的。今天我就教大家一个简单,但高效的方法来进行图片颜色识别

大致思路介绍

众所周知彩色图片是3通道的,分别由R、G、B三原色组成,每个通道由256个值组成,如果不作处理将会有256^3=16777216中颜色,看到这个数字大家不要慌,静下来想一想看一看,在某个区间内连续值的颜色是很接近的,所以我们通常看到的图片是丰富多彩的,这么多色彩如果不作提取是很难在项目中进行应用的,今天我们要做的是从中找到核心颜色并进行有效提取。
首先,把三原色进行降维,将每种通道数值降维到6段区间,这样颜色的种类将变成6^3=216
为每一种颜色区间定义一种16进制颜色值,这里取中值:

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.509,这个时候使用四舍五入大法得出倍数是3对于色值就是"99";一个完成的例子,如RGB(202,0,106)换算后的16进制颜色为#CC0066
那么基于上述理论我们就可以为216种颜色定义字典编码,将他们映射到更加有限的颜色标签上,如#CC0066定义为浅红色


CC0066

实现

基于上述方案,216种字典码如下:

000 黑色
011 黑色
110 黑色
001 黑色
100 黑色
111 黑色
101 黑色
010 黑色
544 浅粉色
533 粉色
534 浅粉色
523 粉色
535 浅粉色
524 粉色
513 深粉色
525 粉色
514 深粉色
503 深粉色
515 深粉色
504 深粉色
554 白色
555 白色
545 白色
222 灰色
333 灰色
444 灰色
200 深红色
310 深红色
201 深红色
300 深红色
311 深红色
410 红色
520 浅红色
202 深红色
301 深红色
400 红色
411 红色
510 红色
312 浅红色
521 浅红色
401 红色
500 红色
511 红色
302 浅红色
412 浅红色
522 浅红色
501 红色
402 浅红色
512 浅红色
502 浅红色
440 浅橙色
430 深橙色
441 浅橙色
420 深橙色
431 深橙色
530 橙色
442 浅橙色
421 深橙色
432 深橙色
531 橙色
422 深橙色
532 橙色
550 黄色
540 深黄色
551 黄色
541 深黄色
552 浅黄色
542 深黄色
553 浅黄色
543 浅黄色
130 青色
230 深青色
054 青色
131 青色
033 深青色
231 深青色
055 青色
132 青色
154 浅青色
133 深青色
232 深青色
155 浅青色
233 深青色
255 浅青色
355 浅青色
455 浅青色
140 青色
141 青色
120 深青色
043 青色
142 青色
044 深青色
121 深青色
143 深青色
122 深青色
144 深青色
045 青色
225 深青色
050 绿色
150 绿色
051 绿色
030 深绿色
250 绿色
151 绿色
052 绿色
031 深绿色
251 绿色
152 绿色
053 绿色
350 浅绿色
032 深绿色
252 绿色
153 绿色
450 浅绿色
351 浅绿色
253 绿色
451 浅绿色
352 浅绿色
254 绿色
452 浅绿色
353 浅绿色
453 浅绿色
354 浅绿色
454 浅绿色
040 绿色
041 绿色
020 深绿色
240 绿色
042 绿色
340 深绿色
021 深绿色
241 绿色
341 深绿色
022 深绿色
242 绿色
342 深绿色
243 绿色
343 深绿色
012 深蓝色
034 浅蓝色
013 深蓝色
112 深蓝色
035 浅蓝色
134 浅蓝色
113 深蓝色
014 蓝色
135 浅蓝色
234 浅蓝色
015 蓝色
114 蓝色
235 浅蓝色
115 蓝色
023 深蓝色
002 深蓝色
024 蓝色
123 蓝色
244 浅蓝色
145 浅蓝色
003 深蓝色
102 深蓝色
025 蓝色
124 蓝色
344 浅蓝色
245 浅蓝色
223 浅蓝色
103 深蓝色
004 蓝色
125 蓝色
345 浅蓝色
224 浅蓝色
005 蓝色
104 蓝色
105 蓝色
212 深紫色
213 深紫色
334 浅紫色
214 深紫色
313 紫色
335 浅紫色
434 浅紫色
215 深紫色
314 紫色
413 紫色
435 浅紫色
315 紫色
414 紫色
415 紫色
323 浅紫色
203 深紫色
324 浅紫色
423 浅紫色
445 浅紫色
204 深紫色
303 紫色
325 浅紫色
424 浅紫色
205 深紫色
304 紫色
403 紫色
425 浅紫色
305 紫色
404 紫色
405 紫色
505 紫色
220 深棕色
330 浅棕色
210 深棕色
221 深棕色
320 棕色
331 浅棕色
211 深棕色
321 棕色
332 浅棕色
322 棕色
443 浅棕色
433 浅棕色 

以上编码映射是我的吐血整理,大家感觉有不合适的地方可自行调整

有了字典编码接下来我们就可以对图片进行颜色识别了吗?No, 因为现在的图片分辨率都很高,一张图片有上亿的rgb色块组成,没办法根据单一色彩进行识别,这里我的做法时图片缩放+描点+均值法(大家有更好的欢迎评论区回复)

  //输入一张图片 返回该图片的均值色彩
  public static Color getAvgRGB(URL url){ 
        BufferedImage bi = ImgUtil.toBufferedImage(ImgUtil.scale(ImgUtil.read(url),0.3f));
        int w = bi.getWidth();
        int h = bi.getHeight();
        float[] dots = new float[]{0.15f, 0.35f, 0.5f, 0.7f, 0.85f};
        int R = 0;
        int G = 0;
        int B = 0;
        for(float dw : dots){
            for(float dh : dots){
                int rgbVal = bi.getRGB((int)(w*dw), (int)(h*dh));
                Color color = ImgUtil.getColor(rgbVal);
                R += color.getRed();
                G += color.getGreen();
                B += color.getBlue();
            }
        }
        int cn = dots.length * dots.length;
        return  new Color(R/cn, G/cn, B/cn);
    }

描点的数量大家可以根据实际效果有所增加

拿到图片颜色之后就可以根据颜色值获取对应的颜色编码,然后根据编码去字典里查找对应的颜色标签


    public static String getTag(Color color){
        int r = Math.round(color.getRed()/colorAvgVal);
        int g = Math.round(color.getGreen()/colorAvgVal);
        int b = Math.round(color.getBlue()/colorAvgVal);
        String k = String.format("%s%s%s",r ,g ,b);
        return getTagFromDic(k);
    }

效果展示

image.png

相关文章

网友评论

      本文标题:Java实现 提取图片主体颜色

      本文链接:https://www.haomeiwen.com/subject/qgxdxktx.html