OpenCV 图像相似度匹配之感知哈希算法

技术原理

原理参考http://www.cnblogs.com/technology/archive/2012/07/12/Perceptual-Hash-Algorithm.html

   参考Neal Krawetz博士的这篇文章, 实现这种功能的关键技术叫做"感知哈希算法"(Perceptual Hash Algorithm), 意思是为图片生成一个指纹(字符串格式), 两张图片的指纹越相似, 说明两张图片就越相似. 但关键是如何根据图片计算出"指纹"呢? 下面用最简单的步骤来说明一下原理:

第一步 缩小图片尺寸

        将图片缩小到8x8的尺寸, 总共64个像素. 这一步的作用是去除各种图片尺寸和图片比例的差异, 只保留结构、明暗等基本信息.

        

第二步 转为灰度图片

         将缩小后的图片, 转为64级灰度图片.

        

第三步 计算灰度平均值

         计算图片中所有像素的灰度平均值

第四步 比较像素的灰度

        将每个像素的灰度与平均值进行比较, 如果大于或等于平均值记为1, 小于平均值记为0.

第五步 计算哈希值

         将上一步的比较结果, 组合在一起, 就构成了一个64位的二进制整数, 这就是这张图片的指纹.

第六步 对比图片指纹

        得到图片的指纹后, 就可以对比不同的图片的指纹, 计算出64位中有多少位是不一样的. 如果不相同的数据位数不超过5, 就说明两张图片很相似, 如果大于10, 说明它们是两张不同的图片.


算法实现OpenCV版

本人是在做2
#include "stdafx.h"
#include "ImageHash.h"

Mat calHashCode(Mat image)  
{  
	resize(image, image, Size(8, 8));  
	Scalar imageMean = mean(image);  
	return (image > imageMean[0]);  
}  

// calculate the pHash code of image  
Mat calPHashCode(Mat image)  
{  
	Mat floatImage, imageDct;  
	resize(image, image, Size(32, 32));   
	image.convertTo(floatImage, CV_32FC1);  
	dct(floatImage, imageDct);  
	Rect roi(0, 0, 8, 8);  
	Scalar imageMean = mean(imageDct(roi));  
	return (imageDct(roi) > imageMean[0]);  
}  

// get hamming distance of two hash code  
int calHammingDistance(Mat modelHashCode, Mat testHashCode)  
{  
	return countNonZero(modelHashCode != testHashCode);  
}  

	Mat leftHash = calPHashCode(leftImage);
	Mat rightHash = calPHashCode(rightImage);
	int lrResult = calHammingDistance(leftHash,rightHash);
	Mat topHash = calPHashCode(topImage);
	Mat bottomHash = calPHashCode(bottomImage);
	int tdResult = calHammingDistance(topHash,bottomHash);
	cout <<"左右图汉明距离是:"<
 
   

总结

总体而言,感知哈希算法运算速度有很大提升,但是精确度还不够准确,还需要优化。
下面是用3D左右图进行计算的结果:
第一组3D左右图,应该是相似度很高的图片:
D:\work\picture\td\1\1.jpg
左右图汉明距离是:2
上下图汉明距离是:19
D:\work\picture\td\1\2.jpg
左右图汉明距离是:3
上下图汉明距离是:8
D:\work\picture\td\1\3.jpg
左右图汉明距离是:4
上下图汉明距离是:16
D:\work\picture\td\1\4.jpg
左右图汉明距离是:9
上下图汉明距离是:12
D:\work\picture\td\1\5.jpg
左右图汉明距离是:2
上下图汉明距离是:11
D:\work\picture\td\1\6.jpg
左右图汉明距离是:2
上下图汉明距离是:12
D:\work\picture\td\1\7.jpg
左右图汉明距离是:4
上下图汉明距离是:27
D:\work\picture\td\1\8.jpg
左右图汉明距离是:3
上下图汉明距离是:10
D:\work\picture\td\1\9.jpg
左右图汉明距离是:7
上下图汉明距离是:27
D:\work\picture\td\1\10.jpg
左右图汉明距离是:4
上下图汉明距离是:20
D:\work\picture\td\1\11.jpg
左右图汉明距离是:1
上下图汉明距离是:6
D:\work\picture\td\1\12.jpg
左右图汉明距离是:6
上下图汉明距离是:28
D:\work\picture\td\1\13.jpg
左右图汉明距离是:3
上下图汉明距离是:12

一般的2D图片:
D:\work\picture\td\normal\1.jpg
左右图汉明距离是:19
上下图汉明距离是:24
D:\work\picture\td\normal\2.jpg
左右图汉明距离是:19
上下图汉明距离是:24
D:\work\picture\td\normal\3.jpg
左右图汉明距离是:24
上下图汉明距离是:34
D:\work\picture\td\normal\4.jpg
左右图汉明距离是:10
上下图汉明距离是:13
D:\work\picture\td\normal\5.jpg
左右图汉明距离是:15
上下图汉明距离是:22
D:\work\picture\td\normal\6.jpg
左右图汉明距离是:16
上下图汉明距离是:19
D:\work\picture\td\normal\7.jpg
左右图汉明距离是:24
上下图汉明距离是:24
D:\work\picture\td\normal\8.jpg
左右图汉明距离是:23
上下图汉明距离是:29
D:\work\picture\td\normal\9.jpg
左右图汉明距离是:11
上下图汉明距离是:17
D:\work\picture\td\normal\10.jpg
左右图汉明距离是:13
上下图汉明距离是:19
D:\work\picture\td\normal\11.jpg
左右图汉明距离是:20
上下图汉明距离是:36
D:\work\picture\td\normal\12.jpg
左右图汉明距离是:2
上下图汉明距离是:14
D:\work\picture\td\normal\13.jpg
左右图汉明距离是:12
上下图汉明距离是:14
D:\work\picture\td\normal\14.jpg
左右图汉明距离是:32
上下图汉明距离是:34
D:\work\picture\td\normal\15.jpg
左右图汉明距离是:27
上下图汉明距离是:26
D:\work\picture\td\normal\16.jpg
左右图汉明距离是:1
上下图汉明距离是:10
D:\work\picture\td\normal\17.jpg
左右图汉明距离是:12
上下图汉明距离是:25
D:\work\picture\td\normal\18.jpg
左右图汉明距离是:32
上下图汉明距离是:24
D:\work\picture\td\normal\19.jpg
左右图汉明距离是:30
上下图汉明距离是:26
D:\work\picture\td\normal\20.jpg
左右图汉明距离是:7
上下图汉明距离是:16
D:\work\picture\td\normal\21.jpg
左右图汉明距离是:35
上下图汉明距离是:28
D:\work\picture\td\normal\22.jpg
左右图汉明距离是:17
上下图汉明距离是:24
D:\work\picture\td\normal\23.jpg
左右图汉明距离是:21
上下图汉明距离是:23
D:\work\picture\td\normal\24.jpg
左右图汉明距离是:26
上下图汉明距离是:20
D:\work\picture\td\normal\25.jpg
左右图汉明距离是:12
上下图汉明距离是:19
D:\work\picture\td\normal\26.jpg
左右图汉明距离是:6
上下图汉明距离是:9
D:\work\picture\td\normal\27.jpg
左右图汉明距离是:2
上下图汉明距离是:3
D:\work\picture\td\normal\28.jpg
左右图汉明距离是:27
上下图汉明距离是:29
D:\work\picture\td\normal\29.jpg
左右图汉明距离是:10
上下图汉明距离是:12
D:\work\picture\td\normal\30.jpg
左右图汉明距离是:6
上下图汉明距离是:2
D:\work\picture\td\normal\31.jpg
左右图汉明距离是:25
上下图汉明距离是:34
D:\work\picture\td\normal\32.jpg
左右图汉明距离是:11
上下图汉明距离是:12
D:\work\picture\td\normal\33.jpg
左右图汉明距离是:20
上下图汉明距离是:26
D:\work\picture\td\normal\34.jpg
左右图汉明距离是:10
上下图汉明距离是:15
D:\work\picture\td\normal\35.jpg
左右图汉明距离是:14
上下图汉明距离是:24
D:\work\picture\td\normal\36.jpg
左右图汉明距离是:6
上下图汉明距离是:7
D:\work\picture\td\normal\37.jpg
左右图汉明距离是:26
上下图汉明距离是:24
D:\work\picture\td\normal\38.jpg
左右图汉明距离是:31
上下图汉明距离是:30
D:\work\picture\td\normal\39.jpg
左右图汉明距离是:2
上下图汉明距离是:10
D:\work\picture\td\normal\40.jpg
左右图汉明距离是:40
上下图汉明距离是:32
D:\work\picture\td\normal\41.jpg
左右图汉明距离是:5
上下图汉明距离是:5
D:\work\picture\td\normal\42.jpg
左右图汉明距离是:28
上下图汉明距离是:31
D:\work\picture\td\normal\43.jpg
左右图汉明距离是:10
上下图汉明距离是:13
D:\work\picture\td\normal\44.jpg
左右图汉明距离是:11
上下图汉明距离是:13
D:\work\picture\td\normal\45.jpg
左右图汉明距离是:22
上下图汉明距离是:27
D:\work\picture\td\normal\46.jpg
左右图汉明距离是:16
上下图汉明距离是:27
D:\work\picture\td\normal\47.jpg
左右图汉明距离是:28
上下图汉明距离是:28
D:\work\picture\td\normal\48.jpg
左右图汉明距离是:12
上下图汉明距离是:25
D:\work\picture\td\normal\49.jpg
左右图汉明距离是:12
上下图汉明距离是:17

你可能感兴趣的:(OpenCV)