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

如何提取图片最常用颜色?PIL/ColorThief返回值异常

为啥PIL和ColorThief提取的图片主色和你实际看到的不一样?

嘿,我来帮你拆解这个问题——你说图片里98%都是#f6f6f6,但PIL和ColorThief返回的结果偏差这么大,其实核心是这俩工具的颜色统计逻辑完全不一样,跟你预期的“找出现最多的颜色”不是一回事儿。

先说说PIL的问题

你用PIL的getcolors()得到的是精确到单个像素的RGB值统计,啥意思呢?就是哪怕两个颜色只差1个通道值(比如#f6f6f6和#f7f7f7),它都会当成两种完全不同的颜色分开算。

那为啥它返回纯白(#ffffff)是最多的?大概率是这两种情况:

  • 你图片里的#f6f6f6其实是一堆接近但不完全相同的像素(比如#f4f4f4到#f8f8f8之间波动),这些像素被PIL拆成了N个小条目,每个的数量都没纯白多;
  • 你可能没把图片转成RGB模式就统计了——如果图片带Alpha通道(RGBA),PIL会把RGBA四元组当成不同颜色,导致统计结果混乱。

再聊聊ColorThief的问题

ColorThief的思路就不一样了,它是用中位切分法做颜色聚类,目的是找“最有代表性的颜色”,而不是“出现次数最多的颜色”。而且它默认会把图片缩小到100x100像素来提高速度,这一缩就把很多细节丢了,原本的#f6f6f6可能被聚类成了更接近的#f3f3f3。另外它默认提取的是6种代表性颜色,第一个颜色未必就是出现次数最高的那个。

怎么调整才能得到正确结果?

针对PIL的解决方案

你需要先把颜色“合并同类项”,也就是做颜色量化,把接近的颜色归为一类:

from PIL import Image

# 打开图片并转成RGB模式(去掉Alpha干扰)
img = Image.open("你的图片.jpg").convert("RGB")
# 把颜色量化成16种(数量可以自己调,越少合并得越狠)
quantized_img = img.quantize(colors=16)
# 统计量化后的颜色出现次数
color_counts = quantized_img.getcolors()
# 按次数从多到少排序
color_counts.sort(reverse=True, key=lambda x: x[0])
# 获取占比最高的颜色
top_color = quantized_img.palette.getcolor(color_counts[0][1])
# 转成十六进制格式
hex_color = f"#{top_color[0]:02x}{top_color[1]:02x}{top_color[2]:02x}"
print(f"实际占比最高的颜色:{hex_color}")

针对ColorThief的解决方案

让它别缩小图片,用原始尺寸采样,这样能保留更多细节:

from colorthief import ColorThief

ct = ColorThief("你的图片.jpg")
# quality=1表示不缩小图片,用原始像素采样
dominant_color = ct.get_color(quality=1)
hex_color = f"#{dominant_color[0]:02x}{dominant_color[1]:02x}{dominant_color[2]:02x}"
print(f"提取的主色:{hex_color}")

如果还是不满意,也可以用它提取所有颜色的像素统计,再自己筛选出现次数最多的。

一句话总结

你要的是“出现次数最多的精确颜色”,但PIL默认给的是“精确像素的单独统计”,ColorThief给的是“代表性聚类颜色”——调整一下工具的使用方式,就能和你的预期对上啦~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 09:02:59