圖片相似度計算
阿新 • • 發佈:2019-02-02
今天自己寫了一個簡單的計算圖相似度的演算法,借鑑了雜湊演算法思想進行編寫,在此分享給大家!
總體思路 :
(借鑑了相似影象搜素的關鍵技術——雜湊演算法)將每一張圖片人為轉換具有0或1規律表達的影象,即將影象按照某個閾值生成對應的指紋字串。我們最終是通過比較不同圖片轉後對應位置的指紋字串,其結果越是趨向於1越相似。
主要實現的步驟如下:
Step 1. 輸入影象
Step 2. 進行灰度化 (如果是需要更高精度的影象相似度計算,可以考慮利用原始圖)
Step 3. 將輸入的影象進行歸一化到指定尺寸 例如9*9
Step 4. 等比降低灰度值 (grayValue/N 其中N是正整數,也可以省略)
Step 5. 計算影象平均灰度值average
Step 6. 生成指紋圖,將歸一化的影象每個位置Img(i,j)與平均灰度值average進行比較,若 Img(I,j)> average,則Img(i,j)=1,否則Img(I,j)=0;
Step 7. 按照一定排列順序進行兩幅影象比較,獲得相似度similarity
我設定初始值similarity = 1。
接下來直接上程式碼:
//第一個函式:計算圖片的指紋資訊 string CalImgHashValue(IplImage* src) { int N = 5; //簡化常數,人為設定 int graySum; string resStr(81,'\0'); uchar* pData; IplImage* image = cvCreateImage(cvGetSize(src),src->depth,1); //step2 : 灰度化 if(src->nChannels == 3) cvCvtColor(src,image,CV_BGR2GRAY); else cvCopy(src,image); //step 3 : 縮小尺寸 9*9 IplImage* temp = cvCreateImage(cvSize(9,9),image->depth,1); cvResize(image,temp); //step 4 : 簡化計算量 for(int i=0; i<temp->height; i++) { pData =(uchar* )(temp->imageData+i*temp->widthStep); for(int j=0; j<temp->width;j++) pData[j]= pData[j]/N; } //step 5 : 計算平均灰度值 int count = 0; for (int row = 0; row< src->iHeight; row++) { for (int col = 0; col<= src->iWidth; col++) { graySum = graySum + (uchar)ImgGray->imageData[row*src->widthStep + col]; count++; } } int average = graySum/count; //step 6 : 計算雜湊值 int index = 0; for(int i=0; i<temp->height; i++) { pData =(uchar* )(temp->imageData+i*temp->widthStep); for(int j=0; j<temp->width;j++) { if(pData[j]>=average) resStr[index++]='1'; else resStr[index++]='0'; } } return resStr; }
//第二個函式:計算兩幅影象的相似度
void GetImgSimilarity(string &str1,string &str2,double* similarity)
{
*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;
}
}
//宣告 string CalImgHashValue(IplImage* src); //計算圖片的指紋資訊 void GetImgSimilarity(string &str1,string &str2); //根據指紋資訊計算兩幅影象的相似度
//測試程式
#include <opencv2/opencv.hpp>
using namespace std;
int main()
{
IplImage* img1 = cvLoadImage("hanshanbuleng1.jpg",1);
IplImage* img2 = cvLoadImage("hanshanbuleng2.jpg",1);
cvShowImage("img1 ",img1 );
cvShowImage("img2 ",img2 );
string imgPrint1 = ImageHashValue(image1);
string imgPrint2 = ImageHashValue(image2);
double similarity = 0;
ImageSimilarity(imgPrint1,imgPrint2,&similarity);
cout<<"The similarity of two img is "<<similarity*100<<"%"<<endl;
if(similarity>=0.9)
cout<<"The two img are extremely similar."<<endl;
else if(similarity>=0.8&&similarity<0.9)
cout<<"The two imag are pretty similar."<<endl;
else if(similarity>=0.7&&similarity<0.8)
cout<<"The two imag are a little similar."<<endl;
else if(similarity<0.7)
cout<<"The two img are not similar."<<endl;
cout<<endl;
cvWaitKey(0);
}