前面连续做了图片清晰度检测和图像差异检测,这次继续做一个比较轻量的 OpenCV 小工具:
图片主色提取工具。
有时候我们看到一张图片,会很自然地觉得它"偏蓝""偏绿"或者"整体是暖色调"。
但如果想让程序自动回答:
这张图片主要由哪些颜色组成?每种颜色大概占多少?
就需要把图片里的大量像素颜色进行归类。
这次我使用 OpenCV + K-Means,实现了一个简单的:
Image Color Palette
上传一张图片后,自动提取 Top 5 主色,并显示:
- 颜色块
- RGB
- HEX
- 颜色占比
- 完整 Color Palette
一、为什么要提取图片主色?
一张普通图片可能包含几十万甚至上百万个像素。
每个像素都有自己的 RGB 值。
如果直接统计所有颜色,会得到非常多结果,而且很多颜色之间只差一点点。
比如天空区域可能同时包含:
浅蓝
蓝灰
亮蓝
偏白蓝
但从人的视觉角度看,它们其实都属于:
"天空这一组蓝色"
所以更合理的做法,是把相近的颜色聚在一起。
这就是这次使用 K-Means 的原因。
二、K-Means 在这里怎么用?
K-Means 本质上是一种聚类算法。
这次可以把每一个像素理解成一个三维数据点:
R
G
B
也就是:
(R, G, B)
然后让 K-Means 把所有像素分成 5 类。
这里设置:
K = 5
最终每一类都会得到一个聚类中心。
这个中心就可以看成:
这一组像素的代表颜色。
整体流程:
读取图片
↓
转换像素数据
↓
K-Means 聚类
↓
得到 5 个颜色中心
↓
统计每一类像素数量
↓
计算颜色占比
↓
按照占比排序
最后就能得到:
Top 5 Dominant Colors
三、这个工具做了哪些功能?
这次功能依然保持简单。
上传一张 JPG 或 PNG 图片以后,页面会自动显示:
原图预览
Top 5 Color Palette
RGB
HEX
颜色占比

同时 5 个主色会按照占比从高到低排列。
这样就能非常直观地看到:
一张图片整体上是什么颜色风格。
四、真实测试:公园里的狗狗图片
这次继续使用前面一直测试的狗狗图片。
图片里主要包含:
蓝天
绿色草地
树木
湖面
金黄色狗狗
从肉眼上看,本身就是一张颜色比较丰富的图片。
程序最终提取到了 5 个主色。

结果如下:
| 排名 | HEX | RGB | 占比 |
|---|---|---|---|
| 1 | #A1C8F0 | (161, 200, 240) | 25.78% |
| 2 | #B2A564 | (178, 165, 100) | 22.65% |
| 3 | #7F7D42 | (127, 125, 66) | 21.96% |
| 4 | #DAC59B | (218, 197, 155) | 15.29% |
| 5 | #4B4D1F | (75, 77, 31) | 14.32% |
五种颜色占比相加刚好为:
100%
五、这些颜色和原图对得上吗?
其实从结果就能看出比较明显的对应关系。
第一种颜色:
#A1C8F0
是比较明显的浅蓝色。
它主要对应:
天空
湖面
部分高亮区域
占比:
25.78%
也是整张图片中占比最高的一类颜色。
第二种:
#B2A564
偏黄绿色。
它主要来自:
草地
树木
部分狗狗毛发和地面区域
占比:
22.65%
第三种:
#7F7D42
属于更深一点的橄榄绿色。
主要对应:
树叶
阴影草地
远处植被
占比:
21.96%
第四种:
#DAC59B
属于浅米黄色。
这类颜色主要来自:
狗狗毛发
亮部草地
部分建筑和地面
占比:
15.29%
第五种:
#4B4D1F
是比较深的绿色。
主要来自:
树木阴影
深色植被区域
占比:
14.32%
所以虽然 K-Means 并不知道什么叫:
天空
草地
狗狗
但通过颜色聚类,最终结果和人眼对这张图片的整体感受是比较一致的。
六、为什么不是直接统计"出现最多的 RGB"?
如果直接统计 RGB 出现次数,结果往往并不好用。
因为真实图片里存在:
光照变化
压缩
阴影
渐变
噪声
同一个蓝色天空区域,可能包含很多不同的 RGB 值。
这些颜色看起来很接近,但数值并不完全一样。
如果逐个统计,就会把它们拆成很多小颜色。
K-Means 的作用,就是把这些:
相近的颜色聚成一组。
最终只保留几个代表色。
所以相比直接做像素频次统计,K-Means 更适合做:
图片主色提取。
七、RGB 和 HEX 为什么都显示?
这次页面里同时显示了:
RGB
和:
HEX
例如第一种颜色:
RGB:
(161, 200, 240)
HEX:
#A1C8F0
RGB 更适合程序和图像处理。
HEX 则在:
网页设计
UI 配色
CSS
平面设计
中更加常见。
所以把两种格式都显示出来,后面直接复制颜色会方便很多。
八、这个工具有什么实际用途?
虽然功能比较简单,但实际使用场景还挺多。
图片配色分析
例如看到一张自己喜欢的照片,可以快速提取它的主要颜色。
然后作为:
PPT
海报
网页
UI
的配色参考。
封面设计
如果想让文字、按钮或者装饰元素和原图风格统一,就可以先提取主色。
然后直接使用对应的 HEX。
数据集分析
做计算机视觉任务时,也可以用主色分布简单观察不同图片之间的色彩差异。
图片自动分类
后面如果继续扩展,还可以根据颜色分布把图片简单分成:
偏蓝
偏绿
偏暖
偏暗
等类别。
九、K-Means 也有局限
主色提取并不是说:
这 5 个颜色就是图片中唯一存在的颜色。
实际上,原图里仍然包含大量不同 RGB。
K-Means 只是把这些像素压缩成:
5 个代表颜色。
另外,K 值也会直接影响结果。
如果:
K = 3
得到的是更加概括的主色。
如果:
K = 10
结果会更加细致。
这次选择:
K = 5
主要是因为既不会过于粗略,也不会让页面出现太多颜色。
比较适合做一个简单的 Palette。
十、这次项目依然保持"小而完整"
最近几篇我没有继续做特别复杂的大系统,而是想尝试这种:
一个文章解决一个具体问题。
这次技术也很简单:
Python
OpenCV
FastAPI
原生 HTML / CSS / JavaScript
不需要:
深度学习模型
数据库
登录系统
复杂前端框架
上传一张图片以后,几秒内就能直接得到颜色分析结果。
对于这种小工具来说已经足够了。
总结
这次完成了一个基于 OpenCV K-Means 的图片主色提取工具。
核心流程:
图片
↓
像素 RGB
↓
K-Means
↓
5 个 Cluster
↓
Color Center
↓
颜色占比
↓
Top 5 Palette
真实测试中,这张狗狗图片最终提取出的主色分别为:
#A1C8F0 --- 25.78%
#B2A564 --- 22.65%
#7F7D42 --- 21.96%
#DAC59B --- 15.29%
#4B4D1F --- 14.32%
结果基本对应:
蓝天
草地
植被
狗狗毛发
阴影区域
也说明 K-Means 用来做简单的图片主色分析还是非常直观的。
前面几篇分别解决了:
图片糊不糊?
两张图片哪里不一样?
这一篇则回答:
这张图片主要是什么颜色?
下一篇可以继续做一个同样简单的 OpenCV 小工具:
图片拍歪了怎么办?用 OpenCV 做自动倾斜检测与纠偏。