You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Pillow Image.get_colors()提取图像常见颜色结果异常问题

图像Top10常见颜色提取结果差异问题分析

问题背景

我用PIL编写了提取图像Top10常见颜色的代码,通过获取图像所有颜色后筛选出现次数最多的10种,但结果与在线工具完全不同,想排查是PIL颜色处理方式差异还是代码逻辑问题。

我的代码

from PIL import Image

img = Image.open(image_url)

all_colors = img.getcolors(maxcolors=100000)  # 获取图像所有颜色
top_10_colors = all_colors[:10]  # 取前10个作为初始列表

for color in all_colors[9:]:
    amount = color[0]
    top_indexes = []
    for top_color in top_10_colors:
        top_index = top_color[0]
        top_indexes.append(top_index)

    if amount > min(top_indexes):
        index = top_indexes.index(min(top_indexes))
        top_10_colors[index] = color

sorted_top_colors = sorted(top_10_colors, key=lambda x: x[0], reverse=True)

print(sorted_top_colors)
print(top_10_colors)

在线工具结果(从多到少排序)

rgb(49,49,49)   rgb(211,211,211)    rgb(67,67,67)   rgb(71,71,71)   rgb(61,61,61) rgb(79,79,79) rgb(166,82,19)  rgb(70,70,70)   rgb(65,65,65)   rgb(29,28,28)

我的结果(从多到少排序)

[(35, 35, 35), (41, 41, 41), (36, 36, 36), (34, 34, 34), (44, 44, 44), (33, 33, 33), (31, 31, 31), (42, 42, 42), (50, 50, 50), (32, 32, 32)]

示例图像

示例图像

问题原因

  1. getcolors()返回顺序不按计数排序:你直接取all_colors[:10]作为初始Top10列表是错误的,这个方法返回的(计数, 颜色)元组按图像像素扫描顺序排列,而非计数从高到低排序,导致初始列表都是随机的低计数颜色。
  2. 在线工具做了颜色聚类:在线工具返回的是合并相似颜色后的结果(比如把相近灰度色归为一类),而你的代码统计的是原始图像中每个精确RGB值的单独出现次数,这是结果差异的核心原因之一。
  3. 筛选逻辑依赖错误初始值:即使后续循环试图替换低计数颜色,由于初始列表本身就不具备参考性,最终结果无法反映真实的高频颜色。

修正方案

方案1:统计精确高频颜色

直接对getcolors()结果按计数降序排序后取前10,无需复杂循环:

from PIL import Image

img = Image.open(image_url)
# 用图像总像素数设置maxcolors,避免颜色截断
total_pixels = img.width * img.height
all_colors = img.getcolors(maxcolors=total_pixels)

# 按出现次数降序排序
sorted_colors = sorted(all_colors, key=lambda x: x[0], reverse=True)
# 获取Top10颜色(包含计数)
top_10_with_count = sorted_colors[:10]
# 仅提取RGB值
top_10_rgb = [color[1] for color in top_10_with_count]

print("Top10颜色(含计数):", top_10_with_count)
print("Top10RGB值:", top_10_rgb)

方案2:颜色聚类(贴近在线工具结果)

如果想和在线工具结果一致,需要对像素颜色做聚类,合并相似颜色:

from PIL import Image
import numpy as np
from sklearn.cluster import KMeans

img = Image.open(image_url)
# 转换为像素数组
pixels = np.array(img).reshape(-1, 3)
# K-means聚类成10类
kmeans = KMeans(n_clusters=10, random_state=42)
kmeans.fit(pixels)
# 获取聚类中心(合并后的颜色)
cluster_colors = kmeans.cluster_centers_.astype(int)
# 统计每类像素数量
counts = np.bincount(kmeans.labels_)
# 按数量降序排序
sorted_clusters = sorted(zip(counts, cluster_colors), key=lambda x: x[0], reverse=True)
# 输出结果
for count, color in sorted_clusters:
    print(f"rgb{tuple(color)}: {count}次")

内容的提问来源于stack exchange,提问作者Aadvik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 15:17:16