⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cretrievemethod.cpp

📁 关于基于内容的图像特征的检索VC的实现,包括直方图,累计直方图等
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// 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;i<iRetrieveBmpNumber-1;i++)
	{
		index=i;
		for(j=i+1;j<iRetrieveBmpNumber;j++)
			if ((pCharacterVq+index)->m_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;count<Max;count++)   ////执行次数
		{
			regionnumberleft=0;
			regionnumberright=0;  
			regiontotallleft=0;
			regiontotalright=0;
				for(i=0; i<dataheigth; i++)
					for(j=0; j<datawidth; j++)
					{
						if(*(pdata + i*datawidth + j)<=(unsigned char)regiondata2)
						{
							regionnumberleft++;       ////左计数器加一
							regiontotallleft=regiontotallleft+(*(pdata + i*datawidth + j));//总和加一

						}
						else 
							regiontotalright=regiontotalright+(*(pdata + i*datawidth + j));
					}
					regionnumberright=datawidth*dataheigth-regionnumberleft;///右计数器计算得出
					if (regionnumberright==0)  //排除异常
					{
						regionnumberright=1;
					}
						if (regionnumberleft==0)//排除异常
					{
						regionnumberleft=1;
					}
					regiondata2=(regiontotallleft/regionnumberleft+regiontotalright/regionnumberright)/2.0;////计算公式
					if((unsigned char)regiondata2==(unsigned char)regiondata1)///结束
						break;
					else 
						regiondata1=regiondata2;

		}
	charactervq->m_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; i<dataheigth-1; i++)
		for(j=1; j<datawidth-1; j++)
				{
					texturematrix[*(pdata + i*datawidth + j)][*(pdata + i*datawidth + j-1)]=texturematrix[*(pdata + i*datawidth + j)][*(pdata + i*datawidth + j-1)]+1;
					texturematrix[*(pdata + i*datawidth + j)][*(pdata + i*datawidth + j+1)]=texturematrix[*(pdata + i*datawidth + j)][*(pdata + i*datawidth + j+1)]+1;
					texturematriy[*(pdata + i*datawidth + j)][*(pdata + (i-1)*datawidth + j)]=texturematrix[*(pdata + i*datawidth + j)][*(pdata + (i-1)*datawidth + j)]+1;
					texturematriy[*(pdata + i*datawidth + j)][*(pdata + (i+1)*datawidth + j)]=texturematrix[*(pdata + i*datawidth + j)][*(pdata + (i+1)*datawidth + j)]+1;
									
				}
	

///////参数3:反差(主对角线的惯性矩)Con
/////////特点:对于粗纹理由于共生矩阵的元素较集中于主对角线附近,此时(h-k)(像素差)较小,
//			  相应的CON值也较小,相反,对于细纹理,则相应的CON值较大。
////////参数4:能量(角二阶矩)Asm
////////特点: 这是一种对图像灰度分布的度量,当共生矩阵的元素分布较集中与主对角线时,
//		  	 相应的ASM值较大,反之,ASM值较小。
////////参数5:熵
/////////特点:当共生矩阵的元素相差不大且较分散时,ENT值较大;反之,生矩阵的元素较集中时,
//      	  ENT值较小。
		unsigned long int MaxNumber=dataheigth*datawidth;////归一化参数
		unsigned long double Ent1=0,Ent2=0;					////熵变量Ent1水平,Ent2
		unsigned long double Asm1=0,Asm2=0;           ///能量变量
	    unsigned long double Con1=0,Con2=0;        ///反差变量
		for(i=0; i<256; i++)
			for(j=0; j<256; j++)
			{
				long double varible1=texturematrix[i][j]/MaxNumber;  //简化计算的变量,/////归一化共生矩阵
				long double varible2=texturematriy[i][j]/MaxNumber;
				Con1=Con1+(i-j)*(i-j)*varible1;
				Con2=Con2+(i-j)*(i-j)*varible2;
				Asm1=Asm1+varible1*varible1;
				Asm2=Asm2+varible2*varible2;
				if(varible1!=0)
					Ent1=Ent1+varible1*log(varible1);
				if(varible2!=0)
					Ent2=Ent2+varible2*log(varible2);				
			}
	charactervq->m_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; l<dataheigth; l++)
		for(int k=0; k<datawidth; k++)
		{ 
		  M_00+=*(pdata + l*datawidth + k);
		  M_01+=*(pdata + l*datawidth + k)*l;
          M_10+=*(pdata + l*datawidth + k)*k;	
		}
	//重心坐标 
		m_00=M_10/M_00;//横坐标
		n_00=M_01/M_00;//纵坐标
	    U_00=M_00;
	for(j=0; j<dataheigth; j++)
		for(i=0; i<datawidth; i++)
	   {
		 U_02+=(j-n_00)*(j-n_00)*(*(pdata + j*datawidth + i));
		 U_20+=(i-m_00)*(i-m_00)*(*(pdata + j*datawidth + i));
		 U_11+=(i-m_00)*(j-n_00)*(*(pdata + j*datawidth + i));
	   }
		u_00=U_00;
		u_02=U_02/pow(u_00,2.0);
		u_11=U_11/pow(u_00,2.0);
		u_20=U_20/pow(u_00,2.0);
	    ///二阶不变矩保存
	  	charactervq->m_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;number<iRetrieveBmpNumber;number++)
	{
				pDistance[number]=0;             ///初始值为0
				for(int vectornumber=0;vectornumber<vector;vectornumber++)
					pDistance[number]=pDistance[number]+pow((KeybmpCharactervq.m_dFileStandCharacter[vectornumber]-(pCharacterVq+number)->m_dFileStandCharacter[vectornumber]),2); ///第k种检索方式

	}
///到现在为止,pDistance[]保存了各个图象和关键图的颜色距离,绝对值
///排序,按着从小到大排序
//基本方法,找到最小的欧式距离后,将它所对应的图象路径给显示数组,然后将赋值256
//由于归一化后的图象的欧式距离不可能为256,故在找下一个图象时不会重复
			int sign=0;            ///做最相似图象的标号
			for(int displaynumber=0;displaynumber<maxOutNumber;displaynumber++)//16个显示图象
			{
				if(displaynumber>iRetrieveBmpNumber-1)        //如果图像数目不够,退出
					{
					
						displaynumber=iRetrieveBmpNumber;
						break;
					}	
					for(int check=0;check<iRetrieveBmpNumber;check++)
					{
						if(pDistance[sign]>pDistance[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;displaynumber<maxOutNumber;displaynumber++)//16个显示图象
		  {
			if(displaynumber>iRetrieveBmpNumber-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;////二分法中的前后两个数

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -