利用Python实现简单的相似图片搜索的教程

发表于 5年以前  | 总阅读数:1018 次

2015423113218600.jpg \(690×197\)大概五年前吧,我那时还在为一家约会网站做开发工作。他们是早期创业公司,但他们也开始拥有了一些稳定用户量。不像其他约会网站,这家公司向来以洁身自好为主要市场形象。它不是一个供你鬼混的网站――是让你能找到忠实伴侣的地方。

由于投入了数以百万计的风险资本(在US大萧条之前),他们关于真爱并找寻灵魂伴侣的在线广告势如破竹。Forbes(福布斯,美国著名财经杂志)采访了他们。全国性电视节目也对他们进行了专访。早期的成功促成了事业起步时让人垂涎的指数级增长现象――他们的用户数量以每月加倍的速度增长。对他们而言,一切都似乎顺风顺水。

但他们有一个严重的问题――色情问题。

该约会网站的用户中会有一些人上传色情图片,然后设置为其个人头像。这种行为破坏了很多其他用户的体验――导致很多用户取消了会员。

可能对于现在的一些约会网站随处可见几张色情图片也许并不能称之为是问题。或者可以说是习以为常甚至有些期待,只是一个被接受然后被无视的在线约会的副产品。

然而,这样的行为既不应该被接受也应该被忽视。

别忘了,这次创业可是将自己定位在优秀的约会天堂,免于用户受到困扰其他约会网站的污秽和垃圾的烦扰。简而言之,他们拥有很实在的以风险资本作为背后支撑的名声,而这也正是他们需要保持的风格。

该约会网站为了能迅速阻止色情图片的爆发可以说是不顾一切了。他们雇佣了图片论坛版主团队,真是不做其他事只是每天盯着监管页面8个小时以上,然后移除任何被上传到社交网络的色情图片。

毫不夸张的说,他们投入了数万美元(更不用说数不清的人工小时)来解决这个问题,然而也仅仅只是缓解,控制情况不变严重而不是在源头上阻止。

色情图片的爆发在2009年的七月达到了临界水平。8个月来第一次用户量没能翻倍(甚至已经开始减少了)。更糟糕的是,投资者声称若该公司不能解决这个问题将会撤资。事实上,污秽的潮汐早已开始冲击这座象牙塔了,将它推翻流入大海也不过是时间问题。

正在这个约会网站巨头快要撑不住时,我提出了一个更鲁棒的长期解决方案:如果我们使用图片指纹来与色情图片的爆发斗争呢?

你看,每张图片都有一个指纹。正如人的指纹可以识别人,图片的指纹能识别图片。

这促使了一个三阶段算法的实现:

1. 为不雅图片建立指纹,然后将图片指纹存储在一个数据库中。

2. 当一个用户上传一份新的头像时,我们会将它与数据库中的图片指纹对比。如果上传图片的指纹与数据库任意一个不雅图片指纹相符,我们就阻止用户将该图片设置为个人头像。

3. 当图片监管人标记新的色情图片时,这些图片也被赋予指纹并存入我们的数据库,建立一个能用于阻止非法上传且不断进化的数据库。

我们的方法,尽管不十分完美,但是也卓有成效。慢慢地,色情图片爆发的情况有所减慢。它永远不会消失――但这个算法让我们成功将非法上传的数量减少了80%以上。

这也挽回了投资者的心。他们继续为我们提供资金支持――直到萧条到来,我们都失业了。

回顾过去时,我不禁笑了。我的工作并没持续太久。这个公司也没有坚持太久。甚至还有几个投资者卷铺盖走人了。

但有一样确实存活了下来。提取图片指纹的算法。几年之后,我把这个算法的基本内容分享出来,期望你们可以将它应用到你们自己的项目中。

但最大的问题是,我们怎么才能建立图片指纹呢?

继续读下去一探究竟吧。
即将要做的事情

我们打算用图片指纹进行相似图片的检测。这种技术通常被称为"感知图像hash"或是简单的"图片hash"。
什么是图片指纹/图片哈希

图片hash是检测一张图片的内容然后根据检测的内容为图片建立一个唯一值的过程。

比如,看看本文最上面的那张图片。给定一张图片作为输入,应用一个hash函数,然后基于图片的视觉计算出一个图片hash。相似的图片也应当有相似的hash值。图片hash算法的应用使得相似图片的检测变得相当简单了。

特别地,我们将会使用"差别Hash"或简单的DHash算法计算图片指纹。简单来说,DHash算法着眼于两个相邻像素之间的差值。然后,基于这样的差值,就建立起一个hash值了。
为什么不使用md5,sha-1等算法?

不幸的是,我们不能在实现中使用加密hash算法。由于加密hash算法的本质使然,输入文件中非常微小的差别也能造成差异极大的hash值。而在图片指纹的案例中,我们实际上希望相似的输入可以有相似的hash输出值。
图片指纹可以用在哪里?

正如我上面举的例子,你可以使用图片指纹来维护一个保存不雅图片的数据库――当用户尝试上传类似图片时可以发出警告。

你可以建立一个图片的逆向搜索引擎,比如TinEye,它可以记录图片以及它们出现的相关网页。

你还可以使用图片指纹帮助管理你个人的照片收集。假设你有一个硬盘,上面有你照片库的一些局部备份,但需要一个方法删除局部备份,一张图片仅保留一份唯一的备份――图片指纹可以帮你做到。

简单来说,你几乎可以将图片指纹/哈希用于任何需要你检测图片的相似副本的场景中。
需要的库有哪些?

为了建立图片指纹方案,我们打算使用三个主要的Python包:

  1. PIL/Pillow用于读取和载入图片
  2. ImageHash,包括DHash的实现
  3. 以及NumPy/SciPy,ImageHash的依赖包

你可以使用下列命令一键安装所需要的必备库:


    $ pip install pillow imagehash

第一步:为一个图片集建立指纹

第一步就是为我们的图片集建立指纹。

也许你会问,但我们不会,我们不会使用那些我为那家约会网站工作时的色情图片。相反,我创建了一个可供使用的人工数据集。

对计算机视觉的研究人员而言,数据集CALTECH-101 是一个传奇般的存在。它包含来自101个不同分类中的至少7500张图片,内容分别有人物,摩托车和飞机。

从这7500多张图片中,我随机的挑选了17张。

然后,从这17张随机挑选的图片中,以几个百分点的比例随机放大/缩小并创建N张新图片。这里我们的目标是找到这些近似副本的图片――有点大海捞针的感觉。

你也想创建一个类似的数据集用于工作吗?那就下载CALTECH-101 数据集,抽取大概17张图片即可,然后运行repo下的脚本文件gather.py。

回归正题,这些图片除了宽度和高度,其他各方面都是一样的。而且因为他们没有相同的形状,我们不能依赖简单的md5校验和。最重要的是,有相似内容的图片可能有完全不相同的md5哈希。然而,采取图片哈希,相似内容的图片也有相似的哈希指纹。

所以赶紧开始写代码为数据集建立指纹吧。创建一个新文件,命名为index.py,然后开始工作:


    # import the necessary packages
    from PIL import Image
    import imagehash
    import argparse
    import shelve
    import glob

    # construct the argument parse and parse the arguments
    ap = argparse.ArgumentParser()
    ap.add_argument("-d", "--dataset", required = True,
    help = "path to input dataset of images")
    ap.add_argument("-s", "--shelve", required = True,
    help = "output shelve database")
    args = vars(ap.parse_args())

    # open the shelve database
    db = shelve.open(args["shelve"], writeback = True)

要做的第一件事就是引入我们需要的包。我们将使用PIL或Pillow中的Image类载入硬盘上的图片。这个imagehash库可以被用于构建哈希算法。

Argparse库用于解析命令行参数,shelve库用作一个存储在硬盘上的简单键值对数据库(Python字典)。glob库能很容易的获取图片路径。

然后传递命令行参数。第一个,―dataset是输入图片库的路径。第二个,―shelve是shelve数据库的输出路径。

下一步,打开shelve数据库以写数据。这个db数据库存储图片哈希。更多的如下所示:


    # loop over the image dataset
    for imagePath in glob.glob(args["dataset"] + "/*.jpg"):
      # load the image and compute the difference hash
      image = Image.open(imagePath)
      h = str(imagehash.dhash(image))

      # extract the filename from the path and update the database
      # using the hash as the key and the filename append to the
      # list of values
      filename = imagePath[imagePath.rfind("/") + 1:]
      db[h] = db.get(h, []) + [filename]

    # close the shelf database
    db.close()

以上就是大部分工作的内容了。开始循环从硬盘读取图片,创建图片指纹并存入数据库。

现在,来看看整个范例中最重要的两行代码:


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

正如本文早些时候提到的,有相同指纹的图片被认为是一样的。

因此,如果我们的目标是找到近似图片,那就需要维护一个有相同指纹值的图片列表。

而这也正是这几行代码做的事情。

前一个代码段提取了图片的文件名。而后一个代码片段维护了一个有相同指纹值的图片列表。

为了从我们的数据库中提取图片指纹并建立哈希数据库,运行下列命令:


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

这个脚本会运行几秒钟,完成后,就会出现一个名为db.shelve的文件,包含了图片指纹和文件名的键值对。

这个基本算法正是几年前我为这家约会创业公司工作时使用的算法。我们获得了一个不雅图片集,为其中的每张图片构建一个图片指纹并将其存入数据库。当来一张新图片时,我只需简单地计算它的哈希值,检测数据库查看是否上传图片已被标识为非法内容。

下一步中,我将展示实际如何执行查询,判定数据库中是否存在与所给图片具有相同哈希值的图片。
第二步:查询数据集

既然已经建立了一个图片指纹的数据库,那么现在就该搜索我们的数据集了。

打开一个新文件,命名为search.py,然后开始写代码:


    # import the necessary packages
    from PIL import Image
    import imagehash
    import argparse
    import shelve

    # construct the argument parse and parse the arguments
    ap = argparse.ArgumentParser()
    ap.add_argument("-d", "--dataset", required = True,
      help = "path to dataset of images")
    ap.add_argument("-s", "--shelve", required = True,
      help = "output shelve database")
    ap.add_argument("-q", "--query", required = True,
      help = "path to the query image")
    args = vars(ap.parse_args())

我们需要再一次导入相关的包。然后转换命令行参数。需要三个选项,―dataset初始图片集的路径,―shelve,保存键值对的数据库的路径,―query,查询/上传图片的路径。我们的目标是对于每个查询图片,判定数据库中是否已经存在。

现在,写代码执行实际的查询:


    # open the shelve database
    db = shelve.open(args["shelve"])

    # load the query image, compute the difference image hash, and
    # and grab the images from the database that have the same hash
    # value
    query = Image.open(args["query"])
    h = str(imagehash.dhash(query))
    filenames = db[h]
    print "Found %d images" % (len(filenames))

    # loop over the images
    for filename in filenames:
      image = Image.open(args["dataset"] + "/" + filename)
      image.show()

    # close the shelve database
    db.close()

首先打开数据库,然后载入硬盘上的图片,计算图片的指纹,找到具有相同指纹的所有图片。

如果有图片具有相同的哈希值,会遍历这些图片并展示在屏幕上。

这段代码使我们仅仅使用指纹值就能判定图片是否已在数据库中存在。
结果

正如本文早些时候提到的,我从CALTECH-101数据集的7500多张图片中随机选取17张,然后通过任意缩放一部分点产生N张新的图片。

这些图片在尺寸上仅仅是少数像素不同―但也是因为这一点我们不能依赖于文件的md5哈希(这一点已在"优化算法"部分进行了详尽的描述)。然而,我们可以使用图片哈希找到近似图片。

打开你的终端并执行下述命令:


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

如果一切顺利你就可以看到下述结果:

2015423113341305.jpg \(690×431\)

左边是输入图片。载入这张图片,计算它的图片指纹,在数据库中搜索指纹查看是否存在有相同指纹的图片。

当然――正如右边所示,我们的数据集中有其他两张指纹相同的图片。尽管从截图中还不能十分明显的看出,这些图片,虽然有完全相同的视觉内容,也不是完全相同!这三张图片的高度宽度各不相同。

尝试一下另外一个输入图片:


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

下面是结果:

2015423113456081.jpg \(690×431\)

左边仍然是我们的输入图片。正如右边展示的,我们的图片指纹算法能够找出具有相同指纹的三张完全相同的图片。

最后一个例子:


    $ python search.py ―dataset images ―shelve db.shelve ―query images/5134e0c2-34d3-40

2015423113538460.jpg \(690×431\)

这一次左边的输入图片是一个摩托车。拿到这张摩托车图片,计算它的图片指纹,然后在指纹数据库中查找该指纹。正如我们在右边看到的,我们也能判断出数据库中有三张图片具有相同指纹。
优化算法

有很多可以优化本算法的方法――但最关键性的是要考虑到相似但不相同的哈希。

比如,本文中的图片仅仅是一小部分点重组了(依比例增大或减小)。如果一张图片以一个较大的因素调整大小,或者纵横比被改变了,对应的哈希就会不同了。

然而,这些图片应该仍然是相似的。

为了找到相似但不相同的图片,我们需要计算汉明距离(Hamming distance).汉明距离被用于计算一个哈希中的不同位数。因此,哈希中只有一位不同的两张图片自然比有10位不同的图片更相似。

然而,我们遇到了第二个问题――算法的可扩展性。

考虑一下:我们有一张输入图片,又被要求在数据库中找到所有相似图片。然后我们必须计算输入图片和数据库中的每一张图片之间的汉明距离。

随着数据库规模的增长,和数据库比对的时间也随着延长。最终,我们的哈希数据库会达到一个线性比对已经不实际的规模。

解决办法,虽然已超出本文范围,就是利用K-d treesVP trees将搜索问题的复杂度从线性减小到次线性。
总结

本文中我们学会了如何构建和使用图片哈希来完成相似图片的检测。这些图片哈希是使用图片的视觉内容构建的。

正如一个指纹可以识别一个人,图片哈希也能唯一的识别一张图片。

使用图片指纹的知识,我们建立了一个仅使用图片哈希就能找到和识别具有相似内容的图片的系统。

然后我们又演示了图片哈希是如何应用于快速找到有相似内容的图片。

repo目录下下载代码。

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:1年以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:1年以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:1年以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:1年以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:1年以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:1年以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:1年以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:1年以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:1年以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:1年以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:1年以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:1年以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:1年以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:1年以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:1年以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:1年以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:1年以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:1年以前  |  398次阅读  |  详细内容 »
 相关文章
Android插件化方案 5年以前  |  237231次阅读
vscode超好用的代码书签插件Bookmarks 2年以前  |  8065次阅读
 目录