本文共 1878 字,大约阅读时间需要 6 分钟。
注:原文地址:
感知哈希算法感知哈希算法(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#include #include 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_ (src); } else { img = Mat_ (src); } //3.计算DCT dct(img, dst); //4.缩小DCT for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { Hash[k++] = dst.at (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.转载地址:http://tbbqb.baihongyu.com/