使用Python查找具有相似颜色调色板的图像

6
假设有一张相册中有1万个JPEG、PNG格式的图片,如何查找所有颜色调色板与所选图片相似的图片,并按相似度降序排列?

2
可能是重复问题:https://dev59.com/y0bRa4cB1Zd3GeqP27Vf - ChristopheD
是的,但是那个问题没有好的答案。 :-) - Frank Krueger
这里有很多类似的讨论: https://dev59.com/V3NA5IYBdhLWcg3wQ7Yw#1048723 - Paul
这里有另一个竞争者 https://github.com/larytet-py/image-mathching 该代码将匹配的颜色分组,并添加颜色组占据的面积百分比。 - Larytet
1个回答

11

为每个图像构建一个颜色直方图。当您想将图像与集合匹配时,只需按其直方图与所选图像直方图的接近程度对列表进行排序。

桶数取决于您想要多精确。用于创建桶的数据类型将定义如何优先考虑搜索。

例如,如果你最关心色调,则可以定义图像的每个单独像素属于哪个桶:

def bucket_from_pixel(r, g, b):
    hue = hue_from_rgb(r, g, b) # [0, 360)
    return (hue * NUM_BUCKETS) / 360

如果您还需要一个通用的匹配器,那么您可以基于完整的RGB值选择桶。

使用PIL,您可以使用内置的histogram函数。 "相似度"直方图可以使用任何想要的距离度量来计算。例如,L1距离可以如下计算:

hist_sel = normalize(sel.histogram())
hist = normalize(o.histogram()) # These normalized histograms should be stored

dist = sum([abs(x) for x in (hist_sel - hist)])

一个 L2 将是:

dist = sqrt(sum([x*x for x in (hist_sel - hist)]))

Normalize操作的目的是将直方图的总和强制设置为某个常数值(1.0效果很好)。这非常重要,因为这样可以正确比较大图像和小图像。如果您打算使用L1距离,则应在normalize中使用L1度量。如果使用L2,则使用L2。


@Frank,感谢您的建议。您能给我提供一些Python的示例代码吗?PIL内置的histogram()函数返回一个列表,如何确定两幅图像的直方图有多接近? - jack
@Frank,看起来在从10,000个候选图像中挑选出具有相似直方图的图像时需要进行10,000次距离计算?是否可以为每个图像关联数值并将它们存储在数据库中,这样比较就可以简化为一些SQL查询了呢? - jack
@jack,10,000次计算并不是很昂贵。加速这样的代码的最佳方法不是将直方图缩小为整数(无法按照您想象的方式完成),而是简单地缓存结果。在数据库中或内存中缓存排序顺序(每个图像),确保还将直方图存储在数据库或内存中,以便重建这些排序顺序缓存不会太昂贵。 - Frank Krueger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接