比较两幅图像的相似度

现在以图搜图的功能比较火热,很好奇其原理。

简单的搜索学习得知,实现相似图片搜索的关键技术是“感知哈希算法”,作用是对每一张图片按照某种规律生成一个对应的指纹字符串。比较不同图片之间的指纹字符串,结果越接近,图片越相似。

现将问题简化为研究两幅图像的相似度,算法可能其他博客都有介绍了,现给出实现代码(简易版)。简易版指纹字符串的算法思想如下:

1.输入图像

2.灰度化

3.将图像大小归一化到8*8尺寸

4.简化灰度以减少计算量,例如所有的灰度除以5

5.计算平均灰度值avg

6.比较8*8=64个像素与平均灰度值avg的大小,若大则记为1,小则记为0,按一定顺序排列成64位2进制的指纹编码。

7.比较两幅图像的指纹编码,计算相似度。

测试样例:(依次为example1,example2,example3,example4)


测试结果

example1-example2 : 64.0625%,not similar.

example1-example3 : 71.875%,a little similar.

example1-example4 : 95.3125%,extremely similar.


代码如下,只有一个文件哦(main.cpp):

#include

using namespace std;
string ImageHashValue(IplImage* src);  //计算图片的指纹信息
double ImageSimilarity(string &str1,string &str2);  //根据指纹信息计算两幅图像的相似度

int main()
{
IplImage* image1 = cvLoadImage("example1.jpg",1);
IplImage* image2 = cvLoadImage("example3.jpg",1);
cvShowImage("image1",image1);
cvShowImage("image2",image2);
string imgPrint1 = ImageHashValue(image1);
string imgPrint2 = ImageHashValue(image2);
double similarity = ImageSimilarity(imgPrint1,imgPrint2);
cout<<"The similarity of two images is "<if(similarity>=0.9)
cout<<"The two images are extremely similar."<else if(similarity>=0.8&&similarity<0.9)
cout<<"The two images are pretty similar."<else if(similarity>=0.7&&similarity<0.8)
cout<<"The two images are a little similar."<else if(similarity<0.7)
cout<<"The two image are not similar."<cout<cvWaitKey(0);
}

//计算图片的指纹信息
string ImageHashValue(IplImage* src)
{
string resStr(64,'\0');
IplImage* image =  cvCreateImage(cvGetSize(src),src->depth,1);
//step one : 灰度化
if(src->nChannels == 3)  cvCvtColor(src,image,CV_BGR2GRAY);
else  cvCopy(src,image);
//step two : 缩小尺寸 8*8
IplImage* temp = cvCreateImage(cvSize(8,8),image->depth,1);
cvResize(image,temp);
//step three : 简化色彩
uchar* pData;
for(int i=0; iheight; i++)
{
pData =(uchar* )(temp->imageData+i*temp->widthStep);
for(int j=0; jwidth;j++)
pData[j]= pData[j]/4;
}
//step four : 计算平均灰度值
int average = cvAvg(temp).val[0];
//step five : 计算哈希值
int index = 0;
for(int i=0; iheight; i++)
{
pData =(uchar* )(temp->imageData+i*temp->widthStep);
for(int j=0; jwidth;j++)
{
if(pData[j]>=average)
resStr[index++]='1';
else 
resStr[index++]='0';
}
}
return resStr;
}

//根据指纹信息计算两幅图像的相似度
double ImageSimilarity(string &str1,string &str2)
{
double similarity = 1.0;
for(int i=0;i<64;i++)
{
char c1 = str1[i];
char c2 = str2[i];
if(c1!=c2)
similarity = similarity -1.0/64;
}
return similarity;
}


你可能感兴趣的:(图像处理,opencv)