K-Means聚类在图片主色提取中的实现

说明主色提取要解决的实际问题

图片主色提取的目标,是从一张图的像素中找出 3~8 个代表颜色,生成可用于配色、设计参考或图片取色工具的主色板。输出不应只有几个色块,还应包含每种颜色的 HEX、RGB、像素占比,以及明确的排序依据。

直接按 RGB 数值排序并不能得到可靠的视觉主色。RGB 是设备相关的加色表示,8 位 RGB 通道通常取值为 0~255;两个颜色在数值上的距离,并不一定符合人眼感受到的颜色差异。例如,蓝绿色和绿色可能在某些通道上距离接近,但视觉上并不相似。

计算时也没必要处理原图的每一个像素。可以先将图片缩放到宽度 300~800 像素,或按固定间隔抽样,把每个保留下来的像素表示为一个颜色样本。这样能减少大图带来的计算量,同时保留背景、主体和明显的强调色。

把像素颜色映射到适合聚类的空间

RGB 适合保存和显示颜色,HSV 适合按色相、饱和度和明度理解颜色,CIE Lab 则更适合用距离近似视觉差异。Lab 中的 L* 表示明度,a*b* 表示颜色方向,因此主色聚类通常优先考虑 Lab,而不是直接在 RGB 上计算距离。

  • RGB:输出方便,适合转换为 #RRGGBB,但欧氏距离与视觉差异并不完全一致。
  • HSV:便于筛选高饱和色或按色相分组,适合交互式取色和规则化配色。
  • CIE Lab:更适合计算颜色间距离,但不同库的通道范围和编码方式必须核对。

实现时可以使用 Python、NumPy 和 OpenCV。读取图片后,先把 BGR 转为 RGB,再把像素排列为形状类似 (样本数, 3) 的矩阵;随后使用 OpenCV 转换到 Lab,或调用 scikit-learn 的 KMeans。OpenCV 的 8 位 Lab 通常采用编码后的通道范围,不能直接与使用浮点真实范围的其他库混用,转换前应确认文档中的范围定义。

抽样方式会影响结果。等比例缩放适合一般照片,随机抽样可以减少重复像素,固定步长采样则实现简单。小面积的高饱和标志、文字或装饰色,可能在抽样中被遗漏;如果这类颜色很重要,应提高采样密度,或保留一定比例的边缘和高饱和像素。

用 K-Means 计算颜色中心与主色占比

K-Means 可以理解为“把颜色样本分成 K 组,并不断调整每组的代表点”。每轮先把样本分配给距离最近的中心,再用每组样本的平均值更新中心,直到中心变化很小或达到迭代上限。

  1. 读取图片,处理透明通道,并缩放或抽样像素。
  2. 将 RGB 像素转换为 Lab,组成二维输入矩阵。
  3. 设定 K,使用 K-Means++ 初始化聚类中心。
  4. 反复执行样本分配和中心更新,直到收敛。
  5. 统计每个簇包含的像素数量,计算占比。
  6. 把 Lab 中心转换回 RGB,并格式化为 #RRGGBB

一个可复现实验配置是 max_iter=100n_init=10random_state=42。其中 max_iter 限制单次运行的最大迭代次数,n_init 表示用不同初始中心重复运行 10 次,算法通常选择簇内误差较小的结果;random_state=42 则固定随机过程,便于比较不同参数。

可以分别测试 K=3K=5K=8。每个簇的占比计算为该簇样本数除以总样本数,再按占比从高到低排序。要注意,聚类中心不是原始像素中出现次数最多的颜色,而是一个簇内样本的平均代表值,原图中可能不存在完全相同的像素。

调参数并生成可使用的主色板

K=3 通常得到背景、主体和一个强调色,但相近颜色容易被合并;K=5 往往能在简洁与细节之间取得平衡;K=8 能保留更多层次,却可能产生相近色或噪声色。具体效果取决于图片内容、抽样方式和所用色彩空间。

选择 K 值时,不要只看 K-Means 的误差下降。更实用的标准是检查主色板是否覆盖了背景、主体和具有视觉意义的强调色。若增加 K 后只是多出几个几乎相同的灰色或阴影色,继续增加聚类数量并没有帮助。

  • 在 Lab 中计算颜色距离,对距离过近的中心进行合并;阈值应根据项目需求测试,不能把某个固定数值视为所有图片通用。
  • 过滤占比低于 1%~3% 的簇,适合去除压缩噪声;但图标、文字等小面积重点颜色不应机械删除。
  • 默认按像素占比排序,设计场景也可以把高饱和强调色单独标记,避免它因面积小而排在末尾。
  • 透明背景应先依据 Alpha 通道处理,黑边则应裁剪或屏蔽,否则边框会被误判为主色。

与图片取色工具结合时,每个结果可以显示色块、HEX、RGB 和占比,并提供点击复制颜色值的操作。这样用户既能快速获得整体配色,也能继续手动检查某个局部区域。

最终结果不是唯一答案。色彩空间、抽样方式、K 值和随机初始化都会影响聚类结果,因此应把参数和处理流程一并保存;在同一批图片中比较时,至少固定 random_state=42、抽样规则和颜色转换方式。

更多推荐

从PDF矢量指令到像素网格 PDF页面不是一张固定分辨率的图片,而是一组绘制指令:路径、文字、嵌入图像、透明度、颜色空间以及它们之间的覆盖关系。栅格化的任务,是把这些指令按页面顺序计算出来,再映射到指定DPI的像素网格中;pdf文件转图片

了解更多 >

8×8 DCT 水印,先从两个中频系数开始 在基于 8×8 块离散余弦变换(DCT)的图像水印中,嵌入位置决定了压缩耐受性和视觉失真。可复现实验可以从亮度通道的 (2,3)、(3,2) 两个中频系数开始,用它们的差值承载 1 bit,再用

了解更多 >

Trimap 只缩小搜索范围,不直接生成透明度 Trimap(三分图)是一张给抠图算法的约束图:它把像素分为确定前景、确定背景和未知区。算法固定前两类像素的 Alpha 值,只在未知区估计连续的 Alpha matte,因此 Trimap

了解更多 >

用坐标网格控制水印平铺间距 平铺水印的核心不是复制很多份,而是建立可计算的坐标网格,让水印覆盖整张图片并保持稳定间距。下面用图片宽度 W、高度 H,以及单个水印的宽度 w、高度 h,说明间距、旋转和偏移如何组合,同时避免边缘被裁掉。 设水

了解更多 >

先用肤色阈值圈出候选区域 连通域分析不能直接认出人脸,它只能把二值图中相邻的前景像素分成若干块。实用流程是:先用肤色规则生成候选区域,再用面积、形状和位置筛选,最后对保留下来的区域打码;这套方法适合背景简单、光照稳定的图片,不适合承担低漏检

了解更多 >