提取图片中渐变色的颜色构成比例,核心思路是先读取图片的像素数据,再对颜色进行聚类分组,最后统计每个颜色组的像素占比,就可以得到对应的构成比例。

实现前的准备
我们需要用到PIL库读取图片,numpy处理像素数组,sklearn的KMeans算法做颜色聚类,如果还没安装这些依赖,可以先执行下面的安装命令:
pip install pillow numpy scikit-learn
完整实现步骤
1. 读取图片并转换像素数据
首先使用PIL读取目标图片,将图片转换为RGB模式,再把像素数据转换为二维数组,每一行代表一个像素的RGB值:
from PIL import Image
import numpy as np
def load_image_pixels(image_path):
# 打开图片并转换为RGB模式
img = Image.open(image_path).convert("RGB")
# 缩小图片尺寸,减少计算量,同时保留颜色特征
img = img.resize((200, 200))
# 转换为numpy数组,形状为(高度, 宽度, 3)
pixels = np.array(img)
# 重塑为二维数组,每个元素是( R, G, B )的列表
pixels = pixels.reshape(-1, 3)
return pixels
# 测试读取
pixels = load_image_pixels("test_gradient.png")
print(f"总像素数: {len(pixels)}")
2. 对颜色进行聚类分组
渐变色本质上是多个相近颜色的过渡,我们可以使用KMeans算法把相近的颜色归为同一类,聚类的数量可以根据渐变色的复杂度调整,一般渐变色3-8个聚类就可以覆盖主要颜色:
from sklearn.cluster import KMeans
def cluster_colors(pixels, n_clusters=5):
# 初始化KMeans模型
kmeans = KMeans(n_clusters=n_clusters, random_state=42, n_init=10)
# 训练模型并预测每个像素的聚类标签
labels = kmeans.fit_predict(pixels)
# 获取每个聚类的中心颜色值,转换为整数
cluster_centers = kmeans.cluster_centers_.astype(int)
return labels, cluster_centers
# 聚类,假设渐变色有5个主要颜色
labels, centers = cluster_colors(pixels, n_clusters=5)
3. 统计每个颜色的占比
统计每个聚类标签出现的次数,除以总像素数就可以得到每个颜色的构成比例,同时可以把RGB值转换为十六进制方便查看:
def calculate_color_ratio(labels, centers, total_pixels):
# 统计每个聚类的像素数量
unique_labels, counts = np.unique(labels, return_counts=True)
color_ratio_list = []
for label, count in zip(unique_labels, counts):
# 计算占比
ratio = count / total_pixels
# 获取当前聚类的中心颜色
rgb_color = tuple(centers[label])
# 转换为十六进制颜色值
hex_color = "#{}".format("".join([f"{c:02x}" for c in rgb_color]))
color_ratio_list.append({
"rgb": rgb_color,
"hex": hex_color,
"count": count,
"ratio": round(ratio, 4)
})
# 按占比从高到低排序
color_ratio_list.sort(key=lambda x: x["ratio"], reverse=True)
return color_ratio_list
# 计算占比
total_pixels = len(pixels)
result = calculate_color_ratio(labels, centers, total_pixels)
# 打印结果
print("渐变色颜色构成比例:")
for item in result:
print(f"颜色HEX: {item["hex"]}, RGB: {item["rgb"]}, 占比: {item["ratio"] * 100}%")
结果展示示例
假设我们处理一张从蓝色到绿色的渐变图片,可能得到如下结果:
| 颜色HEX值 | RGB值 | 像素数量 | 构成比例 |
|---|---|---|---|
| #1e90ff | (30, 144, 255) | 4800 | 12% |
| #3cb371 | (60, 179, 113) | 5200 | 13% |
| #20b2aa | (32, 178, 170) | 9600 | 24% |
| #00ced1 | (0, 206, 209) | 12400 | 31% |
| #00fa9a | (0, 250, 154) | 8000 | 20% |
注意事项
- 聚类数量n_clusters需要根据实际渐变色的复杂度调整,如果渐变色层次多可以适当增大这个值,否则会丢失细节
- 图片尺寸过大会增加计算时间,建议先缩小到合适尺寸再处理,不会影响颜色比例的准确性
- 如果渐变色中包含透明通道,需要先处理透明区域,比如把透明部分替换为白色背景再分析