平均哈希算法

实现步骤

  1. 缩小尺寸:将图像缩小到8*8的尺寸,总共64个像素。这一步的作用是去除图像的细节,只保留结构/明暗等基本信息,摒弃不同尺寸/比例带来的图像差异;
  2. 简化色彩:将缩小后的图像,转为64级灰度,即所有像素点总共只有64种颜色;
  3. 计算平均值:计算所有64个像素的灰度平均值;
  4. 比较像素的灰度:将每个像素的灰度,与平均值进行比较,大于或等于平均值记为1,小于平均值记为0;
  5. 计算哈希值:将上一步的比较结果,组合在一起,就构成了一个64位的整数,这就是这张图像的指纹。组合的次序并不重要,只要保证所有图像都采用同样次序就行了;
  6. 得到指纹以后,就可以对比不同的图像,看看64位中有多少位是不一样的。在理论上,这等同于”汉明距离”(Hamming distance,在信息论中,两个等长字符串之间的汉明距离是两个字符串对应位置的不同字符的个数)。如果不相同的数据位数不超过5,就说明两张图像很相似;如果大于10,就说明这是两张不同的图像。

代码

int aHash(Mat matSrc1, Mat matSrc2)
{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;return iDiffNum;
}

感知哈希算法

平均哈希算法过于严格,不够精确,更适合搜索缩略图,为了获得更精确的结果可以选择感知哈希算法,它采用的是DCT(离散余弦变换)来降低频率的方法

一般步骤

  1. 缩小图片:32 * 32是一个较好的大小,这样方便DCT计算
  2. 转化为灰度图
  3. 计算DCT:利用Opencv中提供的dct()方法,注意输入的图像必须是32位浮点型
  4. 缩小DCT:DCT计算后的矩阵是32 * 32,保留左上角的8 * 8,这些代表的图片的最低频率
  5. 计算平均值:计算缩小DCT后的所有像素点的平均值
  6. 大于平均值记录为1,反之记录为0
  7. 得到信息指纹

代码

int pHash(Mat matSrc1, Mat matSrc2)
{Mat matDst1, matDst2;cv::resize(matSrc1, matDst1, cv::Size(32, 32), 0, 0, cv::INTER_CUBIC);cv::resize(matSrc2, matDst2, cv::Size(32, 32), 0, 0, cv::INTER_CUBIC);cv::cvtColor(matDst1, matDst1, CV_BGR2GRAY);cv::cvtColor(matDst2, matDst2, CV_BGR2GRAY);matDst1.convertTo(matDst1, CV_32F);matDst2.convertTo(matDst2, CV_32F);dct(matDst1, matDst1);dct(matDst2, matDst2);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];arr2[tmp1] = data2[j];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;return iDiffNum;
}

dHash算法

  1. 缩小图片:收缩到8*9的大小,以便它有72的像素点
  2. 转化为灰度图
  3. 计算差异值:dHash算法工作在相邻像素之间,这样每行9个像素之间产生了8个不同的差异,一共8行,则产生了64个差异值
  4. 获得指纹:如果左边的像素比右边的更亮,则记录为1,否则为0

平均结构相似性 MSSIM 算法

原理

代码

double getMSSIM(const Mat& i1, const Mat& i2)
{const double C1 = 6.5025, C2 = 58.5225;/***************************** INITS **********************************/int d = CV_32F;Mat I1, I2;i1.convertTo(I1, d);           // cannot calculate on one byte large valuesi2.convertTo(I2, d);Mat I2_2 = I2.mul(I2);        // I2^2Mat I1_2 = I1.mul(I1);        // I1^2Mat I1_I2 = I1.mul(I2);        // I1 * I2/*************************** END INITS **********************************/Mat mu1, mu2;   // PRELIMINARY COMPUTINGGaussianBlur(I1, mu1, Size(11, 11), 1.5);GaussianBlur(I2, mu2, Size(11, 11), 1.5);Mat mu1_2 = mu1.mul(mu1);Mat mu2_2 = mu2.mul(mu2);Mat mu1_mu2 = mu1.mul(mu2);Mat sigma1_2, sigma2_2, sigma12;GaussianBlur(I1_2, sigma1_2, Size(11, 11), 1.5);sigma1_2 -= mu1_2;GaussianBlur(I2_2, sigma2_2, Size(11, 11), 1.5);sigma2_2 -= mu2_2;GaussianBlur(I1_I2, sigma12, Size(11, 11), 1.5);sigma12 -= mu1_mu2;/ FORMULA Mat t1, t2, t3;t1 = 2 * mu1_mu2 + C1;t2 = 2 * sigma12 + C2;t3 = t1.mul(t2);              // t3 = ((2*mu1_mu2 + C1).*(2*sigma12 + C2))t1 = mu1_2 + mu2_2 + C1;t2 = sigma1_2 + sigma2_2 + C2;t1 = t1.mul(t2);               // t1 =((mu1_2 + mu2_2 + C1).*(sigma1_2 + sigma2_2 + C2))Mat ssim_map;divide(t3, t1, ssim_map);      // ssim_map =  t3./t1;Scalar mssim = mean(ssim_map); // mssim = average of ssim mapreturn (mssim[0] + mssim[1] + mssim[2])/3;
}

由于项目需要使用了上述算法,测试后发现平均哈希算法进行两张图像相似度对比的效果是最好的(有些奇怪)。测试的样本大多是完全相同的两个图片(只是明暗度不一样,比如阴影),iDiffNum 的值一般在10左右。对于明显不同的两张图片,上述算法都存在错误判断的情况(返回的iDiffNum在10左右,正常的应该在20以外)。

reference:

[1] http://blog.csdn.net/wangyaninglm/article/details/43853435

[2] http://www.jb51.net/article/83315.htm

[3] http://blog.csdn.net/ecnu18918079120/article/details/60149864

OpenCV进行图像相似度对比的几种办法相关推荐

  1. OpenCV 进行图像相似度对比的几种办法-【顺带附py对比学习案例】

    最近研究了下计算机视觉.图像对比参考了一下py的一些源码和思路等信息学习学习. 但是呢只能对应相似度.稍微改一改剪切了图片后的就变化差异比较大,对目前自己的需求来说不是很有作用,顺带整理分享一下. 如 ...

  2. 【图像识别与处理】图像相似度对比的几种办法

    对计算图像相似度的方法,本文做了如下总结,主要有三种办法: 1.PSNR峰值信噪比 PSNR(Peak Signal to Noise Ratio),一种全参考的图像质量评价指标. 简介:https: ...

  3. 进行图像相似度对比的几种办法

    转载自 1.直方图方法 方法描述:有两幅图像patch(当然也可是整幅图像),分别计算两幅图像的直方图,并将直方图进行归一化,然后按照某种距离度量的标准进行相似度的测量. 方法的思想:基于简单的向量相 ...

  4. lm opencv 算法_OpenCV进行图像相似度对比的几种办法

    // PSNR.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include // Console I/O #include // St ...

  5. CV之Hog+HamMingDistance:基于Hog提取和汉明距离对比的应用—图像相似度对比之for循环将多个成对图片依次对比并输出相似度

    CV之Hog+HamMingDistance:基于Hog提取和汉明距离对比的应用-图像相似度对比之for循环将多个成对图片依次对比并输出相似度 目录 测试数据集 核心代码 相关文章 ML之相似度计算: ...

  6. python图片相似度计算_python Opencv计算图像相似度过程解析

    这篇文章主要介绍了python Opencv计算图像相似度过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.相关概念 一般我们人区分谁是谁 ...

  7. 图像相似度对比-直方图

    想要排除神经网络训练集中大量的重复图片,但网上找不到合适的图片对比工具.自己写一个 要对比的图片 img0 img1 1. 直方图相似度对比 如果我们有两张图像,并且这两张图像的直方图一样,或者有极高 ...

  8. OpenCV—python 图像相似度算法(dHash,方差)

    文章目录 一.SIFT综述 二.哈希算法(perceptual hash algorithm) 2.1 相似图片检测步骤: 2.2 代码实现 三.使用方差检测图像相似度 3.1 实现步骤 3.2 代码 ...

  9. 深入学习OpenCV中图像相似度的算法

    最近一段时间学习并做的都是对图像进行处理,其实自己也是新手,各种尝试,所以我这个门外汉想总结一下自己学习的东西,图像处理的流程.但是动起笔来想总结,一下却不知道自己要写什么,那就把自己做过的相似图片搜 ...

最新文章

  1. 如何使用canvas绘图
  2. /sbin/ifup: configuration for eth0 not found解决
  3. Java 中这些常用关键字,总有那么些被你遗忘的
  4. IDEA的UML图介绍(一)
  5. Java多线程-CountDownLatch用法
  6. 基于JAVA实现的客户信息管理软件(简易)
  7. Python基础七(深浅copy以及int,str,tuple,list,dic补充)
  8. Android ViewPager实现3D画廊效果
  9. 怎么缩小图片大小kb
  10. 普通网站的建设和维护费用大概是多少?
  11. 让运行ubuntu20.04的笔记本电脑实现关闭盖子自动休眠
  12. iOS系统字体如何使用
  13. Appium TestNg Maven Android Eclipse java简单启动实例
  14. 制作一个favcion.ico
  15. scanpy 单细胞分析包图文详解 01 | 深入理解 AnnData 数据结构
  16. GitLab - Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password)
  17. shell cheat sheet (备忘录)
  18. 【NKOJ-3170】逃离迷宫1
  19. 探寻 vivo 印度崛起背后的秘密
  20. 深度学习aec数据前处理脚本,基于timit和汪德亮老师的paper

热门文章

  1. html5新增的js api,对HTML5新增JS Api的思考
  2. linux cgi命令,Linux之cgi实现系统主机监控
  3. python英文语义角色标注_【顶会100秒】基于相似词计算的旅游词汇语义分析
  4. 单片机点灯不难,但你会网页点灯吗?
  5. 在php100 防恶意注册这个需要怎么填,WordPress防止恶意注册代码
  6. HDLBits答案(7)_Verilog多路选择器
  7. AD4003 VHDL设计及仿真
  8. java 复制文件_Java中复制文件的4种方法
  9. centos xampp安装mysql_在xampp上部署dvwa|centos(linux)环境
  10. java 防止反射_Java设计模式(一):单例模式,防止反射和反序列化漏洞