Android 获取图像主色:Palatte 调色板

相关名词:

  1. 主色:图像区域的主要颜色
  2. 色样(Swatch):一段相近的颜色区间
  3. 饱和度:色彩的鲜艳程度。饱和度越高,越逼近于原始色,饱和度越低,颜色越接近于白色。

引入方式:

implementation 'androidx.palette:palette:1.0.0'

场景:

如下图所示,可以根据网易云歌曲封面图的主色(或之一)对文字、背景颜色、图案颜色进行定制化处理。

 六种主色及其含义:

  1. Vibrant (有活力的): 具有既不亮也不暗高饱和度的颜色

  2. Vibrant dark(有活力的 暗色): 具有高饱和度的颜色

  3. Vibrant light(有活力的 亮色): 具有高饱和度的颜色

  4. Muted (柔和的): 具有既不亮也不暗低饱和度的颜色

  5. Muted dark(柔和的 暗色): 具有低饱和度的颜色

  6. Muted light(柔和的 亮色): 具有低饱和度的颜色

总之,6种主色主要靠饱和度和亮度进行区分,在代码中可以看到,platte对亮、暗、既不亮也不暗的区分如下:

也即:

platte使用方法

初始化

platte提供两种初始化方式,分别是同步和异步

 // SynchronousPalette p = Palette.from(bitmap).generate();// AsynchronousPalette.from(bitmap).generate(new PaletteAsyncListener() {public void onGenerated(Palette p) {// Use generated instance}})

色样Swatch

Swatch是Platte定义的静态类,提供获取RGB颜色空间下的主色、Hsl颜色空间下的主色文字标题色文字内容色等方法。

  • public int getRgb()

  • public float[] getHsl()

  • public int getTitleTextColor()

  • public int getBodyTextColor()

实现原理

1. 对图像建立颜色直方图

2.直方图量化为16个颜色区域

3.对每个区域生成一个色样

4.计算每个色样在6个主色下的得分

5.返回不同主色下得分最高的色样

直方图化

/**
* Execute color quantization.
*
* @param pixels histogram representing an image's pixel data
* @param maxColors The maximum number of colors that should be in the result palette.
* @param filters Set of filters to use in the quantization stage
*/
public void quantize(final int[] pixels, final int maxColors, final Palette.Filter[] filters) {mFilters = filters;// 2^15final int[] hist = mHistogram = new int[1 << (QUANTIZE_WORD_WIDTH * 3)];for (int i = 0; i < pixels.length; i++) {final int quantizedColor = quantizeFromRgb888(pixels[i]);// Now update the pixel value to the quantized value              pixels[i] = quantizedColor;// And update the histogram              hist[quantizedColor]++;}// Now let's count the number of distinct colors         int distinctColorCount = 0;for (int color = 0; color < hist.length; color++) {if (hist[color] > 0 && shouldIgnoreColor(color)) {// If we should ignore the color, set the population to 0            hist[color] = 0;}if (hist[color] > 0) {// If the color has population, increase the distinct color count            distinctColorCount++;}}// Now lets go through create an array consisting of only distinct colors          final int[] colors = mColors = new int[distinctColorCount];int distinctColorIndex = 0;for (int color = 0; color < hist.length; color++) {if (hist[color] > 0) {colors[distinctColorIndex++] = color;}}if (distinctColorCount <= maxColors) {// The image has fewer colors than the maximum requested, so just return the colors             mQuantizedColors = new ArrayList<>();for (int color : colors) {mQuantizedColors.add(new Swatch(approximateToRgb888(color), hist[color]));}} else {// We need use quantization to reduce the number of colors              mQuantizedColors = quantizePixels(maxColors);}
}
  1. 新建直方图,用于记录将RGB888量化到RGB565后的颜色直方图。

  2. 统计不同颜色个数,(注:接近白色、黑色,或接近I线的红色则不计,并清空对应计数)

  3. 新建数组colors,长度为不同颜色的个数,用来存储直方图中数量不为0的颜色的索引。

  4. 如果不同颜色个数过少(少于16),那直接根据当前的不同颜色创建样式即可。

  5. 否则,将其量化为16种颜色并创建样式。

量化

在量化过程中,新建优先队列对量化后的结果进行存储,每次取出队首,然后拆分成两份后放入。量化以VBox为单位,VBox用于表示一段连续的颜色索引,并记录rgb三个通道最大值/最小值,开始将整个颜色作为放入一个VBox,然后置于优先队列中。每次拆分中,按照颜色个数均分成两份。最后计算每个VBox的平均颜色,由此新建Swatch并返回。在Swatch中字体颜色会根据平均颜色对黑色/白色的透明度进行计算。

 

 

打分

对于指定主色类型,将对每个hsl在指定范围内对swatch进行打分,并选择分数最高者。(如果都不在范围内,那么返回空)

   /*** Returns the dominant swatch from the palette.** <p>The dominant swatch is defined as the swatch with the greatest population (frequency)* within the palette.</p>*/@Nullablepublic Swatch getDominantSwatch() {return mDominantSwatch;}@Nullableprivate Swatch findDominantSwatch() {int maxPop = Integer.MIN_VALUE;Swatch maxSwatch = null;for (int i = 0, count = mSwatches.size(); i < count; i++) {Swatch swatch = mSwatches.get(i);if (swatch.getPopulation() > maxPop) {maxSwatch = swatch;maxPop = swatch.getPopulation();}}return maxSwatch;

待优化项

  1. 效率一般,对整个视频实时性不是特别友好(先分了16个色样,然后逐个判断色样是不是亮暗、是不是活泼柔和,然后返回。而不是一开始以亮暗、活泼柔和这个目标去筛选颜色)

  2. 一个色样拆分为两个时,仅仅是简单地以数量进行平均分,而不是寻找最优分类点(fisher、svm)

参考demo

https://github.com/DingMouRen/PaletteImageView

参考文献

根据一张图片获取主颜色的算法是什么样的? - 知乎

效果

测试图像

效果

运行时间

bitmap大小

平均执行时间

640*400*3

40ms

750*450*3

60ms

1920*1280*3

400ms

其他主色方法

  聚类

分类

本文链接:https://my.lmcjl.com/post/8866.html

展开阅读全文

4 评论

留下您的评论.