如何确定图像精准颜色量化的主色数量K以最小化调色板
提问:如何自动确定图像颜色量化所需的主色数量K
我正在尝试对图像进行颜色量化,保留所有主色,去除抗锯齿边缘等次色。例如下方示例图像最终需量化为3种颜色,但原图实际颜色数超过30种。所有抗锯齿边缘色、因过度优化产生的会增加图像颜色数的JPEG伪影,均属于需在量化时消除的次色。注意:源图像可为png或jpeg格式。

量化操作我目前使用PIL.quantize(...)实现,传入参数K为需保留的颜色数量,该方法效果较好,可使输出调色板与原图完美匹配。
def color_quantize(path, K): image = cv2.imread(path, cv2.IMREAD_UNCHANGED) img = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) im_pil = Image.fromarray(np.uint8(img)) im_pil = im_pil.quantize(K, None, 0, None) return cv2.cvtColor(np.array(im_pil.convert("RGB")), cv2.COLOR_RGB2BGR)
若我能提前得知主色数量“K”,即可直接传入im_pil.quantize(...)使用。目前我需要找到获取该“K”值的方法,请问有没有途径可以确定图像的主色数量?
另外关于JPEG伪影去除,我目前使用img = cv2.bilateralFilter(img, 9, 75, 75),效果较好。
回答
自动确定主色数量K的可行方案
你可以根据业务场景选择以下两种方案计算K值,都可以直接适配你现有的处理流程:
方案1:颜色频率阈值过滤法(轻量高效,适合固定场景)
该方案逻辑简单、运行速度快,适合处理的图像风格统一的场景,步骤如下:
- 先运行你现有的双边滤波逻辑去除JPEG伪影,消除干扰色
- 统计预处理后图像所有像素的颜色出现频率,按从高到低排序
- 设定最小占比阈值(推荐初始值为0.5%~2%,可根据实际效果调整),依次累加颜色占比,直到下一个颜色的占比低于阈值,累加得到的颜色数就是K值
- 可以加兜底逻辑限制K的范围,比如最少保留2种、最多保留16种,避免极端情况出错
参考实现代码:
def get_main_color_count(img, min_ratio=0.01): # 入参img为经过双边滤波去伪影的RGB格式图像 pixels = img.reshape(-1, 3) # 统计所有唯一颜色的出现次数 unique_colors, counts = np.unique(pixels, axis=0, return_counts=True) # 按出现次数降序排序 counts = counts[np.argsort(-counts)] total_pixels = pixels.shape[0] k = 0 for cnt in counts: if cnt / total_pixels < min_ratio: break k += 1 # 兜底调整K的合理范围,可按需修改上下限 return max(2, min(k, 16))
方案2:肘部法则+K-means聚类(精度更高,适配通用场景)
如果处理的图像类型不固定、主色占比差异不大,可以用这个方案获取更精准的K值:
- 先完成去伪影预处理
- 对图像像素点运行K从2到最大预设值(比如16)的K-means聚类
- 计算每个K对应的聚类内平方和(SSE),找到SSE下降速率突然变缓的拐点,对应的K就是最优主色数量
该方案计算量稍大,但适配性更强,适合图像风格多变的业务场景。
流程优化建议
建议你把去伪影步骤放到K值计算和颜色量化之前,先过滤掉JPEG伪影和边缘抗锯齿色的干扰,计算出来的K值会更准确,最终量化效果也更好。
内容的提问来源于stack exchange,提问作者Greg
相关产品推荐
相关产品推荐

