度量两张图片的相似度有许多算法,本文讲介绍工程领域中最常用的图片相似度算法之一——Hash算法。Hash算法准确的说有三种,分别为平均哈希算法(aHash)、感知哈希算法你(pHash)和差异哈哈希算法(dHash)。

       三种Hash算法都是通过获取图片的hash值,再比较两张图片hash值的汉明距离(韩明距离的概念可见本公众号《》一文)来度量两张图片是否相似。两张图片越相似,那么两张图片的hash数的汉明距离越小。下面本文将分别介绍这三种Hash算法。

1 平均哈希算法(aHash)

1.1 算法步骤

       平均哈希算法是三种Hash算法中最简单的一种,它通过下面几个步骤来获得图片的Hash值,这几个步骤分别是(1) 缩放图片;(2)转灰度图; (3) 算像素均值;(4)根据相似均值计算指纹。具体算法如下所示:

表1 aHash得到图片Hash值地算法

步骤 具体内容
缩放图片 输入图片大小尺寸各异,为了统一图片的输入,统一将图片尺寸缩放为8*8,一共得到了64个像素点。
转灰度图 输入图片有些为单通道灰度图,有些RGB三通道彩色图,有些为RGBA四通道彩色图。也为了统一下一步输入标准,将非单通道图片都转为单通道灰度图。 其中RGB三通道转单通道算法有下面几种:
1.浮点算法:Gray=R0.3+G0.59+B0.11
2.整数方法:Gray=(R
30+G59+B11)/100
3.移位方法:Gray =(R76+G151+B*28)>>8;
4.平均值法:Gray=(R+G+B)/3;
5.仅取绿色:Gray=G;
算像素均值 通过上一步可得一个8x8的整数矩阵G,计算这个矩阵中所有元素的平均值,假设其值为a
据像素均值计算指纹 初始化输入图片的ahash = ""
从左到右一行一行地遍历矩阵G每一个像素如果第i行j列元素G(i,j) >= a,则ahash += "1"如果第i行j列元素G(i,j) <a, 则ahash += "0"

       得到图片的ahash值后,比较两张图片ahash值的汉明距离,通常认为汉明距离小于10的一组图片为相似图片。

1.2 具体实例

       本文图片为Lena图来说明.



图1 Lena(Origin)图



图2 转为8x8尺寸的Lena图



图3 转为灰度8x8尺寸的Lena图

       其中转为8x8尺寸的Lena对应的数据矩阵为:

       很容得到如上矩阵所有元素的均值a= 121.328125, 将上述矩阵中大于或等于a的元素置为1, 小于a的元素置为0,可得:

       所以可得Lena图的aHash为

       1011111010011110100111011010100110101011101000110000111000101100

       将二进制形式ahash转十六进制hash为

       be9e9da9aba30e2c

       为了测试aHash算法的效果,我们用一张带噪声Lena(noise)图和与Lena不一样的Barbara做图片相似度对比实验,其中Lena(noise)和Barbara如下:



图4 Lena(noise)图



图5 Barbara图

       通过aHash算法容易得三个图片的hash值,然后根据hanming距离计算Lena(origin).png和Lena(noise).png Barbar.png之间汉明距离,具体如下:



图6 aHash算法图片相似度实验

       由上图可见aHash能区别相似图片和差异大的图片。

2 感知哈希算法(pHash)

2.1 算法步骤

       感知哈希算法是三种Hash算法中较为复杂的一种,它是基于DCT(离散余弦变换)来得到图片的hash值,其算法几个步骤分别是(1) 缩放图片;(2)转灰度图; (3) 计算DCT;(4)缩小DCT; (5)算平均值;(6) 计算指纹。具体算法如下所示:

表2 pHash得到图片Hash值地算法

步骤 具体内容
缩放图片 统一将图片尺寸缩放为32*32,一共得到了1024个像素点。
转灰度图 统一下一步输入标准,将非单通道图片都转为单通道灰度图。
计算DCT 计算32x32数据矩阵的离散余弦变换后对应的32x32数据矩阵
缩小DCT 取上一步得到32x32数据矩阵左上角8x8子区域
算平均值 通过上一步可得一个8x8的整数矩阵G, 计算这个矩阵中所有元素的平均值,假设其值为a
计算指纹 初始化输入图片的phash = ""
从左到右一行一行地遍历矩阵G每一个像素
如果第i行j列元素G(i,j) >= a,则phash += "1"
如果第i行j列元素G(i,j) <a, 则phash += "0"

       得到图片的phash值后,比较两张图片phash值的汉明距离,通常认为汉明距离小于10的一组图片为相似图片。

2.2 具体实例

       仍用Lena图来说明.



图7 转为灰度32x32尺寸的Lena图



图8 灰度32x32尺寸Lena图对应的DCT矩阵

       通过计算可得灰度32x32Lenna图对应的DCT矩阵左上角8x8区域子矩阵为:

       很容得到如上矩阵所有元素的均值a= 77.35, 将上述矩阵中大于或等于a的元素置为1, 小于a的元素置为0,可得:

       所以可得Lena图的pHash为

       1001100111000100010101000010010101100000001000111000001010000000

       将二进制形式phash转十六进制hash为

       99c4542560238280

       为了测试pHash算法的效果,同样用一张带噪声Lena(noise)图和与Lena不一样的Barbara做图片相似度对比实验。通过pHash算法容易得三个图片的hash值,然后根据hanming距离计算Lena(origin).png和Lena(noise).png Barbar.png之间汉明距离,具体如下:



图9 pHash算法图片相似度实验

       由上图可见pHash能区别相似图片和差异大的图片。

3 差异哈希算法(dHash)

3.1 算法步骤

       相比pHash,dHash的速度要快的多,相比aHash,dHash在效率几乎相同的情况下的效果要更好,它是基于渐变实现的。其算法几个步骤分别是(1) 缩放图片;(2)转灰度图; (3) 计算DCT;
(4)缩小DCT; (5)算平均值;(6) 计算指纹。具体算法如下所示:

表3 dHash得到图片Hash值地算法

步骤 具体内容
小图片 统一将图片尺寸缩放为9x8,一共得到了72个像素点
转灰度图 统一下一步输入标准,将非单通道图片都转为单通道灰度图。
算差异值 当前行像素值-前一行像素值, 从第二到第九行共8行,又因为矩阵有8列,所以得到一个8x8差分矩阵G
算平均值 通过上一步可得一个8x8的整数矩阵G, 计算这个矩阵中所有元素的平均值,假设其值为a
计算指纹 初始化输入图片的dhash = ""
从左到右一行一行地遍历矩阵G每一个像素
如果第i行j列元素G(i,j) >= a,则dhash += "1"
如果第i行j列元素G(i,j) <a, 则dhash += "0"

       得到图片的phash值后,比较两张图片phash值的汉明距离,通常认为汉明距离小于10的一组图片为相似图片。

3.2 具体实例

       仍用Lena图来说明.



图7 转为灰度9x8尺寸的Lena图

       通过计算可得灰度9x8Lenna图数据矩阵为:

       从第二行开始进行减去前一行操作,可得如下查分矩阵

       将上述矩阵中大于或等于0元素置为1, 小于a的元素置为0,可得:

       所以可得Lena图的dHash为

       0101100000110111111010000101001001101011101011110001010001010000

       将二进制形式dhash转十六进制hash为

       99c4542560238280

       为了测试dHash算法的效果,同样用一张带噪声Lena(noise)图和与Lena不一样的Barbara做图片相似度对比实验。通过pHash算法容易得三个图片的hash值,然后根据hanming距离计算Lena(origin).png和Lena(noise).png Barbar.png之间汉明距离,具体如下:



图9 dHash算法图片相似度实验

       由上图可见dHash能区别相似图片和差异大的图片。

总结

       关于图像相似度算法除了Hash算法,在传统算法领域中还有基于SIFT的匹配算法,基于Gist特征的匹配算法;在深度学习领域中有基于ResNet全连接的匹配算法。感兴趣的读者可以通过google来了解这些算法。

参考资料

432-Looks-Like-It
529-Kind-of-Like-That

图像相似度中的Hash算法的更多相关文章

  1. HashMap中的hash算法总结

    前言 算法一直是我的弱项,然而面试中基本是必考的项目,刚好上次看到一个HashMap的面试题,今天也来学习下 HashMap中的hash算法是如何实现的. 数学知识回顾 << : 左移运算 ...

  2. 【Java深入研究】11、深入研究hashmap中的hash算法

    一.简介 大家都知道,HashMap中定位到桶的位置 是根据Key的hash值与数组的长度取模来计算的. JDK8中的hash 算法: static final int hash(Object key ...

  3. PHP中各种Hash算法性能比较

    国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...

  4. HashMap中的hash算法中的几个疑问

    HashMap中哈希算法的关键代码 //重新计算哈希值 static final int hash(Object key) { int h; return (key == null) ? 0 : (h ...

  5. php中各种hash算法的执行速度比较

    更多内容推荐微信公众号,欢迎关注: PHP中的Hash函数很多,像MD4.MD5.SHA-1.SHA-256.SHA-384.SHA-512等我们比较常见,那么各个哈希的执行速度呢? $algos = ...

  6. 图像相似度算法的C#实现及测评

    近日逛博客的时候偶然发现了一个有关图片相似度的Python算法实现.想着很有意思便搬到C#上来了,给大家看看. 闲言碎语 才疏学浅,只把计算图像相似度的一个基本算法的基本实现方式给罗列了出来,以至于在 ...

  7. [区块链] 密码学中Hash算法(基础)

    在介绍Hash算法之前,先给大家来个数据结构中对hash表(散列表)的简单解释,然后我再逐步深入,讲解一下hash算法. 一.Hash原理——基础篇 1.1 概念 哈希表就是一种以 键-值(key-i ...

  8. hash算法

    作者:July.wuliming.pkuoliver 说明:本文分为三部分内容, 第一部分为一道百度面试题Top K算法的详解:第二部分为关于Hash表算法的详细阐述:第三部分为打造一个最快的Hash ...

  9. hash算法与hashmap

    参考博客: http://zha-zi.iteye.com/blog/1124484 http://www.cnblogs.com/dolphin0520/p/3681042.html(参考了hash ...

随机推荐

  1. Linux常用实用命令

    Linux是我们开发人员必不可少的系统,也是经常接触到的.然而,Linux命令比较多,有些不常用也难记住.那么,我们如何更高效的使用Linux命令,而又不必全面地学习呢?今天就给大家分享一下我在开发过 ...

  2. Spring源码解读之BeanFactoryPostProcessor的处理

    前言 前段时间旁听了某课堂两节Spring源码解析课,刚好最近自己又在重新学习中,便在这里记录一下学习所得.我之前写过一篇博文,是介绍BeanFactoryPostProcessor跟BeanPost ...

  3. 音视频技术“塔尖”之争,网易云信如何C位出道?

    音视频技术“塔尖”之争,网易云信如何C位出道? 社交+美颜.抖音短视频.在线狼人杀.直播竞答.子弹短信……,过往两三年间,互联网新产品和新玩法层出不穷,风口不断切换.这些爆红的网络应用背后,都有一些共 ...

  4. Android 即时通讯开发小结(一)

    <Android 即时通讯开发小结>基于IM Andriod 开发的各种常见问题,结合网易云信即时通讯技术的实践,对IM 开发做一个全面的总结. 相关推荐阅读:. Android 即时通讯 ...

  5. 并发编程-concurrent指南-ReadWriteLock

    ReadWriteLock也是一个接口,在它里面只定义了两个方法: public interface ReadWriteLock { /** * Returns the lock used for r ...

  6. 屏蔽谷歌浏览器"请停用以开发者模式运行的扩展程序"提示

    目标: 对于强迫症患者那是相当难受~~~ 解决方案: 1:进入chrome://extensions/ 右上角开启开发者模式 点击打包扩展程序: 2:扩展程序目录为选择插件(*.crx解压后)的根目录 ...

  7. c++复杂桶排序Java版

    c++复杂桶排序Java版 题目和我的前几个排序一样 这次是Java版的 代码 + 注释 package com.vdian.qatest.supertagbiz.test.niu; /** * Cr ...

  8. ASP.NET Core系列(一): .NET Core简介及安装开发环境

    大家都知道Java是跨平台的,.NET因为不具有跨平台的特性,被越来越多的开发者诟病,之前有各种间接的跨平台的方案,比如mono.但是由于各种兼容问题,最终 .NET Core出现了,它可以让程序在W ...

  9. 齐治运维堡垒机后台存在命令执行漏洞(CNVD-2019-17294)分析

    基本信息 引用:https://www.cnvd.org.cn/flaw/show/CNVD-2019-17294 补丁信息:该漏洞的修复补丁已于2019年6月25日发布.如果客户尚未修复该补丁,可联 ...

  10. 用Python玩数据-笔记整理-第一章

    第一个程序:print >>>print("Hallo World!") >>>Hallo World! mystring = "Ha ...