图像指纹的重复识别

在google上面搜索图像识别的时候,搜到一篇好文章,在这里翻译一下,所有版权来源于https://realpython.com/blog/python/fingerprinting-images-for-near-duplicate-detection/,作者源代码:https://github.com/realpython/image-fingerprinting/blob/master/code/output.csv虽然英语过了六级,但是仍然有很多专业术语不懂,翻译水平也只能是凑合而已。

注:本文写作的目的是这篇文章的作者发现建立网站的时候,很多用户用相同的头像,这导致识别度降低,为了防止用户上传相同的图片作为自己的头像以及上传不当的图像文件,作者研究了这个图像指纹的问题。(等我翻译完成竟然发现网上已经有人翻译好了http://python.jobbole.com/81277/,自愧不如)

不妨想一想,每一个人都有属于他自己的指纹一样,指纹能够识别人,那么图片的指纹也可以用来识别图片。

现在用三个阶段来实现算法:

  1.将一组不合适的图像指纹计算出来,然后将这些图像指纹存入数据库中。

  2.当用户上传一个新的客户资料中的头像时,我们将会将其与数据库中的图像指纹进行对比。如果发现数据库中任意一个头像指纹与该用户上传的图像符合,管理员将会阻止用户上传该图像作为自己的头像。

  3.依次类推,识别出色情图片,根据色情图片的指纹创建一个收集色情图片指纹的数据库,用来防止用户上传色情图片。

我们的程序并不是完美的,有效的。即使效率缓慢但是目的终究是达到了,虽然没有完全的解决问题,但是减少了用户上传的80%以上的不当文件。

那么接下来最大的问题是如何创建图像指纹?

请继续阅读并找出答案。。。

我们接下来需要做什么?

我们将利用图像指纹进行重复识别,一般称这种技术为“图像感知哈希法”或者“图像哈希法”。

什么是图像指纹或者说什么是图像哈希?

图像哈希的过程是通过检测图像的内容,然后构造一个值,该值在这些图像内容的基础上唯一的标志这个图像

如下图所示:

在给定的输入的图像中, 我们将使用一个散列函数,并基于图像视觉上的外观计算它的“图像散列”值,相似的头像,它的散列值应该也是相似的。使用图像哈希算法可以大大简化重复图像检测的程序。

在这里,我们将使用“difference hash”,或者仅仅使用dHash算法来计算我们的图像指纹。简单来说,dHash着力探究相邻像素之间的区别。哈希值是在这个基础上被创建出来的。

为什么我们不直接使用md5,sha-1等等算法?

不幸的是,我们不能在本例中使用加密散列算法。这是由于加密散列算法本身的性质——输入文件中非常微小的变化都会造成显著不同的哈希值。在本次图像指纹的案例中,是希望类似图片的输入能得到类似哈希值的输出。

图像指纹能应用在哪些领域?

就如同上面的例子,你可以用图像指纹来管理你的不合适的图像数据库,当用户尝试上传此类图像的时候你可以提醒他们。

你可以建立一个类似于TinEye的搜索引擎,用来跟踪图片,并且找出类似图片出现的网页。

你甚至可以通过使用图像指纹识别来管理你的个人相集。想象一下,你有一个存储你个人图片的硬盘,但是需要一种方法备份部分修剪的图片,并能够保持唯一的副本——图像指纹可以帮你做到。

简单来说,你可以在任何与图像重复副本检测的地方使用图像指纹或者图像散列方法。

我们需要哪些库?

为了制作我们的图像指纹识别方案,将会用的以下三个python库:

你也可以通过如下命令搭建所有环境(python2.7):

$ pip install pillow imagehash

第一步:创建图像指纹数据集

我们并不打算使用我日常在约会网站上遇到的色情图片,我已经找到了一个我们可以使用的数据集。

对于计算机视觉研究人员来讲,CALTECH-101数据集是个传奇。它包含7500+张来自101个目录的图片,包括人、摩托车和飞机。

我从这7500张图片中随机抽取了17张。

然后从这17张随机抽选的图片中,我通过随机调整图片的尺寸创建了N个新的图像。我们的目标是找到这些近乎重复的图像,这就像是大海捞针。

并且,由于图片除了宽高尺寸外都是相同的,由于他们都没有相同的尺寸,我们不能简单的使用MD5校验,更重要的是内容类似的图片可能具有显著不同的哈希值,原因已解释,相反,我们可以使用图像散列,因为类似的图片拥有相似的哈希指纹。

那么现在开始编写关于数据集的代码,并将其命名为index.py:

 1 # coding=utf-8
 2 # 导入必要的包
 3 import argparse
 4 import shelve   import imagehash
 5 import glob
 6 from PIL import Image
 7
 8 # 构建参数解析,并分析参数
 9 ap = argparse.ArgumentParser()
10 ap.add_argument("-d", "--dataset", required=True,
11                 help="照片数据集的路径")
12 ap.add_argument("-s", "--shelve",required=True,
13                 help="shelve数据集的输出")
14 args = vars(ap.parse_args())
15
16 # 打开shelve数据集
17 db = shelve.open(args["shelve"], writeback=True)

首先,我们要做的就是导入我们需要的包。我们将使用PIL或者Pillow模块中的Image类从磁盘中加载图片。然后用图像指纹库来构建感性序列。

根据上面的代码可知,argparse用于解析命令行参数,shelve用来做python的子典型数据库,并将其存储在磁盘上,glob将用来更加轻易的收集图片的路径位置。

接着,分析命令行参数。第一,--dataset是我们输入图像的路径目录。第二,--shelve是通往shelve数据库的输出路径。

接下来,我们打开shelve数据库并对其进行写入。db将会存储我们的图像哈希值。代码如下:

 1 # 在图像数据集中循环
 2 for imagePath in glob.glob(args["dataset"] + "/*.jpg"):
 3     # 加载图片并计算哈希值的差异
 4     image = Image.open(imagePath)
 5     h = str(imagehash.dhash(image))
 6
 7     # 提取路径中的文件名并更新数据库
 8     # 用散列作为字典的键,文件名添加到值列表
 9     filename = imagePath[imagePath.rfind("/") + 1:]
10     db[h] = db.get(h, []) + [filename]
11
12 # 关闭shelf数据集
13 db.close()

这些就是我们大致需要的代码工作了,从磁盘中加载图像,并遍历图像数据集,然后创建图像指纹。

现在我们观察以下整个教程中最重要的两条代码:

1 filename = imagePath[imagePath.rfind("/") + 1:]
2 db[h] = db.get(h, []) + [filename]

就像我一开始在文章中提到的一样,具有相同指纹的图像被认为是同样的图像。

因此,如果我们的目标是找出相似图片,我们需要创建一个拥有相同指纹值的图像列表。

以上两行代码做的就是这个工作。

第一行提取图像的文件名,第二行给图像创建一个拥有相同哈希值的列表。

从数据库中提取图像指纹并创建我们的散列数据库,使用如下命令:

$ python index.py —dataset images —shelve db.shelve

该脚本将会运行几秒钟,一旦完成就好产生一个文件,里面包含了图像指纹—文件名对应的键值对。

这个算法和我几年前在创建约会网站时写的算法一样,我们将不适合的图片收集起来,并计算他们的散列值,存入数据库。当用户提交图像的时候,我只有计算图像的指纹,并将其与数据库中的指纹进行对比,用来判断是否上传被判无效的内容。

下一步我将会告诉你如何执行搜索,以确定图片是否在数据库中有类似的散列值的图像。

第二步:搜索数据库

既然我们已经创建了一个指纹图像数据库,是时候来搜索数据库了。

打开一个名字为search.py的新文件,开始编写代码:

 1 # coding=utf-8
 2 # 导入必要的包
 3 from PIL import Image
 4 import imagehash
 5 import argparse
 6 import shelve
 7
 8 # 构建参数解析,并分析参数
 9 ap = argparse.ArgumentParser()
10 ap.add_argument("-d", "--dataset", required=True,
11                 help="照片数据集的路径")
12 ap.add_argument("-s", "--shelve",required=True,
13                 help="shelve数据集的输出")
14 ap.add_argument("-q", "--query", required=True,
15                 help="搜索图像的路径")
16 args = vars(ap.parse_args())

像上次一样,导入我们需要的包,然后解析命令行参数。接下来需要三次转换,--dataset,它是原始图片数据集的路径,--shelve,存放键值对的数据库,以及--query,搜索或者上传图片的路径。我们的目标是根据上传的图片对数据库进行搜索类似哈希值的图片。

接下来,写关于执行搜索的代码:

 1 # 打开shelf数据集
 2 db = shelve.open(args["shelf"])
 3
 4 # 加载需要查询的图片,计算它的图像差分散列值,并从数据库中抓取类似散列值得图像
 5 query = Image.open(args["query"])
 6 h = str(imagehash.dhash(query))
 7 filenames = db[h]
 8 print("Found %d images" % (len(filenames)))
 9
10 # 在图像内部循环
11 for filename in filenames:
12     image = Image.open(args["dataset"] + "/" + filename)
13     image.show()
14
15 # 关闭数据集
16 db.close()

我们先打开数据库,并从磁盘中加载图片,计算图像指纹,找出拥有相同指纹值得所有图片。

如果存在任何相同哈希值的图片,将会在图片中循环,依次展示这些图片。

使用这些代码,我们将会判断是否上传的图片已经存在于数据库中。

结果

正如我在文章前段部分提到的,我已经从CALTECH-101数据集中随机采集了17张图片,并通过一些小的尺寸上面的改动创建了N张新图片。

这些图片的尺寸造成只有小部分的像素不同,因此不能使用MD5哈希算法(这一点将会在算法改进中继续探讨)。想法我们需要利用图像散列找到类似的图像。

打开终端,并执行以下命令:

$ python search.py —dataset images —shelve db.shelve —query images/84eba74d-38ae-4bf6-b8bd-79ffa1dad23a.jpg

如果不报错的话将会出现以下结果:

上面图片的左边就是输入的图像,我们将用这张图片对数据集进行搜索,找出拥有相同指纹的所有图像。

值得肯定的是,在我们的数据集中有两张图片具有相同的指纹,如图像右边的两张图片所示。虽然从截图上面查看并不很明显,但是他们确实是具有相同内容的不同尺寸的图片。

让我们尝试输入另外一张图片:

$ python search.py —dataset images —shelve db.shelve —query images/9d355a22-3d59-465e-ad14-138a4e3880bc.jpg

结果如下:

perfect!

改进算法

有很多方法可以改进我们的算法,但是最重要的一种方法时考虑到散列是相似的并不是完全一样的。

比如说,我们这次提交的图片都是在尺寸上(向上或向下)调整了几个百分点的大小,如果图像调整比较大的话,导致纵横比改变,散列值将不会完全相同。

但是图片将是类似的。

为了找出相似并不相同的图片,我们需要进一步用到Hamming距离法。Hamming距离法可以计算出不同哈希值的像素位数。因此,两个具有一位像素相差的图像基本上比10位相差的的图新更相似。

但是我们遇到第二个问题,算法的扩展性。

试想一下,有一张被输入的图像,并需要找到数据库中所有类似的图像。那么我们可以计算输入图像和每一个数据库图像的Hamming距离。

随着数据集的增大,将会导致更多的时间比较所有的哈希值。最后,我们的散列数据库将会到达一定的规模以至于单纯的线性比较是不实际的。

有一个解决方案就是,使用Kd树分类法或者VP树分类,从线性搜索变成亚线性,减少搜索问题的复杂性。

总结

在这篇文章中,我们学会了如何构建和利用图像散列法执行近似图像的检测。图像散列应用在图像视觉内容研究中。

正如指纹可以识别人一样,一个图像的哈希值也可以唯一的标志图像。

使用我们的质问图像知识,再建立一个查找类似图像的系统无非是用的图像的哈希算法。

编后语

ok,这就是昨天晚上和今天上午所翻译的东西了,翻译这篇博客让我认识到了自己语法的不足,例如数据库的载入以及参数的解析的不熟悉等等。也使得我的心能够在五一这种热闹的气氛下安静下来翻译文章,分析算法,并从国际友人的字里行间感受他的热情和思想,再次感谢作者。话说,今天用的流量出校器一直在烧流量,不知道是什么原因,毕竟昨天用的时候没问题,难道谷歌FQ需要消耗大量的流量?还是本身插件具有一定的吸附流量能力?估计最不可能的是我的电脑被人黑了吧,oh,my god!

时间: 2024-10-07 02:35:42

图像指纹的重复识别的相关文章

从指纹到眼球识别:漫谈手机安全方案

随着移动互联网及终端设备的喷涌发展,越来越多的智能手机厂商开始关注新的移动安全.在智能手机产品身上,iPhone 5s率先推出指纹识别功能模块之后,大量的手机品牌也通过跟进方式追赶这种潮流.在今天的智能手机市场上,除了iPhone系列搭载指纹识别模块方式之外, vivo今年上半年推出具备眼球识别的X5Pro等手机产品,也一定程度上丰富和完善了智能手机安全解决方案的普及范围. 其他一些独特的安全识别解决方案,未来也或将陆续呈现在不同领域中. 移动安全迎来百花齐放时代 在APP密码.移动支付.用户数

看起来像它——图像搜索其实也不难 (图像相似,图像指纹,phash hash,图像搜索) 使用时候记得看这文章的评论

链接: http://pan.baidu.com/s/1o7ScyVo 密码: h8eb    这个文章的代码 另一个类似的代码  链接: http://pan.baidu.com/s/1hsFDCNy 密码: jxus http://blog.csdn.net/luoweifu/article/details/8220992                 使用时候记得看这文章的评论 看起来像它——图像搜索其实也不难 标签: pHash图像搜索图像识别图片搜索算法 2012-11-24 23:

Atitit 图像清晰度 模糊度 检测 识别 评价算法 原理

1.1. 图像边缘一般都是通过对图像进行梯度运算来实现的1 1.2. Remark: 1 1.3.  1.失焦检测. 衡量画面模糊的主要方法就是梯度的统计特征,通常梯度值越高,画面的边缘信息越丰富,图像越清晰.1 1.4. 利用边缘检测 ,模糊图片边缘会较少2 1.5. 通过dct比较.Dct分离出的低频信号比较2 1.6. 参考资料2 1.1. 图像边缘一般都是通过对图像进行梯度运算来实现的 1.2. Remark:   1)肉眼可以分辨以上五幅图像的质量排名为:img42 > img81 >

Atitit 图像清晰度 模糊度 检测 识别 评价算法 源码实现attilax总结

1.1. 原理,主要使用像素模糊后的差别会变小1 1.2. 具体流程1 1.3. 提升性能 可以使用采样法即可..1 1.4. 实现代码1 1.1. 原理,主要使用像素模糊后的差别会变小 通过计算横向前后俩点像素的差异..然后累加即可.. 1.2. 具体流程 图片灰度化,这样可以只保留hsv分量了...然后读取v分量,就是明亮度了.. Hs色相和饱和度全部去除了..   比较v分量的差异即可.. 1.3. 提升性能 可以使用采样法即可.. 1.4. 实现代码 package com.attila

机器学习和深度学习资料合集

机器学习和深度学习资料合集 注:机器学习资料篇目一共500条,篇目二开始更新 希望转载的朋友,你可以不用联系我.但是一定要保留原文链接,因为这个项目还在继续也在不定期更新.希望看到文章的朋友能够学到更多.此外:某些资料在中国访问需要梯子. <Brief History of Machine Learning> 介绍:这是一篇介绍机器学习历史的文章,介绍很全面,从感知机.神经网络.决策树.SVM.Adaboost到随机森林.Deep Learning. <Deep Learning in

[转]机器学习和深度学习资料汇总【01】

本文转自:http://blog.csdn.net/sinat_34707539/article/details/52105681 <Brief History of Machine Learning> 介绍:这是一篇介绍机器学习历史的文章,介绍很全面,从感知机.神经网络.决策树.SVM.Adaboost到随机森林.Deep Learning. <Deep Learning in Neural Networks: An Overview> 介绍:这是瑞士人工智能实验室Jurgen

眼部识别和指纹识别,你会选择谁?

自从vivo.中信推出支持眼部识别功能后,引起了大家的关注,那到底眼部识别是怎么回事呢?那么以iPhone5s为代表的指纹识别就会被眼部识别取代吗?下面让我们对比一下眼部识别和指纹识别吧!  一.什么事眼部识别?什么是指纹识别? 眼部识别它是通过扫描眼睛,来进行处理.特征提取和比对等来进行用户安全识别!而指纹是被则是获取指纹图像,并进行处理.特征提取和比对等来进行用户安全识别! 二.眼部识别和指纹识别对硬件的要求     今年以来,魅族和大神分别在自己的千元机魅蓝Metal和大神Note3上大力

用于身份验证的生物识别技术指纹识别相关情况解析方案

众多的用于身份验证的生物识别技术中,指纹识别技术是目前最方便.可靠.非侵害和价格便宜的解决方案. 指纹是人体独一无二的特征,具有随身性.唯一性.不可复制性.绝对保密性,并且它们的复杂度足以提供用于鉴别的足够特征;如果我们想要增加可靠性,我们只需登记更多的指纹,鉴别更多的手指.爱迪尔研制的指纹模块性能卓越,扫描指纹的速度很快,使用非常方便;读取指纹时,用户只需将活体手指与指纹采集头相互接触,与指纹采集头直接接触是读取人体生物特征最可靠的方法. 二.门禁锁具 在日常生活中,人们无处不在的必须使用各种

深夜闲聊节目:华为 Mate7的指纹识别安全么?

许久没有写过任何东西,最近很忙而且还要准备找工作之类的,唉... ....今天的文章也不说技术,只是闲聊. 一.手机指纹识别一揽 打开很多网站.论坛的科技栏目,充斥着各种手机讯息!仿佛手机已经成了科技的代名词.更凶残的是,今年科技界,哦不,手机界永远少不了各种新闻:先是Zealer 和锤子的骂战,再是魅族攒了一年的新闻一起发,紧接着联想.HTC.Moto 不断放大招,最后是苹果的亮相.水货价格更是闪瞎我等屌丝的氪金狗眼 ... ... 手机/科技界的故事还远远没有尽头! 但是,但是... ...