注:原文地址:感知哈希算法
感知哈希算法
感知哈希算法(PHA)是哈希算法的一类,主要用来做相似图片的搜索工作。
算法原理
为图片生成一个指纹(字符串格式), 两张图片的指纹越相似, 说明两张图片就越相似。
算法步骤
1.缩小尺寸:将图片缩小到8*8的尺寸,总共64个像素。2.简化色彩:将缩小后的图片,转为64级灰度,也就是说,所有的像素点共只有64种颜色。3.计算DCT(离散余弦变换):DCT是把图片分解频率聚集和梯状形,虽然JPEG使用8*8的DCT变换,在这里使用32*32的DCT变换。4.缩小DCT:虽然DCT的结果是32*32大小的矩阵,但我们只要保留左上角的8*8的矩阵,这部分呈现了图片中的最低频率。5.计算平均值:计算所有64个值得平均值。6.进一步减少DCT:根据8*8的DCT矩阵,设置0或1的64位hash值,大于DCT均值的设为“1”小于DCT均值的设为“0”。7.计算哈希值:将64bit设置成64位的长整型,组合的次序并不重要,只要保证所有图片都采用同样次序就行了。将32*32的DCT转换成32*32的图像。
算法的优点
无论你改变图片的高宽、亮度甚至颜色,都不会改变哈希值。
参考代码
#include "opencv2/highgui/highgui.hpp"#include "opencv2/imgproc/imgproc.hpp"#include <iostream>#include <stdio.h>#include <fstream>using namespace std;using namespace cv;string PHA(Mat &src){Mat img, dst;string ans(64, 0);double Hash[64];double mid = 0.0;double eps = 1e-9;int k = 0;//1.缩小尺寸resize(src, src, Size(8, 8));//2.简化色彩if (src.channels() == 3){cvtColor(src, src, CV_BGR2GRAY);img = Mat_<double>(src);}else{img = Mat_<double>(src);}//3.计算DCTdct(img, dst);//4.缩小DCT for (int i = 0; i < 8; i++){for (int j = 0; j < 8; j++){Hash[k++] = dst.at<double>(i, j);mid += Hash[k - 1];}}//5.计算平均值mid = mid / 64;//6.计算哈希值for (int i = 0; i < 64; i++){if (Hash[i] - mid>eps) ans[i] = '1';else ans[i] = '0';}return ans;}//计算汉明距离int dis(string s1, string s2){int ans = 0;for (int i = 0; i < 64; i++)if (s1[i] != s2[i]) ans++;return ans;}int main(){ofstream out;out.open("test.txt");Mat src;string s1, s2;int k;Mat img;s1 = PHA(src);out << "person.jpg" << " " << s1 << endl;char path[] = { "person0.jpg" };for (int i = 0; i < 9; i++){path[6] += 1;img = imread(path);s2 = PHA(img);k = dis(s1, s2);out << path << " " << s2 << " " << k << endl;}out.close();return 0;}
参考资料
1.感知哈希算法–百度百科
2.Neal Krawetz的博客Looks like it