以图搜图(一):Python实现dHash算法(转)
近期研究了一下以图搜图这个炫酷的东西。百度和谷歌都有提供以图搜图的功能,有兴趣可以找一下。当然,不是很深入。深入的话,得运用到深度学习这货。Python深度学习当然不在话下。
这个功能最核心的东西就是怎么让电脑识别图片。
这个问题也是困扰了我,在偶然的机会,看到哈希感知算法。这个分两种,一种是基本的均值哈希感知算法(dHash),一种是余弦变换哈希感知算法(pHash)。dHash是我自己命名的,为了和pHash区分。这里两种方法,我都用Python实现了^_^
哈希感知算法基本原理如下:
1、把图片转成一个可识别的字符串,这个字符串也叫哈希值
2、和其他图片匹配字符串
算法不是耍耍嘴皮子就行了,重点是怎么把图片变成一个可识别的字符串。(鄙视网上那些抄来抄去的文章,连字都一模一样)拿一张图片举例。

首先,把这个图片缩小到8x8大小,并改成灰度模式。这样是为了模糊化处理图片,并减少计算量。
8x8的图片太小了,放大图片给大家看一下。

8x8大小的图片就是有64个像素值。计算这64个像素的平均值,进一步降噪处理。
像素值=[
247, 245, 250, 253, 251, 244, 240, 240,
247, 253, 228, 208, 213, 243, 247, 241,
252, 226, 97, 80, 88, 116, 231, 247,
255, 172, 79, 65, 51, 58, 191, 255,
255, 168, 71, 60, 53, 69, 205, 255,
255, 211, 65, 58, 56, 104, 244, 252,
248, 253, 119, 42, 53, 181, 252, 243,
244, 240, 218, 175, 185, 230, 242, 244]
平均值=185.359375
得到这个平均值之后,再和每个像素对比。像素值大于平均值的标记成1,小于或等于平均值的标记成0。组成64个数字的字符串(看起来也是一串二进制的)。
降噪结果=[
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 0, 0, 0, 0, 1, 1,
1, 0, 0, 0, 0, 0, 1, 1,
1, 0, 0, 0, 0, 0, 1, 1,
1, 1, 0, 0, 0, 0, 1, 1,
1, 1, 0, 0, 0, 0, 1, 1,
1, 1, 1, 0, 0, 1, 1, 1]
64位字符串 = '1111111111111111110000111000001110000011110000111100001111100111'
由于64位太长,比较起来也麻烦。每4个字符为1组,由2进制转成16进制。这样就剩下一个长度为16的字符串。这个字符串也就是这个图片可识别的哈希值。
哈希值 = 'ffffc38383c3c3e7'
Python代码如下:
#coding:utf-8
#!usr/bin/python2.7 """
author:Haddy Yang (杨仕航)
data:2016-04-01(代码是4月1号写的,中间太忙了,现在才发布出来)
description:get image's hash value
environ: python2.7 and python2.6
""" #yum install python-imaging (安装PIL图像库,python2.6)
#PIL官方提供的Python2.6可以使用,2.7不行。
#Python2.7可以用pillow库
#import Image #python2.6 PIL
from PIL import Image #python2.7 pillow
import sys def get_hash(image_path):
"""get image hash string"""
im = Image.open(image_path)
#antialias 抗锯齿
#convert 转换 L 代表灰度
im = im.resize((8, 8), Image.ANTIALIAS).convert('L')
#avg:像素的平均值
avg=sum(list(im.getdata()))/64.0 #avg和每个像素比较,得到长度64的字符串
str=''.join(map(lambda i: '0' if i<avg else '1', im.getdata()))
#str切割,每4个字符一组,转成16进制字符
return ''.join(map(lambda x:'%x' % int(str[x:x+4],2), range(0,64,4))) if __name__ == '__main__':
if len(sys.argv)!=2:
print '#sample: python imghash.py filename'
else:
print get_hash(sys.argv[1])
看看其他图片的哈希值:

b.jpg :fff3fbe1e181c3ff

c.jpg :ffffdf818080d9f9

d.jpg :ffffcfc7c7c3c7ef
这3张图片的哈希值分别和a.jpg(举例的那张图片)的哈希值对比。对比方法用汉明距离:相同位置上的字符不同的个数。例如a.jpg和b.jpg对比

有11个位置的字符不一样,则汉明距离是11。汉明距离越小就说明图片越相识。超过10就说明图片很不一样。
a.jpg和c.jpg的汉明距离是8;
a.jpg和d.jpg的汉明距离是7。
说明在这3张图片中,d.jpg和a.jpg最相似。
大致算法就是这样,汉明距离的代码我没给出,这个比较简单。一般都是在数据库里面进行计算,得到比较小的那些图片感知哈希值。
当然,实际应用中很少用这种算法,因为这种算法比较敏感。同一张图片旋转一定角度或者变形一下,那个哈希值差别就很大。不过,它的计算速度是最快的,通常可以用于查找缩略图。
下篇博文讲一下,余弦哈希感知算法的Python实现。这种算法在实际运用中会比较多。 《以图搜图(二):Python实现pHash算法》
(原创博文,转载请注明来自 yshblog.com)
以图搜图(一):Python实现dHash算法(转)的更多相关文章
- Google 以图搜图 - 相似图片搜索原理 - Java实现
前阵子在阮一峰的博客上看到了这篇<相似图片搜索原理>博客,就有一种冲动要将这些原理实现出来了. Google "相似图片搜索":你可以用一张图片,搜索互联网上所有与它相 ...
- Google 以图搜图 - 相似图片搜索原理 - Java实现 (转)
前阵子在阮一峰的博客上看到了这篇<相似图片搜索原理>博客,就有一种冲动要将这些原理实现出来了. Google "相似图片搜索":你可以用一张图片,搜索互联网上所有与它相 ...
- 以图搜图之模型篇: 基于 InceptionV3 的模型 finetune
在以图搜图的过程中,需要以来模型提取特征,通过特征之间的欧式距离来找到相似的图形. 本次我们主要讲诉以图搜图模型创建的方法. 图片预处理方法,看这里:https://keras.io/zh/prepr ...
- 使用 selenium 实现谷歌以图搜图爬虫
使用selenium实现谷歌以图搜图 实现思路 原理非常简单,就是利用selenium去操作浏览器,获取到想要的链接,然后进行图片的下载,和一般的爬虫无异. 用到的技术:multiprocessing ...
- 谷歌百度以图搜图 "感知哈希算法" C#简单实现
/// <summary> /// 感知哈希算法 /// </summary> public class ImageComparer { /// <summary> ...
- [No000007]搜索引擎以图搜图的原理
之前,Google把"相似图片搜索"正式放上了首页. 你可以用一张图片,搜索互联网上所有与它相似的图片.点击搜索框中照相机的图标. 一个对话框会出现. 你输入网片的网址,或者直接上 ...
- php 以图搜图
感知哈希算法count < =5 匹配最相似count > 10 两张不同的图片var_dump(ImageHash::run('1.jpg’, '2.jpg’)); <?php c ...
- Python数据结构与算法之图的最短路径(Dijkstra算法)完整实例
本文实例讲述了Python数据结构与算法之图的最短路径(Dijkstra算法).分享给大家供大家参考,具体如下: # coding:utf-8 # Dijkstra算法--通过边实现松弛 # 指定一个 ...
- Python数据结构与算法之图的广度优先与深度优先搜索算法示例
本文实例讲述了Python数据结构与算法之图的广度优先与深度优先搜索算法.分享给大家供大家参考,具体如下: 根据维基百科的伪代码实现: 广度优先BFS: 使用队列,集合 标记初始结点已被发现,放入队列 ...
随机推荐
- OMCS开发手册(04) -- 二次开发流程
在掌握了前面几篇关于OMCS的详细介绍后,我们就可以正式基于OMCS进行二次开发了.下面我们就从服务端和客户端的角度分别介绍开发的步骤. 一.服务端开发 抛开具体的业务逻辑而言,就OMCS的服务端的开 ...
- ubuntu安装docker
uname -r #查看内核版本要大于3.10apt-get updateapt-get install linux-image-generic-lts-trusty wget -qO- https: ...
- Leetcode 073 Set Matrix Zeroes
Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in place. click ...
- chapter11_3 字符串缓冲
逐行地读取一个文件,典型的代码是: local buff= " " for line in io.lines() do buff = buff .. line .. "\ ...
- 对象比较中 "相等性"和"同一性" 生动地解释
对象们都住在不同的房间里,每个房间只能住一个对象.对象们都被锁在房间里,永远没有办法搬家(至少从我们讨论的角度来说,这个说法是正确的).所以如果你知道了一个对象的房间号,就能找到对应的对象. 现在假如 ...
- CDOJ 1324 卿学姐与公主 分块
题目地址 分块模板 #include<cstdio> #include<algorithm> #include<math.h> using namespace st ...
- windows service and process 的关系
1.查询windows 对应的服务 sc query > 1.txt notepad 1.txt 2.查询对应的进程信息 tasklist /m > tasks.txt notepad t ...
- sql or 与and同时有时要注意
如果是一天sql语句中有or和and同时在 正确:where xxx=xx and (xxx=xx or xxx=xx) 错误:where xxx=xx and xxx=xx or xxx=xx (这 ...
- EditText光标居上
<EditText android:id="@+id/shareContent_editText" android:layout_width="wrap_conte ...
- JDK,Tomcat,myeclipse相关资料
配置JDK(安装oracle必须先配好jdk): 1.右击计算机-属性-高级系统设置-高级-环境变量,弹出“环境变量”对话框.在Administrator的用户变量里添加: JAVA_HOME指明JD ...