圖像相似度

来源:互联网 发布:网络包工头如何接业务 编辑:程序博客网 时间:2024/06/11 18:31

圖像相似度

       圖像相似度是指圖像的相似程序。本文給出了實現步驟與代碼。

      

一、大致實現步驟如下:

  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開源圖像處理庫。

原创粉丝点击