图像相似度计算之哈希值方法OpenCV实现
http://blog.csdn.net/fengbingchun/article/details/42153261
Image Processing(18) 
版权声明:本文为博主原创文章,未经博主允许不得转载。
感知哈希算法(perceptual hash algorithm),它的作用是对每张图像生成一个“指纹”(fingerprint)字符串,然后比较不同图像的指纹。结果越接近,就说明图像越相似。
实现步骤:
1. 缩小尺寸:将图像缩小到8*8的尺寸,总共64个像素。这一步的作用是去除图像的细节,只保留结构/明暗等基本信息,摒弃不同尺寸/比例带来的图像差异;
2. 简化色彩:将缩小后的图像,转为64级灰度,即所有像素点总共只有64种颜色;
3. 计算平均值:计算所有64个像素的灰度平均值;
4. 比较像素的灰度:将每个像素的灰度,与平均值进行比较,大于或等于平均值记为1,小于平均值记为0;
5. 计算哈希值:将上一步的比较结果,组合在一起,就构成了一个64位的整数,这就是这张图像的指纹。组合的次序并不重要,只要保证所有图像都采用同样次序就行了;
6. 得到指纹以后,就可以对比不同的图像,看看64位中有多少位是不一样的。在理论上,这等同于”汉明距离”(Hamming distance,在信息论中,两个等长字符串之间的汉明距离是两个字符串对应位置的不同字符的个数)。如果不相同的数据位数不超过5,就说明两张图像很相似;如果大于10,就说明这是两张不同的图像。
以上内容摘自:http://www.ruanyifeng.com/blog/2011/07/principle_of_similar_image_search.html
下面是用OpenCV实现的测试代码:
- string strSrcImageName = "src.jpg";
- cv::Mat matSrc, matSrc1, matSrc2;
- matSrc = cv::imread(strSrcImageName, CV_LOAD_IMAGE_COLOR);
- CV_Assert(matSrc.channels() == 3);
- cv::resize(matSrc, matSrc1, cv::Size(357, 419), 0, 0, cv::INTER_NEAREST);
- //cv::flip(matSrc1, matSrc1, 1);
- cv::resize(matSrc, matSrc2, cv::Size(2177, 3233), 0, 0, cv::INTER_LANCZOS4);
- cv::Mat matDst1, matDst2;
- cv::resize(matSrc1, matDst1, cv::Size(8, 8), 0, 0, cv::INTER_CUBIC);
- cv::resize(matSrc2, matDst2, cv::Size(8, 8), 0, 0, cv::INTER_CUBIC);
- cv::cvtColor(matDst1, matDst1, CV_BGR2GRAY);
- cv::cvtColor(matDst2, matDst2, CV_BGR2GRAY);
- int iAvg1 = 0, iAvg2 = 0;
- int arr1[64], arr2[64];
- for (int i = 0; i < 8; i++) {
- uchar* data1 = matDst1.ptr<uchar>(i);
- uchar* data2 = matDst2.ptr<uchar>(i);
- int tmp = i * 8;
- for (int j = 0; j < 8; j++) {
- int tmp1 = tmp + j;
- arr1[tmp1] = data1[j] / 4 * 4;
- arr2[tmp1] = data2[j] / 4 * 4;
- iAvg1 += arr1[tmp1];
- iAvg2 += arr2[tmp1];
- }
- }
- iAvg1 /= 64;
- iAvg2 /= 64;
- for (int i = 0; i < 64; i++) {
- arr1[i] = (arr1[i] >= iAvg1) ? 1 : 0;
- arr2[i] = (arr2[i] >= iAvg2) ? 1 : 0;
- }
- int iDiffNum = 0;
- for (int i = 0; i < 64; i++)
- if (arr1[i] != arr2[i])
- ++iDiffNum;
- cout<<"iDiffNum = "<<iDiffNum<<endl;
- if (iDiffNum <= 5)
- cout<<"two images are very similar!"<<endl;
- else if (iDiffNum > 10)
- cout<<"they are two different images!"<<endl;
- else
- cout<<"two image are somewhat similar!"<<endl;
图像相似度计算之哈希值方法OpenCV实现的更多相关文章
- win10下计算文件哈希值的方法
cmd下使用certutil命令 使用方法: certutil -hashfile FILE_NAME ALGORITHM_NAME 支持的加密算法包括:MD2,MD4,MD5,SHA1,SHA256 ...
- Opencv python图像处理-图像相似度计算
一.相关概念 一般我们人区分谁是谁,给物品分类,都是通过各种特征去辨别的,比如黑长直.大白腿.樱桃唇.瓜子脸.王麻子脸上有麻子,隔壁老王和儿子很像,但是儿子下巴涨了一颗痣和他妈一模一样,让你确定这是你 ...
- Java 对象的哈希值是每次 hashCode() 方法调用重计算么?
对于没有覆盖hashCode()方法的对象 如果没有覆盖 hashCode() 方法,那么哈希值为底层 JDK C++ 源码实现,实例每次调用hashcode()方法,只有第一次计算哈希值,之后哈希值 ...
- 我用JAVA做了个简易图像相似度计算器
简单说两句: 笔主利用这个七夕前后两天的寂寞时光,用JAVA磨了一个简单的图像相似度计算小程序,就在刚才终于纠结完毕,输出了1.0版本,小小的满足了一下可怜的虚荣心..→_→ 使用最简单最基础的感知哈 ...
- 转-------CNN图像相似度匹配 2-channel network
基于2-channel network的图片相似度判别 原文地址:http://blog.csdn.net/hjimce/article/details/50098483 作者:hjimce 一.相 ...
- 加解密(校验哈希值、MD5值)
1.计算文本哈希值: public static string ComputeHash(string password) { byte[] buffer = System.Text.Encoding. ...
- 上传图片用图片文件的对象hash哈希值判断图片是否一样,避免重复提交相同的图片到服务器中
上传图片用图片文件的对象hash哈希值判断图片是否一样,避免重复提交相同的图片到服务器中 前端:要用到一个插件,点击下载 <!DOCTYPE html> <html xmlns=&q ...
- 红黑树规则,TreeSet原理,HashSet特点,什么是哈希值,HashSet底层原理,Map集合特点,Map集合遍历方法
==学习目标== 1.能够了解红黑树 2.能够掌握HashSet集合的特点以及使用(特点以及使用,哈希表数据结构) 3.能够掌握Map集合的特点以及使用(特点,常见方法,Map集合的遍历) 4.能够掌 ...
- Java中String的哈希值计算
下面都是从String类的源码中粘贴出来的 private int hash; // Default to 0 public int hashCode() { int h = hash; if (h ...
随机推荐
- PNPOLY - Point Inclusion in Polygon Test
https://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html The C Code Here is the code, ...
- 32bit程序在64bit操作系统下处理重定向细节(转自http://bbs.pediy.com/showthread.php?t=89054)
1. 64bit操作系统的重定向机制以及目的 在64bit操作系统中,为了无缝兼容32bit程序的运行,64bit的Windows操作系统采用重定向机制.目的是为了能让32bit程序在64bit的操作 ...
- 分布式版本控制系统Git-----3.图形化Tortoisegit创建本地库并且提交到远程服务器上
[前提你已经有了自己的远程仓库帐号密码和HTTP地址] PS:图形化会方便,但是个人认为还是敲命令比较好,会锻炼人的思维和逻辑. 1.首先在任意一个地方创建test目录.若要把test目录放在Git的 ...
- uva 12356 Army Buddies
简单的并查集应用. #include<stdio.h> #include<string.h> #include<math.h> #include<algori ...
- 使用javassist运行时动态重新加载java类及其他替换选择
在不少的情况下,我们需要对生产中的系统进行问题排查,但是又不能重启应用,java应用不同于数据库的存储过程,至少到目前为止,还不能原生的支持随时进行编译替换,从这种角度来说,数据库比java的动态性要 ...
- thinkphp 的两种建构模式 第一种一个单入口里面定义两个模块,前台和后台,函数控制模块必须function.php前台加载前台模块的汉书配置文件,后台加载后台模块的汉书配置文件,公共文件共用。第二种架构模式两个单入口文件,分别生成两个应用定义define。。。函数可以定义配置文件。。。。
thinkphp 的两种建构模式 第一种一个单入口里面定义两个模块,前台和后台,函数控制模块必须function.php前台加载前台模块的汉书配置文件,后台加载后台模块的汉书配置文件,公共文件共用. ...
- vs2013+opencv2.4.11+Qt5.5.1配置
注意本教程配置环境:win7 32位 如果只配置vs2013+opencv2.4.11,参考http://jingyan.baidu.com/article/ff411625b1311a12e4823 ...
- mysql的字符串处理函数
一.简明总结ASCII(char) 返回字符的ASCII码值BIT_LENGTH(str) 返回字符串的比特长度CONCAT(s1,s2…,sn) 将s1,s2…,sn连接成字符串CONCAT_WS( ...
- LeetCode OJ 78. Subsets
Given a set of distinct integers, nums, return all possible subsets. Note: Elements in a subset must ...
- Chapter 15_4 子模块和包
Lua支持具有层级性的模块名,可以用一个点来分隔名称中的层级. 比如,一个mod.sub模块,它就是mod的子模块.一个包(package)就是一个完整的模块树. 当你require "mo ...