server程序员@IT·互联网

感知散列检测重复图像

2017-03-31  本文已影响140人  treelake

Duplicate image detection with perceptual hashing in Python

为了实现对大量图片的重复检测,我们用python实现了dHash感知散列算法和漂亮的BK树数据结构。

我们的网站有着近十五万的高清旅游照片,而且还在不断增加。这些照片来自各种来源,并以半自动的方式上传。所以经常有重复或几乎相同的照片,但是我们不希望我们的图片搜索页面充满重复。

所以我们决定使用感知散列算法(perceptual hashing)自动化过滤重复图片。感知散列就如普通哈希一样,它是一个比较大的数据片段的相对小的可比较的指纹。但它与典型的哈希算法不同在于,如果原始图像是相近的,感知散列值也"相近"(或相等)。

差分散列(dHash)

def dhash_row_col(image, size=8):
    width = size + 1
    grays = get_grays(image, width, width)

    row_hash = 0
    col_hash = 0
    for y in range(size):
        for x in range(size):
            offset = y * width + x
            row_bit = grays[offset] < grays[offset + 1]
            row_hash = row_hash << 1 | row_bit

            col_bit = grays[offset] < grays[offset + width]
            col_hash = col_hash << 1 | col_bit

    return (row_hash, col_hash)

重复的阈值

def get_num_bits_different(hash1, hash2):
    return bin(hash1 ^ hash2).count('1')

MySQL位计数

SELECT asset_id, dhash8
FROM assets
WHERE
    BIT_COUNT(CAST(CONV(HEX(SUBSTRING(dhash8, 1, 8)), 16, 10)
        AS UNSIGNED) ^ :dhash8_0) +    -- high part
    BIT_COUNT(CAST(CONV(HEX(SUBSTRING(dhash8, 9, 8)), 16, 10)
        AS UNSIGNED) ^ :dhash8_1)      -- plus low part
    <= 2                               -- less than threshold?

BK树与更快的重复检测

def add(self, item):
    node = self.tree
    if node is None:
        self.tree = (item, {})
        return

    while True:
        parent, children = node
        distance = self.distance_func(item, parent)
        node = children.get(distance)
        if node is None:
            children[distance] = (item, {})
            break

讨论

上一篇 下一篇

猜你喜欢

热点阅读