相似图片搜索原理二(phash—c++实现)
前段时间介绍过相似图片搜索原理一(ahash) http://blog.csdn.net/lu597203933/article/details/45101859,它是基于内容检索最简单的一种;这里介绍它的增强版本感知哈希算法(perceptual hash, phash)。它主要也是用缩略图搜原图并能达到较好点的效果.
理论部分:
理论部分主要包括以下几个步骤:
<1> 图像缩放—将图像缩放到32*32大小
<2>灰度化—对32*32大小的图像进行灰度化
<3>离散余弦变换(DCT)—对32*32大小图像进行DCT
<4>计算均值—用32*32大小图片前面8*8大小图片处理并计算这64个像素的均值
<4>得到8*8图像的phash—8*8的像素值中大于均值的则用1表示,小于的用0表示,这样就得到一个64位二进制码作为该图像的phash值。
<5>计算两幅图像ahash值的汉明距离,距离越小,表明两幅图像越相似;距离越大,表明两幅图像距离越大。
这样做能够避免伽马校正或者颜色直方图调整带来的影响。
更详细的理论可以参看:
1:http://www.hackerfactor.com/blog/index.php?/archives/432-Looks-Like-It.html
2:http://blog.csdn.net/luoweifu/article/details/8220992包括java代码实现
下面我给出自己的c++代码实现:
<1>图像灰度化与缩放
[cpp] view plaincopyprint?

- Mat img = imread("E:\algorithmZack\ImageSearch\image\person.jpg", 1);
- if(!img.data){
- cout << "the image is not exist" << endl;
- return 0;
- }
- int size = 32; // 图片缩放后大小
- resize(img, img, Size(size,size)); // 缩放到32*32
- cvtColor(img, img, COLOR_BGR2GRAY); // 灰度化
<2>DCT变换
[cpp] view plaincopyprint?

- /*
- 功能:获取DCT系数
- n:矩阵大小
- quotient: 系数
- quotientT: 系数转置
- */
- void coefficient(const int &n, double **quotient, double **quotientT){
- double sqr = 1.0/sqrt(n+0.0);
- for(int i = 0; i < n; i++){
- quotient[0][i] = sqr;
- quotientT[i][0] = sqr;
- }
- for(int i = 1; i < n; i++){
- for(int j = 0; j < n; j++){
- quotient[i][j] = sqrt(2.0/n)*cos(i*(j+0.5)*PI/n); // 由公式得到
- quotientT[j][i] = quotient[i][j];
- }
- }
- }
- /*
- 功能:两矩阵相乘
- A和B:源输入矩阵
- result:输出矩阵
- */
- void matrixMultiply(double **A, double **B, int n, double **result){
- double t = 0;
- for(int i = 0; i < n; i++){
- for(int j = 0; j < n; j++){
- t = 0;
- for(int k = 0; k < n; k++)
- t += A[i][k]*B[k][j];
- result[i][j] = t;
- }
- }
- }
- void DCT(Mat_<uchar> image, const int &n, double **iMatrix){
- for(int i = 0; i < n; i++){
- for(int j = 0; j < n; j++){
- iMatrix[i][j] = (double)image(i,j);
- }
- }
- // 为系数分配空间
- double **quotient = new double*[n];
- double **quotientT = new double*[n];
- double **tmp = new double*[n];
- for(int i = 0; i < n; i++){
- quotient[i] = new double[n];
- quotientT[i] = new double[n];
- tmp[i] = new double[n];
- }
- // 计算系数矩阵
- coefficient(n, quotient, quotientT);
- matrixMultiply(quotient, iMatrix, n, tmp); // 由公式成绩结果
- matrixMultiply(tmp, quotientT, n, iMatrix);
- for(int i = 0; i < n; i++){
- delete []tmp[i];
- delete []quotient[i];
- delete []quotientT[i];
- }
- delete []tmp;
- delete []quotient;
- delete []quotientT;
- }
<3>计算均值
[cpp] view plaincopyprint?

- // 计算8*8图像的平均灰度
- float calcAverage(double **iMatrix, const int &size){
- float sum = 0;
- for(int i = 0 ; i < size; i++){
- for(int j = 0; j < size; j++){
- sum += iMatrix[i][j];
- }
- }
- return sum/(size*size);
- }
<4>计算汉明距离
[cpp] view plaincopyprint?

- /* 计算hash值
- image:8*8的灰度图像
- size: 图像大小 8*8
- phash:存放64位hash值
- averagePix: 灰度值的平均值
- */
- void fingerPrint(double **iMatrix, const int &size, bitset<hashLength> &phash, const float &averagePix){
- for(int i = 0; i < size; i++){
- int pos = i * size;
- for(int j = 0; j < size; j++){
- phash[pos+j] = iMatrix[i][j] >= averagePix ? 1:0;
- }
- }
- }
完整源代码:
[cpp] view plaincopyprint?

- #include <iostream>
- #include <bitset>
- #include <string>
- #include <iomanip>
- #include <cmath>
- #include <opencv2highguihighgui.hpp>
- #include <opencv2imgprocimgproc.hpp>
- #include <opencv2corecore.hpp>
- using namespace std;
- using namespace cv;
- #define PI 3.1415926
- #define hashLength 64
- /*
- 功能:获取DCT系数
- n:矩阵大小
- quotient: 系数
- quotientT: 系数转置
- */
- void coefficient(const int &n, double **quotient, double **quotientT){
- double sqr = 1.0/sqrt(n+0.0);
- for(int i = 0; i < n; i++){
- quotient[0][i] = sqr;
- quotientT[i][0] = sqr;
- }
- for(int i = 1; i < n; i++){
- for(int j = 0; j < n; j++){
- quotient[i][j] = sqrt(2.0/n)*cos(i*(j+0.5)*PI/n); // 由公式得到
- quotientT[j][i] = quotient[i][j];
- }
- }
- }
- /*
- 功能:两矩阵相乘
- A和B:源输入矩阵
- result:输出矩阵
- */
- void matrixMultiply(double **A, double **B, int n, double **result){
- double t = 0;
- for(int i = 0; i < n; i++){
- for(int j = 0; j < n; j++){
- t = 0;
- for(int k = 0; k < n; k++)
- t += A[i][k]*B[k][j];
- result[i][j] = t;
- }
- }
- }
- void DCT(Mat_<uchar> image, const int &n, double **iMatrix){
- for(int i = 0; i < n; i++){
- for(int j = 0; j < n; j++){
- iMatrix[i][j] = (double)image(i,j);
- }
- }
- &n
声明:该文观点仅代表作者本人,入门客AI创业平台信息发布平台仅提供信息存储空间服务,如有疑问请联系rumenke@qq.com。
- 上一篇:没有了
- 下一篇:没有了