www.pudn.com > CRetrieveMethod.rar > CRetrieveMethod.cpp
// CRetrieveMethod.cpp: implementation of the CCRetrieveMethod class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "VqRetrieve.h"
#include "CRetrieveMethod.h"
#include "math.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CRetrieveMethod::CRetrieveMethod()
{
}
CRetrieveMethod::~CRetrieveMethod()
{
}
//升序
void CRetrieveMethod::ListByAverage(CHARACTERVQ *pCharacterVq, long int iRetrieveBmpNumber)
{
long int i,j;
long int index; //索引
CHARACTERVQ varible;
for(i=0;im_dAverage>(pCharacterVq+j)->m_dAverage)
{
index=j;
} //end of for j,get the index
if (index==i) //本身最小
{
continue;//next i
}
varible=*(pCharacterVq+i);
*(pCharacterVq+i)=*(pCharacterVq+index);
*(pCharacterVq+index)=varible;
}
}
//计算高:dataheigth,datawidth首地址为*pdata的特征矢量存在结构体中:charactervq
//characterfirst:为特征矢量结构体的存入的第一个的编号,characternumber:该算法提取参数的个数
///本算法中,characternumber必须等于7
bool CRetrieveMethod::CharacterVqDistillMethod_1_7(unsigned char *pdata, int datawidth, int dataheigth, CHARACTERVQ *charactervq, int characterfirst, int characternumber)
{
if (characternumber!=7)
{
MessageBox(NULL,"CharacterDistill Number error","error!",MB_OK);
return false;
}
////add your word here
/////注意:计算一个特征量,iCharacterNumbercheck++;
//////////////////////////////////////////////////////////////////////////
////////参数1:最佳域值
//////算法:给定初始值,将像素分为两部分,计算个自的中心,中心的均值作为新的域值,与
//////////前一次的最佳域值比较,若相同则结束
/////////并用最大值限制迭代次数
////说明:参数1,2是颜色中的不变量,是在最佳域值方法中提取出来的
int i,j;
double regiondata1=128,regiondata2=128; ///最佳域值初值
int Max=1000; ///迭代最多的次数
int regionnumberleft=0,regionnumberright=0; ////两个区域的计数值
long double regiontotallleft=0,regiontotalright=0; ////两个区域的总和
long int count; //计数器
for(count=0;countm_dFileOriginalCharacter[characterfirst+0]=regiondata2/255.0; ///归一化
///参数2
charactervq->m_dFileOriginalCharacter[characterfirst+1]=(double)regionnumberleft/(regionnumberleft+regionnumberright);
////end of 颜色
///颜色参数的个数
//////说明:参数3,4,5是纹理中的不变量,他们是在共生矩阵中提取的
////参数3:
///统计共生矩阵
double (*texturematrix)[256]=new double[256][256]; ///共生矩阵x
double (*texturematriy)[256]=new double[256][256]; ///共生矩阵x
for(i=0; i<256; i++)
for(j=0; j<256; j++)
{
texturematrix[i][j]=0;
texturematriy[i][j]=0;
}
for(i=1; im_dFileOriginalCharacter[characterfirst+2]=(Con1+Con2)/2/255.0/255.0; //提取反差变量
charactervq->m_dFileOriginalCharacter[characterfirst+3]=(Asm1+Asm2)/2; ///提取能量变量
charactervq->m_dFileOriginalCharacter[characterfirst+4]=-(Ent1+Ent2)/2; ///提取熵变量
delete[] texturematrix;
delete[] texturematriy;
//////参数3,4,5提取结束
////end of 纹理
///纹理参数的个数
////参数6,7提取:形状不变量
///////二阶矩和一阶矩
/////特点:矩是对图像的一种的一种统计形式,他的计算要用到图像或区域中的所有相关的像素点,
//// 对一个数字图像函数F(X),如果他分段连续且只在XY平面上的有限个点不为零,则可以证明他的
////////各阶矩存在。
//范例图像的各阶矩的声明
double M_00=0.0,M_01=0.0,M_10=0.0,M_11=0.0,M_20=0.0,M_02=0.0;//P+Q阶矩
double U_00=0.0,U_11=0.0,U_20=0.0,U_02=0.0;//P+Q阶中心矩
double m_00,n_00;//重心坐标
double u_00,u_11,u_20,u_02;//归一化的P+Q阶中心矩
///计算范例图的各阶矩
for(int l=0; lm_dFileOriginalCharacter[characterfirst+5]=(pow((u_20-u_02),2.0)+4*u_11*u_11); ////保存
///一阶不变矩保存
charactervq->m_dFileOriginalCharacter[characterfirst+6]=(u_20+u_02);
return true;
}
//矢量检索,方法1
///直接的检索矢量,对图像的矢量进行检索
///pCharacterVq图像库矢量结构体指针,iCurrentCharacter:检索矢量的数量,
//iRetrieveBmpNumber图像库图像数目, KeybmpCharactervq :关键图像的结构
//pOutCharactervq:输出结构体的头指针,maxOutNumber输出图像的最多数目,*pOutBmpNumber:输出图像的数目的地址
//pDistance检索图像和关键图像的距离输出的头指针,RetrieveTime检索时间
bool CRetrieveMethod::RetrieveKeyVqMethod_1Nomal(CHARACTERVQ *pCharacterVq, int iCurrentCharacter, long iRetrieveBmpNumber, CHARACTERVQ KeybmpCharactervq, CHARACTERVQ *pOutCharactervq, unsigned char maxOutNumber, unsigned char *pOutBmpNumber, double *pOutDistance, CString *RetrieveTime)
{
int vector=iCurrentCharacter; //特征量未计算完最大可以是100
double *pDistance=new double[iRetrieveBmpNumber];//开辟内存空间保存距离数据
///开辟内存,载入颜色几何均值
////初始化////
clock_t time1,time2; ///定义时间变量
double timecost;
time1=clock();
for(long int number=0;numberm_dFileStandCharacter[vectornumber]),2); ///第k种检索方式
}
///到现在为止,pDistance[]保存了各个图象和关键图的颜色距离,绝对值
///排序,按着从小到大排序
//基本方法,找到最小的欧式距离后,将它所对应的图象路径给显示数组,然后将赋值256
//由于归一化后的图象的欧式距离不可能为256,故在找下一个图象时不会重复
int sign=0; ///做最相似图象的标号
for(int displaynumber=0;displaynumberiRetrieveBmpNumber-1) //如果图像数目不够,退出
{
displaynumber=iRetrieveBmpNumber;
break;
}
for(int check=0;checkpDistance[check]) //要最小的
{
sign=check;
}
}
CHARACTERVQ* pcharactervqvar; //临时
pcharactervqvar=(CHARACTERVQ*)(pOutCharactervq+displaynumber);
*pcharactervqvar=*(pCharacterVq+sign);///save the PathName for display
*(pOutDistance+displaynumber)=pDistance[sign];
pDistance[sign]=100*36; //给最大值100 个矢量*6*6
}
///事后处理
delete[] pDistance; //释放保存欧式距离内存
time2=clock();
timecost=(double)(time2-time1)/CLOCKS_PER_SEC;
RetrieveTime->Empty();
RetrieveTime->Format("%s%f",*RetrieveTime,timecost);
///为显示文件名作准备,
*pOutBmpNumber=maxOutNumber;
for(displaynumber=0;displaynumberiRetrieveBmpNumber-1) //如果图像数目不够,退出
{
*pOutBmpNumber=(unsigned char)iRetrieveBmpNumber;
break;
}
}
//////////////////////////////////////////////////////////////////////////
return true;
}
//矢量检索,方法2:快速检索最相似的一幅图像
///pCharacterVq图像库矢量结构体指针,iCurrentCharacter:检索矢量的数量,
//iRetrieveBmpNumber图像库图像数目, KeybmpCharactervq :关键图像的结构
//pOutCharactervq:输出结构体的头指针,maxOutNumber=1输出图像的最多数目,*pOutBmpNumber:输出图像的数目的地址
//pDistance检索图像和关键图像的距离输出的头指针,RetrieveTime检索时间
bool CRetrieveMethod::RetrieveKeyVqMethod_2AccelerateBestOne(CHARACTERVQ *pCharacterVq,int iCurrentCharacter, long int iRetrieveBmpNumber,CHARACTERVQ KeybmpCharactervq, CHARACTERVQ *pOutCharactervq, unsigned char maxOutNumber,unsigned char *pOutBmpNumber, double *pOutDistance, CString *RetrieveTime)
{
///下面我们采用快速检索
////我们的矢量是按照均值排序的,而且,均值在矢量的最后一维分量上,从小到大的排序
////1.找和关键图的矢量最接近的矢量均值
////采用二分法
CHARACTERVQ testvq;
testvq.m_dFileStandCharacter;
clock_t time1,time2; ///定义时间变量
double timecost;
time1=clock();
int min=0,max=iRetrieveBmpNumber;////二分法中的前后两个数
int iFindNumber;
int i,j;
while(1)
{
//如果关键图的均值比中间的小
if (KeybmpCharactervq.m_dAverage<(pCharacterVq+(min+max)/2)->m_dAverage)
{
max=(min+max)/2;
}
else
min=(min+max)/2;
//上下限相等后相差一个单位,结束我们取均值较小的那个
if (min==max||(min==(max-1)))
{
double distance1=0;
double distance2=0;
for(i=0;im_dFileStandCharacter[i],2.0);
distance2=distance2+pow(KeybmpCharactervq.m_dFileStandCharacter[i]-(pCharacterVq+max)->m_dFileStandCharacter[i],2.0);
if(distance1m_dFileStandCharacter[i],2.0);
dDistanceMin=dDistanceCurrent; ///初始值
double mmin=KeybmpCharactervq.m_dAverage-sqrt(dDistanceCurrent/iCurrentCharacter); ///快速检索的上下限
double mmax=KeybmpCharactervq.m_dAverage+sqrt(dDistanceCurrent/iCurrentCharacter); ///快速检索的上下限
////检索开始
BOOL flagup=FALSE,flagdown=FALSE; ///上下检索标志是否继续标志
double distancevarible=0; ///变量
if (dDistanceCurrent==0)
{
flagup=true;
flagdown=true;
}
for(i=0;im_dAveragem_dFileStandCharacter[j],2.0);
if (distancevarible=iRetrieveBmpNumber||(pCharacterVq+iFindNumber+i)->m_dAverage>mmax) ///如果向上不能再检索
{
flagdown=TRUE;
}
else
{
///计算距离
distancevarible=0;
distancevarible=0;
for(j=0;jm_dFileStandCharacter[j],2.0);
if (distancevaribleEmpty();
RetrieveTime->Format("%s%f",*RetrieveTime,timecost);
///为显示文件名作准备,
*pOutBmpNumber=1;
*(pOutDistance+0)=dDistanceCurrent;
*(pOutCharactervq+0)=*(pCharacterVq+index);
//////////////////////////////////////////////////////////////////////////
return true;
}
//矢量检索,方法3:对矢量的某一维分量进行检索:vector维分量
///直接的检索矢量,对图像的矢量进行检索
///pCharacterVq图像库矢量结构体指针,iCurrentCharacter:检索矢量的数量,
//iRetrieveBmpNumber图像库图像数目, KeybmpCharactervq :关键图像的结构
//pOutCharactervq:输出结构体的头指针,maxOutNumber输出图像的最多数目,*pOutBmpNumber:输出图像的数目的地址
//pDistance检索图像和关键图像的距离输出的头指针,RetrieveTime检索时间
///int vector:分量值0~iCurrentCharacter-1
//0~100
bool CRetrieveMethod::RetrieveKeyVqMethod_3Single(CHARACTERVQ *pCharacterVq,int iCurrentCharacter, long int iRetrieveBmpNumber,CHARACTERVQ KeybmpCharactervq, CHARACTERVQ *pOutCharactervq, unsigned char maxOutNumber,unsigned char *pOutBmpNumber, double *pOutDistance, CString *RetrieveTime,int vector)
{
if (vector>iCurrentCharacter-1)
{
MessageBox(NULL,"this vector is not exist!","error",MB_OK);
return false;
}
double *pDistance=new double[iRetrieveBmpNumber];//开辟内存空间保存距离数据
///开辟内存,载入颜色几何均值
////初始化////
clock_t time1,time2; ///定义时间变量
double timecost;
time1=clock();
for(long int number=0;numberm_dFileStandCharacter[vector]),2); ///第k种检索方式
///到现在为止,pDistance[]保存了各个图象和关键图的颜色距离,绝对值
///排序,按着从小到大排序
//基本方法,找到最小的欧式距离后,将它所对应的图象路径给显示数组,然后将赋值256
//由于归一化后的图象的欧式距离不可能为256,故在找下一个图象时不会重复
int sign=0; ///做最相似图象的标号
for(int displaynumber=0;displaynumberiRetrieveBmpNumber-1) //如果图像数目不够,退出
{
displaynumber=iRetrieveBmpNumber;
break;
}
for(int check=0;checkpDistance[check]) //要最小的
{
sign=check;
}
}
CHARACTERVQ* pcharactervqvar; //临时
pcharactervqvar=(CHARACTERVQ*)(pOutCharactervq+displaynumber);
*pcharactervqvar=*(pCharacterVq+sign);///save the PathName for display
*(pOutDistance+displaynumber)=pDistance[sign];
pDistance[sign]=100*9; //给最大值100 个食量*9
}
///事后处理
delete[] pDistance; //释放保存欧式距离内存
time2=clock();
timecost=(double)(time2-time1)/CLOCKS_PER_SEC;
RetrieveTime->Empty();
RetrieveTime->Format("%s%f",*RetrieveTime,timecost);
///为显示文件名作准备,
*pOutBmpNumber=maxOutNumber;
for(displaynumber=0;displaynumberiRetrieveBmpNumber-1) //如果图像数目不够,退出
{
*pOutBmpNumber=(unsigned char)iRetrieveBmpNumber;
break;
}
}
//////////////////////////////////////////////////////////////////////////
return true;
}
//矢量检索,方法4:快速检索最相似的前16幅图像
///pCharacterVq图像库矢量结构体指针,iCurrentCharacter:检索矢量的数量,
//iRetrieveBmpNumber图像库图像数目, KeybmpCharactervq :关键图像的结构
//pOutCharactervq:输出结构体的头指针,maxOutNumber=16输出图像的最多数目,*pOutBmpNumber:输出图像的数目的地址
//pDistance检索图像和关键图像的距离输出的头指针,RetrieveTime检索时间
bool CRetrieveMethod::RetrieveKeyVqMethod_4AccelerateBest16(CHARACTERVQ *pCharacterVq,int iCurrentCharacter, long int iRetrieveBmpNumber,CHARACTERVQ KeybmpCharactervq, CHARACTERVQ *pOutCharactervq, unsigned char maxOutNumber,unsigned char *pOutBmpNumber, double *pOutDistance, CString *RetrieveTime)
{
clock_t time1,time2; ///定义时间变量
double timecost;
time1=clock();
int min=0,max=iRetrieveBmpNumber;////二分法中的前后两个数
int iFindNumber;
int i,j;
while(1)
{
//如果关键图的均值比中间的小
if (KeybmpCharactervq.m_dAverage<(pCharacterVq+(min+max)/2)->m_dAverage)
{
max=(min+max)/2;
}
else
min=(min+max)/2;
//上下限相等后相差一个单位,结束我们取均值较小的那个
if (min==max||(min==(max-1)))
{
double distance1=0;
double distance2=0;
for(i=0;im_dFileStandCharacter[i],2.0);
distance2=distance2+pow(KeybmpCharactervq.m_dFileStandCharacter[i]-(pCharacterVq+max)->m_dFileStandCharacter[i],2.0);
if(distance1m_dFileStandCharacter[i],2.0);
int finddmaxup,finddmaxdown; ////找最大的距离参数的上下限
BOOL flagup=FALSE,flagdown=FALSE; ///上下检索标志是否继续标志
finddmaxup=iFindNumber-16/2; ////上限
if(finddmaxup<=0) //如果越界,我们不用在向上检索
{
finddmaxup=0;
flagup=TRUE;
}
finddmaxdown=finddmaxup+15; ////下限
if(finddmaxdown>=iRetrieveBmpNumber) //如果越界,我们不用像下检索
{
finddmaxdown=iRetrieveBmpNumber-1;
flagdown=TRUE;
}
///初始化
for(i=0;i<16;i++)
kdistancevarible[i]=0;
///如果到图像数目小于16
if (iRetrieveBmpNumber<=16)
{
flagup=TRUE; /////此时,finddminup=0;finddmaxdown=m_iOverSign
flagdown=TRUE;
}
///到顶上,图像数目大于16,且到顶部
else if(finddmaxup==0)
{
finddmaxdown=15;
flagup=TRUE;
}
///到底端,图像数目大于16,且到底端
else if(finddmaxdown==iRetrieveBmpNumber-1)
{
finddmaxup=iRetrieveBmpNumber-16;
flagdown=TRUE;
///获得距离
}
///统一处理,计算它们的距离
{
for(i=finddmaxup;i<=finddmaxdown;i++)
{
index[i-finddmaxup]=i; ///给初始值
for(j=0;jm_dFileStandCharacter[j],2.0);
}
///排序,从小到大
for(i=finddmaxup;ikdistancevarible[j-finddmaxup])///比后面的大
{
////交换距离
distancevarible=kdistancevarible[i-finddmaxup];
kdistancevarible[i-finddmaxup]=kdistancevarible[j-finddmaxup];
kdistancevarible[j-finddmaxup]=distancevarible;
////交换索引号
indexvarible=index[i-finddmaxup];
index[i-finddmaxup]=index[j-finddmaxup];
index[j-finddmaxup]=indexvarible;
}
}
}
////检索
///我们以新的dDistanceCurrent作为上下限的控制来检索
///当然如果图像数目不够,我们应该控制
///具体的算法参考《矢量量化编码算法及应用研究》,陆哲明,2001,1
/////这里给出程序
///////我们检索的是前16幅图像
dDistanceCurrent=kdistancevarible[15]; ///取最大的
double mmin=KeybmpCharactervq.m_dAverage-sqrt(dDistanceCurrent/iCurrentCharacter); ///快速检索的上下限
double mmax=KeybmpCharactervq.m_dAverage+sqrt(dDistanceCurrent/iCurrentCharacter); ///快速检索的上下限
////向上下搜索
for(i=1;im_dAveragem_dFileStandCharacter[j],2.0);
if (distancevarible=0;t--)
{
if(distancevarible=iRetrieveBmpNumber||(pCharacterVq+finddmaxdown+i)->m_dAverage>mmax) ///如果向上不能再检索
{
flagdown=TRUE;
}
else
{
///计算距离
distancevarible=0;
for(j=0;jm_dFileStandCharacter[j],2.0);
if (distancevarible=0;t--)
{
if(distancevaribleEmpty();
RetrieveTime->Format("%s%f",*RetrieveTime,timecost);
///为显示文件名作准备,显示文件名为:m_sDisplayFileName
///为显示文件名作准备,
*pOutBmpNumber=maxOutNumber; //默认16
for(int displaynumber=0;displaynumberiRetrieveBmpNumber-1) //如果图像数目不够,退出
{
*pOutBmpNumber=(unsigned char)iRetrieveBmpNumber;
break;
}
pOutDistance[displaynumber]=kdistancevarible[displaynumber];
pOutCharactervq[displaynumber]=pCharacterVq[index[displaynumber]];
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
return true;
}
///用参数归一化一矢量结构体
//KeybmpCharactervq :关键图像的结构,characternumber矢量的数目
//pstandequvarible,方差的头指针,pstandaverage均值的头指针
bool CRetrieveMethod::StandKeyBmp(CHARACTERVQ *KeybmpCharactervq,int characternumber,double *pstandequvarible,double *pstandaverage)
{
const double mindata=1e-15;
int i;
for(i=0;im_dFileStandCharacter[i]=(KeybmpCharactervq->m_dFileOriginalCharacter[i]-*(pstandaverage+i))/(*(pstandequvarible+i));
if(fabs(KeybmpCharactervq->m_dFileStandCharacter[i])<=3.0)
continue;
else if (KeybmpCharactervq->m_dFileStandCharacter[i]<-3)
{
KeybmpCharactervq->m_dFileStandCharacter[i]=-3;
}
else
{
KeybmpCharactervq->m_dFileStandCharacter[i]=3;
}
}
///给出均值
double Datatotal=0;
for(i=0;im_dFileStandCharacter[i];
KeybmpCharactervq->m_dAverage=Datatotal/characternumber;
return true;
}
////标准化参数
/////charactervq:待归一化的结构;numberbmp=图像的数目;characternumber:矢量的维数
///pstandequvarible:输出标准差的首地址,pstandaverage:输出均值的首地址
bool CRetrieveMethod::StandCharacter(CHARACTERVQ *charactervq,long int numberbmp,int characternumber,double *pstandequvarible,double *pstandaverage)
{
long double Datatotal=0; /////同一类的参数的和
long int number; ///循环计数,矢量维数
double Average,squareDifference; ////均值和方差
for(number=0;numberm_dFileOriginalCharacter[number];
}
Average=Datatotal/numberbmp; ///均值
Datatotal=0; ///初始化
for(i=0;im_dFileOriginalCharacter[number]-Average,2.0);
}
squareDifference=sqrt(Datatotal/numberbmp);
*(pstandequvarible+number)=squareDifference;///////均方差输出
*(pstandaverage+number)=Average;///均值输出
for(i=0;im_dFileStandCharacter[number]=((charactervq+i)->m_dFileOriginalCharacter[number]-Average)/(*(pstandequvarible+number));
if(fabs((charactervq+i)->m_dFileStandCharacter[number])<=3.0) //限制范围
continue;
else if ((charactervq+i)->m_dFileStandCharacter[number]<-3)
{
(charactervq+i)->m_dFileStandCharacter[number]=-3;
}
else
{
(charactervq+i)->m_dFileStandCharacter[number]=3;
}
}
}
///计算均值
for(number=0;numberm_dFileStandCharacter[i];
(charactervq+number)->m_dAverage=Datatotal/characternumber;
}
////
return true;
}
///方法2:计算基于颜色的三个的三个中心矩
//计算高:dataheigth,datawidth首地址为*pdata的特征矢量存在结构体中:charactervq
//characterfirst:为特征矢量结构体的存入的第一个的编号,characternumber:该算法提取参数的个数
///本算法中,characternumber必须等于3
bool CRetrieveMethod::CharacterVqDistillMethod_2_3(unsigned char *pdata, int datawidth, int dataheigth, CHARACTERVQ *charactervq, int characterfirst, int characternumber)
{
if (characternumber!=3)
{
MessageBox(NULL,"CharacterDistill Number error","error!",MB_OK);
return false;
}
////add your word here
//////////////////////////////////////////////////////////////////////////
////////参数1:///像素均值
int width,height; //高宽
long int length=dataheigth*datawidth;
int i; ///变量
double M1=0,M2=0,M3=0; ///三阶矩
double *pihistogram=new double[256];
//
for(i=0;i<256;i++)
{
pihistogram[i]=0;
}
for(height=0;heightm_dFileOriginalCharacter[characterfirst+0]=M1;
charactervq->m_dFileOriginalCharacter[characterfirst+1]=M2;
charactervq->m_dFileOriginalCharacter[characterfirst+2]=M3;
//////////////////////////////////////////////////////////////////////////
///end of 计算
///delete the memory
delete[]pihistogram;
return true;
}
///提取参数,三阶矩
bool CRetrieveMethod::CharacterVqDistillMethod_3_1(unsigned char *pdata, int datawidth, int dataheigth, CHARACTERVQ *charactervq, int characterfirst, int characternumber)
{
if (characternumber!=1)
{
MessageBox(NULL,"CharacterDistill Number error","error!",MB_OK);
return false;
}
////add your word here
//////////////////////////////////////////////////////////////////////////
double M_00=0.0,M_01=0.0,M_10=0.0,M_12=0.0,M_30=0.0,M_03=0.0;//P+Q阶矩
double U_00=0.0,U_21=0,U_12=0.0,U_30=0.0,U_03=0.0;//P+Q阶中心矩
double m_00,n_00;//重心坐标
double u_00,u_12,u_21,u_30,u_03;//归一化的P+Q阶中心矩
///计算范例图的各阶矩
unsigned char * pBits = pdata;
for(int l=0; lm_dFileOriginalCharacter[characterfirst+0]=pow((u_30-3*u_12),2.0)+pow((3*u_21-u_03),2.0);
//end
return true;
}