c4.5算法python实现_使用openCV和Python实现图像哈希(hash)算法

之前介绍了许多图像比对的算法,这里再介绍一个算法,叫感知哈希算法:perceptual hash algorithm, 它的作用是对每张图像生成一个“指纹”字符串,然后比较不同图像的指纹。结构越接近,说明图像越相似。

9940a8c45f4bc35cc058b8564bc5fe81.png

哈希算法步骤图解

这个算法常用于图像整理,归类上,比如快速整理手机中的照片文件夹子。该算法的优点明显,相对于其它算法实现起来比较简单,且速度快,准确率高。

图像哈希或者叫感知哈希包括以下两个过程:

1)检查图像内容

2)构造基于图像内容唯一标识,即输入图像的哈希值

最典型的应用比如TinEye,就是一种采用反向图像搜索引擎。用户可以:

1)上传图像

2)然后TinEye给出类似图像的网址

接下来我们将讨论:

1)图像散列(为什么传统散列不起作用)

2)实现图像散列,特别是差异散列(dHash)

3)将图像散列应用于实际问题和数据集

为什么我们不能使用md5,sha-1等?

84911832320a5f630df865b206c2083f.png

图2:在此示例中,我获取输入图像并计算md5哈希值。然后我将图像调整为宽度为250像素而不是500像素,然后再次计算md5哈希值。即使图像的内容没有改变,哈希也是如此。

具有密码学或文件验证背景的读者可能想知道为什么不能使用md5或sha-1等。这里的问题在于加密散列算法的本质:更改文件中的单个位将导致不同的散列。这意味着如果我们改变输入图像中单个像素的颜色,最终会得到一个不同的校验和,而事实上对于我们在图像感知层面上根本不觉得有什么不同。也就是说这个微小的改变我们是无法觉察的。

图2中的例子就说明这个问题,只是改变图像的大小,其它不变,计算图像的md5哈希,结构哈希值发生变化。在图像哈希情况下,我们实际上希望类似的图像具有类似的哈希值。

该项目的测试图像哈希数据集

该项目的目标是:

1)两个图像目录,dataset和query

2)确定query目录中的图像哪些已经在dataset中,哪些没有

使用图像哈希,我们可以快速完成这个任务。

了解图像哈希和差异哈希

dHash算法只有四个步骤

步骤一:转换图像为灰度

4bc95b5aabbf3988e4c800c363adc1e8.png

图3:通过差异散列算法进行图像散列的第一步是将输入图像(左)转换 为灰度(右)。

图像散列算法的第一步把输入图像转换成灰度并丢弃任何颜色信息。这样我们只需要检查一个通道,从而更快地散列图像,另外匹配相同但颜色空间略有变化的图像。无论出于何种原因,如果你对于颜色感兴趣,可以独立在每个通道上应用散列算法,然后在最后进行组合。

步骤二:调整大小

灰度图像后,把图像压缩到9 x 8像素,忽略纵横比。对于大多数图像和数据集,调整大小、插值步骤是算法中最慢的部分。

为什么在调整大小期间忽略图像的宽高比呢?将图像压缩到9x8并忽略纵横比,以确保生成的图像哈希与相似的照片匹配,无论其初始空间维度如何。

为什么是 9 x 8这么一个奇怪的大小呢?后面会对这个问题详细解释。

步骤三:计算差异

我们最终的目标是计算64位散列 - 因为8 x 8 = 64,我们非常接近这个目标。

那么回答上面第二个问题,为什么调整大小到9 x 8?请记住我们正在实现的算法是dHash差异哈希。差异散列算法通过计算相邻像素之间的差异(即,相对梯度)来工作的。

如果我们采用每行9个像素的输入图像并计算相邻列像素之间的差异,我们最终得到8个差异。八行八个差异(即8x8)是64,这将成为我们的64位散列。

在实践中,我们实际上不必计算差异:我们可以应用“大于”测试(或“小于”,只要始终使用相同的操作,它就不重要,我们将在下面的步骤中看到)。

步骤四:构建哈希

最后一步是分配位并构建结果哈希。为此,我们使用简单的二进制测试。

给定差异图像D和对应的像素组P,我们应用以下测试:P[x]>P[x+1] = 1 否则 0。

在这种情况下,我们测试左像素是否比右像素更亮。如果左侧像素更亮,我们将输出值设置为1,否则,如果左侧像素较暗,我们将输出值设置为0。

如果我们假设这个差异映射是 8×8 像素,则该测试的输出产生一组64个二进制值,然后将它们组合成单个64位整数(即实际图像散列)。

dHash的好处

使用差异散列(dHash)有很多好处,但主要的好处包括:

1)如果我们的输入图像的宽高比发生变化(因为我们忽略了宽高比),我们的图像哈希不会改变。

2)调整亮度或对比度要么不改变我们的哈希值,要么仅稍微改变它,确保哈希值接近。

3)差异散列非常快。

比较差异哈希值

通常我们使用汉明距离来比较哈希值。汉明距离测量两个不同哈希值中的比特数。

汉明距离为零的两个散列意味着两个散列是相同的(因为没有不同的位)并且两个图像在相同/感知上相似。

通常情况,差异散列 >10位图像最有可能不同而汉明距离在1和10之间的图像很可能相同或类似。实际上,你可能需要为自己的应用程序和相应的数据集调整这些阈值。

使用OpenCV和Python实现图像散列

首先,请确保您已经安装了我的imutils软件包,新建一个文件hash_and_search.py,先导入必要的包:

# import the necessary packagesfrom imutils import pathsimport argparseimport timeimport sysimport cv2import os#定义dhash函数,包含我们的差异哈希实现:def dhash(image, hashSize=8):# resize the input image, adding a single column (width) so we# can compute the horizontal gradientresized = cv2.resize(image, (hashSize + 1, hashSize)) #调整图像大小位9x8 # compute the (relative) horizontal gradient between adjacent# column pixelsdiff = resized[:, 1:] > resized[:, :-1] #计算二进制值测试相邻像素明暗 # convert the difference image to a hashreturn sum([2 ** i for (i, v) in enumerate(diff.flatten()) if v]) #转换64位整数来构建哈希值

我们的dhash函数需要一个输入image以及一个可选的hashSize。设置hashSize = 8 以指示输出散列将是8 x 8 = 64位。然后将得到的整数返回给调用函数。

接下来输入以下代码解析命令行参数:

# construct the argument parse and parse the argumentsap = argparse.ArgumentParser()ap.add_argument("-a
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值