基于颜色特征的检索——颜色矩
(一)颜色空间转换:由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;
}
}