相似图片检测:感知哈希算法之aHash,dHash,pHash的Python实现

原文:http://blog.sina.com.cn/s/blog_56fd58ab0102xpqf.html

感知哈希算法是一类算法的总称,包括aHash、pHash、dHash。顾名思义,感知哈希不是以严格的方式计算Hash值,而是以更加相对的方式计算哈希值,因为“相似”与否,就是一种相对的判定。某些情况下,我们需要检测图片之间的相似性,进行我们需要的处理:删除同一张图片、标记盗版等。
如何判断是同一张图片呢?最简单的方法是使用加密哈希(例如MD5, SHA-1)判断。但是局限性非常大。例如一个txt文档,其MD5值是根据这个txt的二进制数据计算的,如果是这个txt文档的完全复制版,那他们的MD5值是完全相同的。但是,一旦改变副本的内容,哪怕只是副本的缩进格式,其MD5也会天差地别。因此加密哈希只能用于判断两个完全一致、未经修改的文件,如果是一张经过调色或者缩放的图片,根本无法判断其与另一张图片是否为同一张图片。
那么如何判断一张被PS过的图片是否与另一张图片本质上相同呢?比较简单、易用的解决方案是采用感知哈希算法(Perceptual Hash Algorithm)。

  • aHash:平均值哈希。速度比较快,但是常常不太精确。
  • pHash:感知哈希。精确度比较高,但是速度方面较差一些。
  • dHash:差异值哈希。Amazing!精确度较高,且速度也非常快。因此我就选择了dHash作为我图片判重的算法。
compare_ssim比较图像相似,光照不一样,图像不相似

phash:光照变化会过滤掉,64*64需要1ms左右

dhash需要2ms左右

import datetimepath=r"D:\data\similar"a=path+"/0720_090352_840781.jpg"
b=path+"/0720_133954_832176.jpg"
# b=path+"/0720_085858_768830.jpg"import cv2
import numpy as np
import time#Hash值对比
def cmpHash(hash1,hash2):n=0#hash长度不同则返回-1代表传参出错if len(hash1)!=len(hash2):return -1#遍历判断for i in range(len(hash1)):#不相等则n计数+1,n最终为相似度if hash1[i]!=hash2[i]:n=n+1return 1 - n / 64def pHash(img):"""get image pHash value"""#加载并调整图片为32x32灰度图片# img=cv2.imread(imgfile, 0)#创建二维列表h, w = img.shape[:2]vis0 = np.zeros((h,w), np.float32)vis0[:h,:w] = img #填充数据#二维Dct变换vis1 = cv2.dct(cv2.dct(vis0))#cv.SaveImage('a.jpg',cv.fromarray(vis0)) #保存图片vis1.resize(32,32)#把二维list变成一维listimg_list=vis1.flatten()#计算均值avg = sum(img_list)*1./len(img_list)avg_list = ['0' if i else '1' for i in img_list]#得到哈希值return ''.join(['%x' % int(''.join(avg_list[x:x+4]),2) for x in range(0,32*32,4)])'''
cv2.imread
flags>0时表示以彩色方式读入图片
flags=0时表示以灰度图方式读入图片
flags<0时表示以图片的本来的格式读入图片interpolation - 插值方法。共有5种:
1)INTER_NEAREST - 最近邻插值法
2)INTER_LINEAR - 双线性插值法(默认)
3)INTER_AREA - 基于局部像素的重采样(resampling using pixel area relation)。对于图像抽取(image decimation)来说,这可能是一个更好的方法。但如果是放大图像时,它和最近邻法的效果类似。
4)INTER_CUBIC - 基于4x4像素邻域的3次插值法
5)INTER_LANCZOS4 - 基于8x8像素邻域的Lanczos插值
'''
def hammingDist(s1, s2):
#assert len(s1) == len(s2)return 1 - sum([ch1 != ch2 for ch1, ch2 in zip(s1, s2)])*1. / (32*32/4)if __name__ == '__main__':img1 = cv2.imread(a,0)img2 = cv2.imread(b,0)img1 = cv2.resize(img1, (64, 64), interpolation=cv2.INTER_CUBIC)img2 = cv2.resize(img2, (64, 64), interpolation=cv2.INTER_CUBIC)time1 = datetime.datetime.now()hash1 =pHash(img1)hash2 = pHash(img2)n = cmpHash(hash1, hash2)print('均值哈希算法相似度:', n, "--time=", (datetime.datetime.now() - time1).microseconds)time1 = time.time()
import datetimepath=r"D:\data\similar"a=path+"/0720_090352_840781.jpg"
b=path+"/0720_133954_832176.jpg"
# b=path+"/0720_085858_768830.jpg"import cv2
import numpy as np
import time
#均值哈希算法
def aHash(img):#缩放为8*8img=cv2.resize(img,(8,8),interpolation=cv2.INTER_CUBIC)#转换为灰度图gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#s为像素和初值为0,hash_str为hash值初值为''s=0hash_str=''#遍历累加求像素和for i in range(8):for j in range(8):s=s+gray[i,j]#求平均灰度avg=s/64#灰度大于平均值为1相反为0生成图片的hash值for i in range(8):for j in range(8):if gray[i,j]>avg:hash_str=hash_str+'1'else:hash_str=hash_str+'0'return hash_str#差值感知算法
def dHash(img):#缩放8*8img=cv2.resize(img,(9,8),interpolation=cv2.INTER_CUBIC)#转换灰度图gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)hash_str=''#每行前一个像素大于后一个像素为1,相反为0,生成哈希for i in range(8):for j in range(8):if gray[i,j]>gray[i,j+1]:hash_str=hash_str+'1'else:hash_str=hash_str+'0'return hash_str#Hash值对比
def cmpHash(hash1,hash2):n=0#hash长度不同则返回-1代表传参出错if len(hash1)!=len(hash2):return -1#遍历判断for i in range(len(hash1)):#不相等则n计数+1,n最终为相似度if hash1[i]!=hash2[i]:n=n+1return 1 - n / 64def pHash(imgfile):"""get image pHash value"""#加载并调整图片为32x32灰度图片# img=cv2.imread(imgfile, 0)img=cv2.resize(imgfile,(64,64),interpolation=cv2.INTER_CUBIC)#创建二维列表h, w = img.shape[:2]vis0 = np.zeros((h,w), np.float32)vis0[:h,:w] = img #填充数据#二维Dct变换vis1 = cv2.dct(cv2.dct(vis0))#cv.SaveImage('a.jpg',cv.fromarray(vis0)) #保存图片vis1.resize(32,32)#把二维list变成一维listimg_list=vis1.flatten()#计算均值avg = sum(img_list)*1./len(img_list)avg_list = ['0' if i else '1' for i in img_list]#得到哈希值return ''.join(['%x' % int(''.join(avg_list[x:x+4]),2) for x in range(0,32*32,4)])'''
cv2.imread
flags>0时表示以彩色方式读入图片
flags=0时表示以灰度图方式读入图片
flags<0时表示以图片的本来的格式读入图片interpolation - 插值方法。共有5种:
1)INTER_NEAREST - 最近邻插值法
2)INTER_LINEAR - 双线性插值法(默认)
3)INTER_AREA - 基于局部像素的重采样(resampling using pixel area relation)。对于图像抽取(image decimation)来说,这可能是一个更好的方法。但如果是放大图像时,它和最近邻法的效果类似。
4)INTER_CUBIC - 基于4x4像素邻域的3次插值法
5)INTER_LANCZOS4 - 基于8x8像素邻域的Lanczos插值
'''
def hammingDist(s1, s2):
#assert len(s1) == len(s2)return 1 - sum([ch1 != ch2 for ch1, ch2 in zip(s1, s2)])*1. / (32*32/4)if __name__ == '__main__':img1 = cv2.imread(a)img2 = cv2.imread(b)time1 = datetime.datetime.now()hash1 = dHash(img1)hash2 = dHash(img2)n = cmpHash(hash1, hash2)print('均值哈希算法相似度:', n, "--time=", (datetime.datetime.now() - time1).microseconds)time1 = time.time()

相似图片检测:感知哈希算法之aHash,dHash,pHash的Python实现相关推荐

  1. 图片识别——感知哈希算法

    所谓感知哈希算法(Perceptual hash algorithm,PHA),它是用于对多种格式的数据生成一个指纹的算法.当然本文只讨论图片格式.感知哈希不同于密码哈希(如md5云云),它对于相似特 ...

  2. 相似图片检测:感知哈希算法之dHash的Python实现

    原文:https://blog.csdn.net/haluoluo211/article/details/52769325 相似图片检测:感知哈希算法之dHash的Python实现 某些情况下,我们需 ...

  3. 感知哈希算法——找出相似的图片

    参考Neal Krawetz博士的这篇文章, 实现这种功能的关键技术叫做"感知哈希算法"(Perceptual Hash Algorithm), 意思是为图片生成一个指纹(字符串格 ...

  4. 【转】感知哈希算法——找出相似的图片

    Google 图片搜索功能 在谷歌图片搜索中, 用户可以上传一张图片, 谷歌显示因特网中与此图片相同或者相似的图片. 比如我上传一张照片试试效果: 原理讲解 参考Neal Krawetz博士的这篇文章 ...

  5. 基于感知哈希算法的中药标本相似图片的搜索

    一 前言 笔者最近在开发中药标本相似图片的搜索,就是根据用户上传的图片,然后到中药标本库里找到相似的图片,从而帮助用户识别标本,获取标本信息.查阅了大量资料,看到了阮一峰的一篇文章,经过一个月的开发终 ...

  6. 感知哈希算法原理与实现

    今天忽然想做一个图像识别的APP,但是在两张图片相似度的问题上产生了问题,感知哈希算法并不能解决这个问题,只是我在试着解决问题的过程中学到的一点知识. 这里的关键技术叫做"感知哈希算法&qu ...

  7. 感知哈希算法(Perceptual hash algorithm)的OpenCV实现

    1.前言 目前"以图搜图"的引擎越来越多,可参考博文: http://blog.csdn.net/forthcriminson/article/details/8698175 此篇 ...

  8. 图片识别——均值哈希算法

    均值哈希算法(Average hash algorithm,AHA)第一次是从著名的阮一峰阮老师的博文<相似图片搜索的原理>看到的.而此篇文章与阮老师也很类似Looks Like It - ...

  9. 图像比对-感知哈希算法

    感知哈希算法是一类哈希算法的总称,其作用在于生成每张图像的"指纹"(fingerprint)字符串,比较不同图像的指纹信息来判断图像的相似性.结果越接近图像越相似.感知哈希算法包括 ...

最新文章

  1. SQL Server 2014 许可证(五)降级与升级
  2. linux查看log4c版本号,linux下安装log4cplus
  3. This version of MySQL doesn't yet support 'LIMIT IN/ALL/ANY/SOME subquery'
  4. 多点积分又改规则了_2020年落户广州积分入户名额有多少个?如何加分?
  5. Search Engine XSS Worm
  6. 确定Java等价性的新时代?
  7. FreeRTOS信号量---二值信号量
  8. 64位游戏找call_网络小游戏怎么修改技能满级,满血?教大家一个很简单的修改方法!...
  9. html中的声明的作用域,Html/CSS 作用域
  10. MyEclipse10 离线图文安装SVN插件教程
  11. Lua_手册_代码版
  12. 图像形状特征(四)--轮廓树及PGH
  13. phpexcel读取输出操作
  14. [转]中国七大顶级黑客X档案
  15. 【附源码】计算机毕业设计SSM网上汽车租赁系统
  16. 使用sikuli测试web网页实例
  17. 2022-2027年中国酒店餐饮行业市场调研及未来发展趋势预测报告
  18. 如何用自签名证书给.Sis文件签名
  19. 3大奇葩排序之猴子算法
  20. 用VHDL编写testbench激励文件

热门文章

  1. 数组之间的计算matlab,MATLAB软件数组的运算
  2. 实现用户协议显示_HTTP协议工作原理及其特点
  3. java计算24小时之内_java的系统时间,怎么计算从现在到凌晨还剩下多少时间?
  4. 华为手机获取状态栏高度是错误的_华为后置指纹这么多功能,你不会还以为只能解锁和支付吧...
  5. MySQL DATE_FORMAT() 函数
  6. 灰度值取值范围_一幅灰度图像,用8bit量化,取值范围为[0,255],其中0表示(),255表示()。...
  7. mysql b 树删除操作,B-树的删除过程介绍
  8. 节省磁盘空间的新一代包管理工具PNPM
  9. 与优秀的人在一起,自己也会优秀起来!高质量技术群等你加入!
  10. 编程一万小时是种什么样的体验?