vc++实现基于内容的图像检索系统(二)

vc++实现基于内容的图像检索系统(二)

基于颜色特征的检索——颜色矩
(一)颜色空间转换:由RGB 空间结构转换为HSV空间;
(二)计算颜色矩:变量m_graph记录值的变化;
(三)保存颜色矩:保存在feature_color。
具体方法在centerM()函数中实现:

void CImagetrievalDlg::centerM(CString pathfile,int mode)
{	
    CBitmap hbmp;
	HBITMAP hbitmap; 
	//装载资源
    hbitmap=(HBITMAP)::LoadImage (::AfxGetInstanceHandle(),pathfile,IMAGE_BITMAP,
		          0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);  
	hbmp.Attach(hbitmap);	
	//获取图像格式
	BITMAP bm;  
	hbmp.GetBitmap(&bm);    
	//创建临时的内存DC对象
	CDC dcMem;	
	dcMem.CreateCompatibleDC(GetDC());	
	dcMem.SelectObject(hbmp);
	int width=bm.bmWidth;
	int height=bm.bmHeight;
	int totalnum= height *width;

	long m_graph[3][12];
	float m_graphf[3][12];;
	for(int i=0;i<3;i++)
		for(int j=0;j<12;j++)
		{
		   m_graph[i][j]=0;
		   m_graphf[i][j]=0.0;
		   if(mode==1)
			   feature_color[i][j]=0.0;
		   else
			   feature_color_1[i][j]=0.0;
		}
	COLORREF color;
	double h=0,s=0,v=0;

	for(long y=0;y<height;y++)
		{	
		for(long x=0;x<width;x++)
		{			
			color=dcMem.GetPixel(x,y);
			RGBToHSV(GetRValue(color),GetGValue(color),GetBValue(color),&h,&s,&v);
		    int result_h=(int)(6*h/PI);
			if( result_h ==12)
				m_graph[0][11]++;
			else
        	    m_graph[0][result_h]++;

            int result_s=(int)(s*12);
			if( result_s ==12)
				m_graph[1][11]++;
			else
			    m_graph[1][result_s]++;

            int result_v=(int)(v*12);
			if( result_v ==12)
				m_graph[2][11]++;
			else
			    m_graph[2][result_v]++;
		}
	}	
	for(int i=0;i<3;i++)
		for(int j=0;j<12;j++)
		   m_graphf[i][j]=((float)m_graph[i][j])/((float)totalnum);
	float m1[3],m2[3],m3[3];
	for(int i=0;i<3;i++)
	{
		m1[i] = 0.0;
		m2[i] = 0.0;
		m3[i] = 0.0;
	}
	for(int i=0;i<3;i++)
		for(int j=0;j<12;j++)
		m1[i] +=m_graphf[i][j]/12;
	for(int i=0;i<3;i++)
		for(int j=0;j<12;j++)
		{
					m2[i] +=((m_graphf[i][j] - m1[i]) * (m_graphf[i][j] - m1[i]))/12;
			m3[i] +=((m_graphf[i][j] - m1[i]) * (m_graphf[i][j] - m1[i])
				* (m_graphf[i][j] - m1[i]))/12;
		}
	float zz=1/3;
    for(int i=0;i<3;i++)
	{
		m2[i] = sqrtf(m2[i]);
		m3[i] = (float)pow( m3[i], zz );
	}
	if(mode==1)
	{
	feature_color[0][0]=m1[0]; feature_color[0][1]=m2[0]; feature_color[0][2]=m3[0];
	feature_color[1][0]=m1[1]; feature_color[1][1]=m2[1]; feature_color[1][2]=m3[1];
	feature_color[2][0]=m1[2]; feature_color[2][1]=m2[2]; feature_color[2][2]=m3[2];
	}
	else
	{
	feature_color_1[0][0]=m1[0]; feature_color_1[0][1]=m2[0]; feature_color_1[0][2]=m3[0];
	feature_color_1[1][0]=m1[1]; feature_color_1[1][1]=m2[1]; feature_color_1[1][2]=m3[1];
	feature_color_1[2][0]=m1[2]; feature_color_1[2][1]=m2[2]; feature_color_1[2][2]=m3[2];
	}
}

基于形状特征的检索——Hu不变矩法提取特征

(一)检索指定坐标点的像素的RGB颜色值;
(二)大津法求阈值;
(三)阈值分割;
(四)求图像的区域重心;
(五)求中心矩;
(六)求HU不变矩;
(七)求图像离心率。
具体方法在torque()函数中实现:

void CImagetrievalDlg::torque(CString pathfile,int mode)
{	
    CBitmap hbmp;
	HBITMAP hbitmap; 
	int R,G,B;
	//装载资源
    hbitmap=(HBITMAP)::LoadImage (::AfxGetInstanceHandle(),pathfile,IMAGE_BITMAP,
		           0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);  
	hbmp.Attach(hbitmap);	
	//获取图像格式
	BITMAP bm;  
	hbmp.GetBitmap(&bm);    
	//创建临时的内存DC对象
	CDC dcMem;	
	dcMem.CreateCompatibleDC(GetDC());	
	dcMem.SelectObject(hbmp);
	int width=bm.bmWidth;
	int height=bm.bmHeight;
	COLORREF clr;
	for(int x=0;x<width;x++)
	{
		for(int y=0;y<height;y++)
		{
			//该函数检索指定坐标点的像素的RGB颜色值
			clr=dcMem.GetPixel(x,y);
			R=GetRValue(clr);
			G=GetGValue(clr);
			B=GetBValue(clr);
			pix[x][y]=0.299*R+0.587*G+0.114*B;
		}
	}
	//大津法求阈值
	int index_max;//最佳阈值
	double g_max;
	g_max=0;
	for(int index=0;index<256;index++)
	{
		double c0,c1,sum_0,sum_1;
		double w0,w1,u0,u1,g;
		c0=c1=sum_0=sum_1=w0=w1=u0=u1=g=0;
		for(int x=0;x<width;x++)
		{
			for(int y=0;y<height;y++)
			{
				if(pix[x][y]<index)
				{
				sum_0=sum_0+pix[x][y];//统计背景灰度值
				c0++;                               //统计背景像素值
				}
				else
				{
				sum_1=sum_1+pix[x][y];//统计前景灰度值
				c1++;                               //统计前景像素值
				}
			}
		}
		w0=c0/(c0+c1);//背景像素所占比例
		w1=c1/(c0+c1);//前景像素所占比例
		if(c0==0)
			u0=0;
		else
			u0=sum_0/c0;//背景平均灰度值
		if(c1==0)
			u1=0;
		else
			u1=sum_1/c1;//前景平均灰度值
		g=w0*w1*(u0-u1)*(u0-u1);
		if(g>g_max)//保存最佳阈值
		{
			g_max=g;
			index_max=index;
		}
	}
	//根据所求阈值进行阈值分割
	for(int x=0;x<width;x++)
	{
		for(int y=0;y<height;y++)
		{
			if(pix[x][y]<index_max)
				pix[x][y]=0;
			else
				pix[x][y]=1;
		}
	}

	//0+0阶矩
	double m00=0;
	for(int x=0;x<width;x++)
		for(int y=0;y<height;y++)
			m00+=pix[x][y];
	//1+0阶矩
	double m10=0;
	for(int x=0;x<width;x++)
		for(int y=0;y<height;y++)
			m10+=(x+1)*pix[x][y];
    //0+1阶矩
	double m01=0;
	for(int x=0;x<width;x++)
		for(int y=0;y<height;y++)
			m01+=(y+1)*pix[x][y];
	//1+1阶矩
	double m11=0;
	for(int x=0;x<width;x++)
		for(int y=0;y<height;y++)
			m11+=(y+1)*(x+1)*pix[x][y];
	//2+0阶矩
	double m20=0;
	for(int x=0;x<width;x++)
		for(int y=0;y<height;y++)
			m20+=(x+1)*(x+1)*pix[x][y];
	//0+2阶矩
	double m02=0;
	for(int x=0;x<width;x++)
		for(int y=0;y<height;y++)
			m02+=(y+1)*(y+1)*pix[x][y];
	//3+0阶矩
	double m30=0;
	for(int x=0;x<width;x++)
		for(int y=0;y<height;y++)
			m30+=(x+1)*(x+1)*(x+1)*pix[x][y];
	//0+3阶矩
	double m03=0;
	for(int x=0;x<width;x++)
		for(int y=0;y<height;y++)
			m03+=(y+1)*(y+1)*(y+1)*pix[x][y];
	//1+2阶矩
	double m12=0;
	for(int x=0;x<width;x++)
		for(int y=0;y<height;y++)
			m12+=(x+1)*(y+1)*(y+1)*pix[x][y];
	//2+1阶矩
	double m21=0;
	for(int x=0;x<width;x++)
		for(int y=0;y<height;y++)
			m21+=(x+1)*(x+1)*(y+1)*pix[x][y];

	//求图像的区域重心
	double xbar,ybar;
	xbar=(double)m10/m00;
	ybar=(double)m01/m00;

	//求中心矩
	double eta11,eta20,eta02,eta30,eta03,eta21,eta12;
	eta11=(m11-ybar*m10)/(m00*m00);
	eta20=(m20-xbar*m10)/(m00*m00);
	eta02=(m02-ybar*m01)/(m00*m00);
	eta30=(m30-3*xbar*m20+2*xbar*xbar*m10)/(m00*m00*sqrt(m00));
	eta03=(m03-3*ybar*m02+2*ybar*ybar*m01)/(m00*m00*sqrt(m00));
	eta21=(m21-2*xbar*m11-ybar*m20+2*xbar*xbar*m01)/(m00*m00*sqrt(m00));
	eta12=(m12-2*ybar*m11-xbar*m02+2*ybar*ybar*m10)/(m00*m00*sqrt(m00));

    //HU不变矩
	double phi[8];
	phi[0]=eta20+eta02;
	phi[1]=(eta20-eta02)*(eta20-eta02)+(4*eta11*eta11);
	phi[2]=((eta30-3*eta12)*(eta30-3*eta12))+((3*eta21-eta03)*(3*eta21-eta03));
	phi[3]=((eta30+eta12)*(eta30+eta12))+((eta21+eta03)*(eta21+eta03));
	phi[4]=(eta30-3*eta12)*(eta30+eta12)*((eta30+eta12)*(eta30+eta12)-3*(eta21+eta03)*(eta21+eta03)+
		        (3*eta21-eta03)*(eta21+eta03)*(3*(eta30+eta12)*(eta30+eta12)-(eta21+eta03)*(eta21+eta03)));
	phi[5]=(eta20-eta02)*((eta30+eta12)*(eta30+eta12)-(eta21+eta03)*(eta21+eta03))+
		        4*eta11*(eta30+eta12)*(eta21+eta03);
	phi[6]=(3*eta21-eta03)*(eta30+eta12)*((eta30+eta12)*(eta30+eta12)-3*(eta21+eta03)*(eta21+eta03))+
		        (3*eta12-eta30)*(eta21+eta03)*(3*(eta30+eta12)*(eta30+eta12)-(eta21+eta03)*(eta21+eta03)); 
	//图像离心率
	phi[7]=((eta20-eta02)*(eta20-eta02)+4*eta11*eta11)/((eta20+eta02)*(eta20+eta02));
if(mode==1)
	for(int i=0;i<8;i++)
	{
		phi[i]=fabs(log(fabs(phi[i])));
		feature_shape[i]=phi[i];
	}
else
	for(int i=0;i<8;i++)
	{
		phi[i]=fabs(log(fabs(phi[i])));
		feature_shape_1[i]=phi[i];
	}
}

基于纹理特征的检索——灰度共生矩阵
(一)灰度降级,对原始影像进行灰度降级如8,16,32,64等;
(二)根据设定好的窗口大小,逐窗口计算灰度共生矩阵;
(三)根据选择的二阶统计量,计算纹理值。
具体方法在CGrayShow()函数中实现:

{
	PMatrixRD = NULL;	//45度方向上的灰度共现矩阵
	PMatrixLD = NULL;	//135度方向上的灰度共现矩阵
	PMatrixV = NULL;		//90度方向上的灰度共现矩阵
	PMatrixH = NULL;		//0度方向上的灰度共现矩阵
	ImageArray = NULL;	//原始的图像数据数组

	m_tOriPixelArray = NULL;//原始位图数据
	m_tResPixelArray = NULL;//参考位图数据
	m_dib = new CDib();

	distance = 5;
	FilterWindowWidth = 16;
	GrayLayerNum = 8; //初始化设为8个灰度层,可以修改
	//这样共现矩阵均为GrayLayerNum×GrayLayerNum
	int i;
	PMatrixH = new int*[GrayLayerNum];
	PMatrixLD= new int*[GrayLayerNum];
	PMatrixRD= new int*[GrayLayerNum];
	PMatrixV = new int*[GrayLayerNum];
	for(i=0; iOpen(FilePathName);
	ImageWidth = m_dib->GetWidth();
	ImageHeight = m_dib->GetHeight();

	BYTE	*colorTable;
	colorTable = (BYTE *)m_dib->m_pDibBits;
	int byteBitCount  = m_dib->GetBiBitCount()/8;

	m_tOriPixelArray  = new RGBQUAD*[ImageHeight];
	m_tResPixelArray  = new RGBQUAD*[ImageHeight];
	ImageArray = new BYTE*[ImageHeight];
	for(int l=0 ; l=0; i--)
	{
		for(j=0; j1e-12)
			{
				FeatureEntropy -= pdMatrix[i][j]*log(pdMatrix[i][j]);
			}

			//惯性矩
			FeatureInertiaQuadrature += (double)(i-j)*(double)(i-j)*pdMatrix[i][j];

			//局部平稳
			FeatureLocalCalm += pdMatrix[i][j]/(1+(double)(i-j)*(double)(i-j));
		}
	}

	//计算ux
	double ux = 0.0;
	double localtotal = 0.0;
	for(i=0; i

基于形状特征的检索——相似度计算
计算正在检索的第N幅图与待检索图像的距离:dis+=fabs((feature_shape_1[i]-feature_shape[i])/fabs(feature_shape[i]))
若为第一次计算,则保存相似度计算结果,若已经计算过,则读取相似度计算结果,最后结果放在变量image_shape里面,详细实现在Shape_SeekImage()函数中:

void CImagetrievalDlg::Shape_SeekImage()
{
	for(int count=0; count<counts; count++)
		temp_1[count] = *temp[count];
	if(image_shape_temp.strfile_old==strfile&&image_shape_temp.m_strPath_old==m_strPath)
			shape=1;//此检索库下的此检索图像已经用此方法计算过
	else
			shape=0;
	for(int pic=0; pic<counts; pic++)//逐个分析检索库中图像
	{
		if(shape==0)
		{
		torque(temp_1[pic],2);//提取检索的第N幅图的不变矩
		double dis=0;//第N幅图与待检索图像的距离
		double dis_temp=0;
		//显示正在检索的第N幅图与待检索图像的距离
    	for(int i=0;i<8;i++)
			dis+=fabs((feature_shape_1[i]-feature_shape[i])/fabs(feature_shape[i]));
		image_shape_temp.tp[pic]=temp_1[pic];//保存第N幅图路径
		image_shape_temp.num[pic]=dis;//保存第N幅图与待检索图像的距离
		}
		ShowPic(temp_1[pic],IDC_VIEW1);
	}
	if(shape==0)//若本方法为第一次计算,则保存相似度计算结果
		image_shape=image_shape_temp;
	else//若本方法已经计算过,则读取相似度计算结果
		image_shape_temp=image_shape;
	//检索过的待检索图像及检索库路径更新
	image_shape_temp.m_strPath_old=m_strPath;
	image_shape_temp.strfile_old=strfile;
}

基于颜色特征的检索——相似度计算

颜色布局描述符在匹配时使用欧式距离公式,计算正在检索的第N幅图与待检索图像的距离:dis_temp+=(feature_color_1[i][j]-feature_color[i][j])*(feature_color_1[i][j]-feature_color[i][j])
若为第一次计算,则保存相似度计算结果,若已经计算过,则读取相似度计算结果,最后结果放在变量image_shape里面,详细实现在Color_SeekImage ()函数中:

void CImagetrievalDlg::Color_SeekImage()
{
	for(int count=0; count<counts; count++)
		temp_1[count] = *temp[count];
	switch(c_method)
	{
	case 1:
		if(image_color_1.strfile_old==strfile&&image_color_1.m_strPath_old==m_strPath)
			color=1;//此检索库下的此检索图像已经用此方法计算过
		else
			color=0;
		break;
	case 2:
		if(image_color_2.strfile_old==strfile&&image_color_2.m_strPath_old==m_strPath)
			color=1;//此检索库下的此检索图像已经用此方法计算过
		else
			color=0;
		break;
	case 3:
		if(image_color_3.strfile_old==strfile&&image_color_3.m_strPath_old==m_strPath)
			color=1;//此检索库下的此检索图像已经用此方法计算过已经用此方法计算过
		else
			color=0;
		break;
	}
	for(int pic=0; pic<counts; pic++)//逐个分析检索库中图像
	{
		if(color==0)
		{
			switch(c_method)
			{
			case 1:
			general(temp_1[pic],2);//提取检索的第N幅图的颜色直方图
			break;
			case 2:
			succession(temp_1[pic],2);//提取检索的第N幅图的累计直方图
			break;
			case 3:
			centerM(temp_1[pic],2);//提取检索的第N幅图的颜色矩
			break;
			}
			double dis=0;//第N幅图与待检索图像的距离
			double dis_temp=0;
			//计算正在检索的第N幅图与待检索图像的距离
			for(int i=0;i<3;i++)
			{
				for(int j=0;j<12;j++)
					dis_temp+=(feature_color_1[i][j]-feature_color[i][j])*(feature_color_1[i][j]-feature_color[i][j]);
				dis+=sqrt((double)dis_temp);
				dis_temp=0;
			}
			image_color_temp.tp[pic]=temp_1[pic];//保存第N幅图路径
			image_color_temp.num[pic]=dis;//保存第N幅图与待检索图像的距离
		}
		ShowPic(temp_1[pic],IDC_VIEW1);
	}
	switch(c_method)
	{
	case 1:
		if(color==0)//若本方法为第一次计算,则保存相似度计算结果
		{
			image_color_1=image_color_temp;
			sort();			
		}
		else//若本方法已经计算过,则读取相似度计算结果
		{
			image_color_temp=image_color_1;
			sort();
		}
		//检索过的待检索图像及检索库路径更新
	image_color_1.m_strPath_old=image_color_temp.m_strPath_old=m_strPath;	image_color_1.strfile_old=image_color_temp.strfile_old=strfile;
		break;
	case 2:
		if(color==0)
		{
			image_color_2=image_color_temp;
			sort();
		}
		else
		{
			image_color_temp=image_color_2;
			sort();
		}
		image_color_2.m_strPath_old=image_color_temp.m_strPath_old=m_strPath;
		image_color_2.strfile_old=image_color_temp.strfile_old=strfile;
		break;
	case 3:
		if(color==0)
		{
			image_color_3=image_color_temp;
			sort();
		}
		else
		{
			image_color_temp=image_color_3;
			sort();
		}
		image_color_3.m_strPath_old=image_color_temp.m_strPath_old=m_strPath;
		image_color_3.strfile_old=image_color_temp.m_strPath_old=strfile;
		break;
	}
}

你可能感兴趣的:(vc++2010)