zoukankan      html  css  js  c++  java
  • 之于图片主色调提取算法

    图片颜色量化算法,

    又称之为图片主色调提取算法。

    也可以称之为调色板提取算法。

    比较常见的应用就是用于提取图片的主色调用于上色配色,

    当然也可以用于图像分割。

    算法的主要目的是从真彩色图像所能表现的大约16M中颜色中选取最代表性或者出现频率最高的256种颜色。

    维基百科:

    https://en.wikipedia.org/wiki/Color_quantization

    相关细节,请参阅维基百科。

    经典的例子有:

    色调窃取:

    http://lokeshdhakar.com/projects/color-thief/

    比较有意思的做法就是用来做图片压缩,

    png格式中最高压缩比的算法就是基于颜色量化表实现的。

    相关项目:

    https://github.com/kornelski/pngquant

    感兴趣的同学可以,翻翻相应的代码,温故而知新。

    常见的颜色量化算法有:

    中位切分法(Median cut)
    Median-Cut Color Quantization
     

    八叉树算法(Octree)
    A Simple Method for Color Quantization: Octree Quantization
     

    聚类算法 (KMeans)
    Color Quantization using K-Means

    直方图量化(Histogram)

    Color Quantization using Histogram

    神经网络(Neural-Net)

    Optimal Colour Quantization using Kohonen Neural Networks

    当然算法还有很多,以及相关的变种。

     
     曾经做过一个需求,想要从一个图片中找到它的主体颜色然后显示出来,

    要有两个输出,

    一个是颜色的文字描述,一个是颜色的RGB值。

    颜色的文字描述很好解决,参照项目:

    Name that Color:

    http://chir.ag/projects/name-that-color/

    主要思路是建表查表,这个也没啥好说了,简单粗暴。

    而重点在于精准地找到颜色的RGB值,

    这一点,恕我直言,

    以上提及到的算法,都不能很好地精准描述到颜色的RGB值。

    相关开源项目很多,谷歌一下,github一下 关键词 Color Quantization,

    如果不死心的同学可以去做下试验,这里就不展开说了。

    这个跟人的视觉感官有关,我们的视觉焦点跟实际的数字颜色有差别。

    举个例子,万绿丛中一点红。

    明显周围都是绿,那一点红就显得很耀眼。

    而如果采用均值也好,切分也好,分类也好。

    是很难很好的描述那个耀眼的颜色。

    有一段时间,清闲的时候总在思考,如何更好地找到那个合适的颜色值。

    最终我从算法的核心,量化的思想出发。

    我是不是可以采用过筛子的方式进行逐步逼近结果呢?

    这个时候颜色相关的基础知识就显得尤为重要。

    转换颜色空间,进行量化是否可行,例如采用HSL或HSV色域。

    这个也不展开科普了,需要补课的同学,移步维基:

    https://zh.wikipedia.org/wiki/HSL%E5%92%8CHSV%E8%89%B2%E5%BD%A9%E7%A9%BA%E9%97%B4

    HSL和HSV都是一种将RGB色彩模型中的点在圆柱坐标系中的表示法。这两种表示法试图做到比RGB基于笛卡尔坐标系的几何结构更加直观。

    HSL即色相、饱和度、亮度(英语:Hue, Saturation, Lightness)。HSV即色相、饱和度、明度(英语:Hue, Saturation, Value),又称HSB,其中B即英语:Brightness。

    色相(H)是色彩的基本属性,就是平常所说的颜色名称,如红色、黄色等。
    饱和度(S)是指色彩的纯度,越高色彩越纯,低则逐渐变灰,取0-100%的数值。
    明度(V),亮度(L),取0-100%。

    大家观察一下这个图中的圆环。

    按照视觉感官来说,

    位于圆环中间的颜色区域就是视觉不敏感的地方。

    换句话来说,饱和度和亮度,我们都可以不考虑。

    只要考虑量化色相就可以基本得知颜色的分布。

    而量化的色相,还可以控制需要量化的精度,也就是,

    你可以针对色相进行进一步的细分。

    例如细分至1000等分,细分至10等分等等。

    这个就看具体需求了。

    名称颜色色光色料色相代码MS-DOS
    角度饱和明度
    红色   255 0 0 0 255 255 0 100% 100% #FF0000 12
    黄色   255 255 0 0 0 255 0 60° 100% 100% #FFFF00 14
    绿色   0 255 0 255 0 255 0 120° 100% 100% #00FF00 10
    青色   0 255 255 255 0 0 0 180° 100% 100% #00FFFF 11
    蓝色   0 0 255 255 255 0 0 240° 100% 100% #0000FF 9
    品红色   255 0 255 0 255 0 0 300° 100% 100% #FF00FF 13
    栗色   128 0 0 0 255 255 127 100% 50% #800000 4
    橄榄色   128 128 0 0 0 255 127 60° 100% 50% #808000 6
    深绿色   0 128 0 255 0 255 127 120° 100% 50% #008000 2
    蓝绿色   0 128 128 255 0 0 127 180° 100% 50% #008080 3
    深蓝色   0 0 128 255 255 0 127 240° 100% 50% #000080 1
    紫色   128 0 128 0 255 0 127 300° 100% 50% #800080 5
    白色   255 255 255 0 0 0 0 0% 100% #FFFFFF 15
    银色   192 192 192 0 0 0 63 0% 75% #C0C0C0 7
    灰色   128 128 128 0 0 0 127 0% 50% #808080 8
    黑色   0 0 0 0 0 0 255 0% 0% #000000 0

    看这图表比较形象一些。

    重点关注角度这个值。

    相关的计算方式就不展开了。

    这个比较基础。

    经过实验,验证采用色相进行量化是比较适宜的。

    具体算法就不贴出来了。

    大概的算法思路如下:

    1.确定需要量化颜色的精度,(0-360) 或者(0-60) 稍微换算一下即可。

    2.按照量化的精度,对图像进行色相直方图统计(要更加精准的话可以加入亮度或饱和度的直方图,最好把Name that Color的RGB值也进行直方图统计) 

    3.对直方图进行统计分析,排序以及平滑等

    4.通过2-3直方图进行评估确定对应的rgb值

    5.输出结果

    虽然可以完整地贴出示例代码,

    但是有时候,授人以鱼不如授人以渔。

    以上的思路,供有类似需求的同学参考之。

    若有其他相关问题或者需求也可以邮件联系俺探讨。

    邮箱地址是: 
    gaozhihan@vip.qq.com

  • 相关阅读:
    数学分析教材编写大纲
    鲁病案号1357324
    数据库-常见函数-分组函数
    Java中的快速输入输出
    数据库-数学函数
    IDEA 常用快捷键 (尚硅谷·宋红康 设置版)——高仿eclipse
    linux下网络死掉了肿么办?(Networking Disabled)
    zookeeper集群搭建
    WMware克隆虚拟机后出现网络无法连接的问题
    Partitioner编程——根据运营商分组统计用户上网流量
  • 原文地址:https://www.cnblogs.com/cpuimage/p/9017732.html
Copyright © 2011-2022 走看看