图像相似度
图像相似度是指图像的相似程序。本文给出了实现步骤与代码。
一、大致实现步骤如下:
1, 将图像转换成相同大小,以有利于计算出相像的特征
2, 计算转化后的灰度,二值
3, 利用相似度公式,得到图像相似度的定量度量
4, 统计相似度结果数据
相似度公式:
二、部分代码
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
//计算相减后的绝对值
float GetAbs(float f, float s)
{
float abs = fabs((float)f - (float)s);
float result = MAX(f, s);
if (result == 0)
result = 1;
return abs / result;
}
//相似度
float GetResult(float firstNum[], float scondNum[],int nSize)
{
if (nSize==0)
{
return 0;
}
else
{
float result = 0;
int j = nSize;
for (int i = 0; i < j; i++)
{
result += 1 - GetAbs(firstNum[i], scondNum[i]);
}
return result/j;
}
}
//函数功能:自动普通二值化
//参数说明:iSrc,表示原图像
//iDst,表示目标图像
//nLevel,表示阈值 [OUT]
//iIterationTimes,表示迭代次数
void AutoThreshold(CxImage *iSrc, int &nLevel,CxImage *iDst,int iIterationTimes)
{
void* pDib = NULL;
pDib = iSrc->GetDIB();
if (!pDib)
return ;
if (iSrc->GetBpp()==1)
return ;
long iWidth = 0,iHeight =0,x = 0,y = 0,i = 0,t = 0;
unsigned char iThreshold, iNewThreshold, iMaxGrayValue = 255, iMinGrayValue = 0, iMean1GrayValue, iMean2GrayValue;
double w0,w1,iMeanGrayValue;
double G=0, tempG=0;
long lP1, lS1, lP2, lS2;
iWidth = iSrc->GetWidth();
iHeight = iSrc->GetHeight();
//保存原始图像
CxImage tmpSrc(iWidth,iHeight,iSrc->GetBpp());
tmpSrc.Copy(*iSrc);
///////////////////////////////////////////////
iSrc->GrayScale();
//灰度分布统计
long *pGray = new long[256];
memset(pGray,0,sizeof(long)*256);
for (y=0;y<iHeight;y++)
{
for (x=0;x<iWidth;x++)
{
i = iSrc->GetPixelIndex(x,y);
pGray[i]++;
//修改最大灰度值和最小灰度值
if(iMinGrayValue > i)
{
iMinGrayValue = i;
}
if(iMaxGrayValue < i)
{
iMaxGrayValue = i;
}
}
}
// 遍历t, 选取最佳阈值
for(t = iMinGrayValue; t < iMaxGrayValue ; t++)
{
iNewThreshold = t;
lP1 = 0;
lS1 = 0;
lP2 = 0;
lS2 = 0;
// 求前景,背景两个区域的平均灰度值, 点数所占比例
for(i = iMinGrayValue; i <= iNewThreshold; i++)
{
lP1 += pGray[i] * i;
lS1 += pGray[i];
}
if(lS1==0)
continue;
iMean1GrayValue = (unsigned char) (lP1/lS1);
w0 = (double) (lS1) / (iWidth * iHeight);
for(i = iNewThreshold + 1; i <= iMaxGrayValue; i++)
{
lP2 += pGray[i] * i;
lS2 += pGray[i];
}
if(lS2==0)
continue;
iMean2GrayValue = (unsigned char) (lP2/lS2);
w1 = 1 - w0;
iMeanGrayValue=w0*iMean1GrayValue +w1*iMean2GrayValue ;
G = w0 *(iMean1GrayValue-iMeanGrayValue)*(iMean1GrayValue-iMeanGrayValue)+w1*
(iMean2GrayValue-iMeanGrayValue)*(iMean2GrayValue-iMeanGrayValue);
if(G > tempG)
{
tempG = G;
iThreshold = iNewThreshold;
}
}
nLevel = iThreshold;
if(pGray)
{
delete []pGray;
pGray = NULL;
}
////////////////////////////////////////////////
CxImage tmp(iWidth,iHeight,1);
if (!tmp.IsValid())
{
return ;
}
for (y=0;y<iHeight;y++)
{
for (x=0;x<iWidth;x++)
{
i = iSrc->GetPixelIndex(x,y);
if (i>nLevel)
tmp.SetPixelIndex(x,y,0);
else
tmp.SetPixelIndex(x,y,1);
}
}
tmp.SetPaletteColor(0,255,255,255);
tmp.SetPaletteColor(1,0,0,0);
iDst->Transfer(tmp);
//
iSrc->Copy(tmpSrc);
}
//图像的相似比率
float ImageSameRatio(CxImage *iSrc,CxImage *iDst)
{
float fRadio = 1.0f,fRadio1 = 1.0f,fRadio2 = 1.0f;
long iWidth = 0,iHeight =0,x = 0,y = 0,i = 0,t = 0,j = 0;
long iWidth2 = 0,iHeight2 = 0;;
iWidth = iSrc->GetWidth();
iHeight = iSrc->GetHeight();
//统一成一样的大小
iWidth2 = iDst->GetWidth();
iHeight2 = iDst->GetHeight();
if(iWidth==iWidth2 && iHeight==iHeight2)
{
}
else
{
int nImageType = iSrc->GetType();
CxImage * newIma = new CxImage(nImageType);
iDst->Resample(iWidth,iHeight,1,newIma);
iDst->Copy(*newIma);
}
//////////////////////////////////////////////
//二值化处理
int nLevel = 128;
CxImage *pBinImage1 = NULL,*pBinImage2 = NULL;
pBinImage1 = new CxImage(iWidth,iHeight,1);
pBinImage2 = new CxImage(iWidth,iHeight,1);
AutoThreshold(iSrc,nLevel,pBinImage1,200);
AutoThreshold(iDst,nLevel,pBinImage2,200);
//提取iSizeX*iSizeY点比率特征
int iSizeX = 3,iSizeY = 3;
int mm=0,nn=0,num = 0;
mm = (iWidth+iSizeX-1)/iSizeX;
nn = (iHeight+iSizeY-1)/iSizeY;
float *pDotRadio1 = new float[mm*nn+1];
memset(pDotRadio1,0,sizeof(float)*(mm*nn+1));
float *pDotRadio2 = new float[mm*nn+1];
memset(pDotRadio2,0,sizeof(float)*(mm*nn+1));
for(j=0;j<nn;j++)
{
for(i=0;i<mm;i++)
{
fRadio = 0.0f;
num = 0;
for(y=j*iSizeY;y<j*iSizeY+iSizeY;y++)
{
for(x=i*iSizeX;x<i*iSizeX+iSizeX;x++)
{
if(x>=iWidth || y>=iHeight)
continue;
fRadio += pBinImage1->GetPixelIndex(x,y);
num = num + 1;
}
}
if(num!=0)
{
pDotRadio1[j*mm+i] = fRadio/num;
}
}
}
for(j=0;j<nn;j++)
{
for(i=0;i<mm;i++)
{
fRadio = 0.0f;
num = 0;
for(y=j*iSizeY;y<j*iSizeY+iSizeY;y++)
{
for(x=i*iSizeX;x<i*iSizeX+iSizeX;x++)
{
if(x>=iWidth || y>=iHeight)
continue;
fRadio += pBinImage2->GetPixelIndex(x,y);
num = num + 1;
}
}
if(num!=0)
{
pDotRadio2[j*mm+i] = fRadio/num;
}
}
}
fRadio = GetResult(pDotRadio1,pDotRadio2,nn*mm);
if(pDotRadio1)
{
delete []pDotRadio1;
pDotRadio1 = NULL;
}
if(pDotRadio2)
{
delete []pDotRadio2;
pDotRadio2 = NULL;
}
// pBinImage1->Save("c://1.tif",CXIMAGE_FORMAT_TIF);
// pBinImage2->Save("c://2.tif",CXIMAGE_FORMAT_TIF);
if(pBinImage1)
{
delete pBinImage1;
}
if(pBinImage2)
{
delete pBinImage2;
}
return fRadio;
}
注:使用了Cximage开源图像处理库。