救救小王吧:如何快速解决图像相似性检测问题?

相似性图像检测,是模型训练过程中常出现的问题,本文介绍了 4 个常用的哈希算法,并通过 Colab 代码,展示了完整的训练过程。

新晋炼丹师小王最近遇到了一个难题,愁的头发掉了好几根儿。

一问才知道,原来是他师傅给他分配了一个深度学习模型训练的任务,但是训练模型的图像数据集,略微有那么一丝丝复杂:

里边除了已有的公开数据集外,还包含一些从 Google、Bing 等网站上爬取的图像。

重复图像的存在,使得模型性能变得十分不可靠,毕竟:

* 重复图像将 bias 引入数据集,使得深度学习模型不得不学习重复图像的特定模式;

* 特定的学习模式,会使得深度学习模型概括新图像的能力下降。

手动删除重复图像,绝对不是最优解,原因是数据集中的图像数量动辄成百上千万,手动检查和删除会是一个非(丧)常(心)繁(病)琐(狂)的过程,将会耗费大量时间。

哈希算法成为小王最先想到的解决方案。

图像相似性检索,「哈希」一下

哈希算法是解决图像相似性检索的「魔法工具」,它可以对任意一组输入数据进行计算,得到一个固定长度的输出摘要(字符串)。

比较输出摘要,结果越接近,就说明图像越相似。

哈希算法具有以下特点:

* 相同的输入一定得到相同的输出;

* 不同的输入大概率得到不同的输出;

注意: 哪怕两张输入图像之间,只有一个字节之差,输出的哈希值也可能天差地别。

ImageHash Python 库中,常用的哈希算法包括 aHash、pHash、dHash 及 wHash。

 Average Hash (aHash):均值哈希算法,将图像切割成 8x8 的灰度图像,并依据像素值是否大于图像所有颜色的平均值,来设置哈希值中的 64 位。

aHash 计算速度快,不受图像尺寸大小影响,但对均值敏感,例如对图像进行伽马校正或直方图均衡会影响均值,从而导致报率,准确度无法保证。

df11dccee20abe84d74809051150ac9e.png
aHash 图像处理效果展示

 Perceptual Hash (pHash):感知哈希算法,与 aHash 类似,区别是 pHash 不依赖 average color,而是依赖离散余弦变换 (DCT),并依据频率 (frequency) 而非颜色值 (color value) 进行比较。

pHash 能避免伽马校正或颜色直方图被调整带来的影响,它准确率高、误报少,但计算速度比较慢。

f38d02204a89431cbd7e9ff2f185141c.png
pHash 图像处理效果展示

 Difference Hash (dHash):差异值哈希算法与 aHash 原理类似,只是不使用平均颜色值的信息,而是使用梯度(相邻像素的差异)。

dHash 算法运行速度与 aHash 相当,但误报率非常低。

3c00e91a17d02f91734a044b889d286e.png
dHash 图像处理效果展示

 Wavelet Hash (wHash):小波哈希算法,与 pHash 非常相似,但是 wHash 使用的是离散小波变换 (discrete wavelet transformation),而非 DCT。

wHash 比 pHash 更迅速,更准确,误报更少。

730087db5c75239412df6ace6a86b6a5.png
wHash 图像处理效果展示

不同哈希算法效果对比详见:TESTING DIFFERENT IMAGE HASH FUNCTIONS

善用轮子:用现成模块进行相似图像检测

作为一名合格的工程师,避免重复造轮子、提高开发效率,是小王一贯的追求。

经过搜索查找,小王发现了 Jina Hub 的 ImageHasher Executor

88fd482528e2c343fdd2a90a92918a14.png

查阅相关文档后小王发现,Executor 对应神经搜索系统中的不同模块,实现数据处理的核心功能,可以直接使用。

Flow 则对应整套神经搜索系统,它将多个 Executor 连接起来,构建成一套完整的搜索系统,轻松实现相似图像检测。

直接上代码:

!gdown --id 1wPg_Yx2ydcgsDA3BYO-Lw8ym5vjT0oQ3
!unzip data.zip -d images
! mkdir index
! mv images/*1.* index/
! mkdir query
!mv images/*.* query/
!pip install jina imagehash

创建一个索引 Document 的 Flow:

from jina import Flow
from docarray import Document, DocumentArray
import matplotlib.pyplot as plt
!rm -rf workspace

包含图像的 Document 将被编码成哈希值,接下来可以使用上述 4 种哈希算法中的任何一种,并用 SimpleIndexer 进行存储:

# Creating a DocumentArray object
docs_index = DocumentArray.from_files('index/*')
docs_index = [doc.load_uri_to_image_tensor() for doc in docs_index]


# Creating the indexing flow with ImageHasher and SimpleIndexer
flow = (
    Flow()
    .add(uses='jinahub://ImageHasher/v0.2', uses_metas={'hash_type': 'dhash'})
    .add(
        uses='jinahub://SimpleIndexer',
        uses_metas={'workspace': 'workspace'},
        uses_with={
            'match_args': {'limit': 1, 'metric': 'euclidean', 'use_scipy': True}
        },
    )
)


# Indexing the Documents using the flow
with flow:
    flow.post(on='/index', inputs=docs_index)
def print_matches(resp):
    for idx, doc in enumerate(resp.docs):
        print('-'*50)
        print(f'Query {idx + 1}')
        plt.imshow(doc.tensor)
        plt.show()
        for match in doc.matches:
            print('Matching query -->')
            plt.imshow(match.tensor)
            plt.show()

查询任何一个新的 Document,并在索引数据中找到匹配的 Document:

docs_query = DocumentArray.from_files('query/*')
docs_query = [doc.load_uri_to_image_tensor() for doc in docs_query]


# Using the same flow to find matches
# Opening the flow for incoming queries
with flow:
    flow.post(
        on='/search',
        inputs=docs_query,
        on_done=print_matches,
    )

整个过程跑下来,一起来看看小王的相似图像检测结果吧!

423797ddc5bb779f79651ca41efbb668.png
即使图像只是像素、滤镜或尺寸不同,也可以利用哈希算法检测出来

炼丹师小王利用 Jina Hub ImageHasher Executor,终于解决了数据集中的相似图像问题,并将代码都放到了 Colab 上

参与更多深度学习、哈希算法相关讨论,找到组织戳→Slack

热心小王期待大家的加入!


参考文献:

Imagehashing--Find duplicates 完整 Colab

ImageHasher Executor

廖雪峰的官方网站--哈希算法

相似图像检测方法

Testing different image hash functions

An image hashing library written in Python

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
预处理:读取图片 第一步,缩小尺寸。 将图片缩小到8x8的尺寸,总共64个像素。这一步的作用是去除图片的细节,只保留结构、明暗等基本信息,摒弃不同尺寸、比例带来的图片差异。 第二步,简化色彩。 将缩小后的图片,转为64级灰度。也就是说,所有像素点总共只有64种颜色。 第三步,计算平均值。 计算所有64个像素的灰度平均值。 第四步,比较像素的灰度。 将每个像素的灰度,与平均值进行比较。大于或等于平均值,记为1;小于平均值,记为0。 第五步,计算哈希值。 将上一步的比较结果,组合在一起,就构成了一个64位的整数,这就是这张图片的指纹。组合的次序并不重要,只要保证所有图片都采用同样次序就行了。 得到指纹以后,就可以对比不同的图片,看看64位中有多少位是不一样的。在理论上,这等同于计算"汉明距离"(Hammingdistance)。如果不相同的数据位不超过5,就说明两张图片相似;如果大于10,就说明这是两张不同的图片。 你可以将几张图片放在一起,也计算出他们的汉明距离对比,就可以看看两张图片是否相似。 这种算法的优点是简单快速,不受图片大小缩放的影响,缺点是图片的内容不能变更。如果在图片上加几个文字,它就认不出来了。所以,它的最佳用途是根据缩略图,找出原图。 实际应用中,往往采用更强大的pHash算法和SIFT算法,它们能够识别图片的变形。只要变形程度不超过25%,它们就能匹配原图。这些算法虽然更复杂,但是原理与上面的简便算法是一样的,就是先将图片转化成Hash字符串,然后再进行比较。 以上内容大部分直接从阮一峰的网站上复制过来,想看原著的童鞋可以去在最上面的链接点击进去看。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值