用VC++实现图像检索技术Word格式文档下载.docx
- 文档编号:5733010
- 上传时间:2023-05-05
- 格式:DOCX
- 页数:18
- 大小:28.36KB
用VC++实现图像检索技术Word格式文档下载.docx
《用VC++实现图像检索技术Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《用VC++实现图像检索技术Word格式文档下载.docx(18页珍藏版)》请在冰点文库上搜索。
将这些颜色对中差值小于某一域值的颜色对删除以消除颜色噪声à
选取颜色对表中数值最大的几个颜色对做为图片的代表特征à
搜索目标图像的每一子块的颜色对表寻找与这写代表颜色对的匹配à
统计单一匹配次数à
若有某一比例以上的颜色对匹配到,图像即被检索到。
相似性度量:
(N为所用查询颜色对数目)
qj、gj:
颜色对j在查询图像Q和目标图像G中出现的次数
查询时颜色对的匹配应该是不精确的,应该允许的误差为2%以内
二.具体程序实现
a)基于子块颜色直方图方法的程序实现:
将图片分成4×
4格局,按从左到右、从上到下的顺序,分别计算各子块的颜色直方图,因此需要设定一个三维数组,前两维为子块的坐标,最后一维为颜色级,但现在采样得到的象素点的颜色值是RGB形式的,因此,需要将RGB形式转换为可以用比较合理的有限数表示的颜色级,而人眼对亮度是最为敏感的,因此可以将RGB转换为亮度值Y,公式为:
Y=R×
0.299+G×
0.587+B×
0.114
这样就确定的一个256级的颜色级别,而统计颜色直方图的三维数组就可以定义为:
intColor[4][4][256],当采样到某一颜色级时候,将相应的位置加一即可。
根据以上的子块间的相似公式:
,知道某一颜色级对应的数有可能是分母,当两个颜色级的数都为0的时候,显然是不能统计的,因此需要一个数组记录实际统计过的颜色级数,也需要一个数组记录4×
4子块的两幅图像的各子块的相似度。
对于用户选定的块其实是代表查询对象的,因此应该加大权重,相对来说就是减小其他块的权重,然后可以将乘过对应权重的块的相似度相加,得到最终的相似度,然后将所有目标图像与用户输入的图像的相似度从大到小排序,选出值最大的几张作为最后的查询结果显示出来返回。
以上是具体实现设想,程序实现如下:
//基于颜色直方图的方法
pDC->
TextOut(10,168,"
检索结果:
"
);
CBmpProc*pDestBmp;
CStringcomp_pic_path;
doublefsim[15];
file:
//15张待比较的目标图片与用户输入图片的相似度存放的数组
intpsim[15];
//与fsim想对应的图片编号数组,以便显示
for(intcomp_pic=1;
comp_pic<
=15;
comp_pic++){
comp_pic_path.Format("
image%d.bmp"
comp_pic);
bmp.LoadFromFile(comp_pic_path);
//从库中读入位图
pDestBmp=(CBmpProc*)new(CBmpProc);
//用new分配类目标
pDestBmp->
LoadFromObject(bmp,&
CRect(0,0,128,128));
//从bmp中的指定区域读入图像,以便图片匹配的进行
CalculateColor(*pDC);
//计算目标图片的颜色直方图
intx1,x2,y1,y2,x3,x4,y3,y4;
x1=obj_set.m_x1;
x2=obj_set.m_x2;
x3=obj_set.m_x3;
x4=obj_set.m_x4;
y1=obj_set.m_y1;
y2=obj_set.m_y2;
y3=obj_set.m_y3;
y4=obj_set.m_y4;
file:
//用户输入的对象所在子块(既用户选定的4个子块)的坐标
doublesim[4][4];
//子块之间的相似度数组
intccount[4][4];
//有过统计的颜色数目记录数组
for(inti=0;
i<
4;
i++)
for(intj=0;
j<
j++){
sim[i][j]=0;
ccount[i][j]=0;
}
//以下两个for按公式计算两幅图像的各对应子块之间的相似度
for(i=0;
j++)
for(intk=0;
k<
256;
k++){
if((pDestBmp->
Color[i][j][k]>
=pBmp->
Color[i][j][k])&
&
Color[i][j][k]!
=0){
sim[i][j]+=(1-((fabs(pDestBmp->
Color[i][j][k]-pBmp->
Color[i][j][k]))/(pDestBmp->
Color[i][j][k])));
ccount[i][j]++;
Color[i][j][k]Color[i][j][k])&
pBmp->
Colori][j][k]-pBmp->
Color[i][j][k]))/(pBmp->
ccount[i][j]++;
}
}
sim[i][j]=sim[i][j]/ccount[i][j];
}
//计算两图像最终的相似度结果
doublefinal_sim=0;
//对用户指定的块设置权重为1
if((i==x1&
j==y1)||(i==x2&
j==y2)||(i==x3&
j==y3)||(i==x4&
j==y4))
final_sim+=sim[i][j];
else
//其他块降低权重为0.7,提高对对象匹配的精确度
final_sim+=(sim[i][j]*0.7);
//将15幅被比较图像与用户输入源图像的最后计算出来的相似度结果记录在数组中
fsim[comp_pic-1]=final_sim;
delete(CBmpProc*)pDestBmp;
intcount=15;
doubletempf;
inttempp;
for(intl=0;
l<
15;
l++){
psim[l]=l+1;
//设定编号数组
//将15个相似度从大到小排列,并且改变次序的时候编号数组和跟着改变
for(inti=count;
i>
0;
i--){
j
if(fsim[j]
tempf=fsim[j];
tempp=psim[j];
fsim[j]=fsim[j+1];
psim[j]=psim[j+1];
fsim[j+1]=tempf;
psim[j+1]=tempp;
intdisp=0;
intspace=-128;
//将相似度最大的的两张图片显示出来
for(intdisp_pic=1;
disp_pic<
=2;
disp_pic++){
psim[disp_pic]);
//从bmp中的指定区域读入图像
disp++;
space+=128;
Rectangle(10+space-1,190-1,138+space+1,318+1);
Draw(*pDC,&
CRect(10+space,190,138+space,318));
//将pBmp中的图像绘入DC的指定区域
space+=6;
delete(CBmpProc*)pBmp;
//删除类目标,delete会自动调用类的析构函数。
AfxMessageBox("
检索完成"
b)基于颜色对的方法的程序实现
该方法也需要分成4×
4子块,计算颜色直方图,具体计算颜色直方图的方法上面已经有过详细的解释。
该方法主要在于对颜色对表示结构的实现,颜色对是某一图片的代表特征,因此在程序中必须有定量表示,现在采取用两个子块颜色直方图的欧氏距离表示,因此计算某一子块的颜色对表就是按八方向计算其与周围的子块之间的欧氏距离,将结果存放于一个doubleo_dis[8]的数组中,然后将这个数组从大到小排序,排序完成后再将数组中相互之间值的差小于某一域值(取8个颜色对的平均值的2%)的颜色对祛除(按序两两比较再移动数组里的变量实现),最后将结果先填入图像的特征颜色对表(有4×
8=32个变量,是一个结构数组,结构记录用户选定子块的坐标和与其相对应的被选中的颜色对值)。
最后,对4个用户选定的子块依次计算完毕,就可以调用SortColorPair()函数,对特征颜色对表做出处理(先从大到小排序,然后祛除差值小于总平均值的2%的特征颜色对)。
在比较的时候,按顺序计算出目标图像的子块颜色对表,和以上的特征颜色对表匹配,如果匹配到,则标记该颜色对(设定另一标记0数组),并且将匹配数变量加一,如果最后匹配到的数目是60%以上,就算目标图像被搜索到。
具体程序实现如下:
//计算子块(x,y)的颜色对表,采取"
八方向邻接技术"
intCBmpProc:
:
CalculateColorPair(intx,inty)
{
//颜色对采取欧氏距离来描述
doubleo_dis[8];
8;
o_dis[k]=0;
//计算(x,y)与周围所有子块的颜色直方图的欧氏距离
//---------------------------------------------
i++){
if((x-1)>
=0&
(y-1)>
=0)
o_dis[0]=o_dis[0]+(Color[x-1][y-1][i]-Color[x][y][i])*(Color[x-1][y-1][i]-Color[x][y][i]);
o_dis[0]=-1;
if((y-1)>
o_dis[1]=o_dis[1]+(Color[x][y-1][i]-Color[x][y][i])*(Color[x][y-1][i]-Color[x][y][i]);
o_dis[1]=-1;
if((x+1)<
=3&
o_dis[2]=o_dis[2]+(Color[x+1][y-1][i]-Color[x][y][i])*(Color[x+1][y-1][i]-Color[x][y][i]);
o_dis[2]=-1;
o_dis[3]=o_dis[3]+(Color[x-1][y][i]-Color[x][y][i])*(Color[x-1][y][i]-Color[x][y][i]);
o_dis[3]=-1;
=3)
o_dis[4]=o_dis[4]+(Color[x+1][y][i]-Color[x][y][i])*(Color[x+1][y][i]-Color[x][y][i]);
o_dis[4]=-1;
(y+1)<
o_dis[5]=o_dis[5]+(Color[x-1][y+1][i]-Color[x][y][i])*(Color[x-1][y+1][i]-Color[x][y][i]);
o_dis[5]=-1;
if((y+1)<
o_dis[6]=o_dis[6]+(Color[x][y+1][i]-Color[x][y][i])*(Color[x][y+1][i]-Color[x][y][i]);
o_dis[6]=-1;
o_dis[7]=o_dis[7]+(Color[x+1][y+1][i]-Color[x][y][i])*(Color[x+1][y+1][i]-Color[x][y][i]);
o_dis[7]=-1;
if(o_dis[j]>
o_dis[j]=sqrt(o_dis[j]);
//------------------------------------------------
//欧氏距离计算结束
intflag=0;
intnum=0;
for(intpairnum=0;
pairnum<
32;
pairnum++){
if(pair[pairnum].x!
=-1){
num++;
}//因为在计算子块的颜色对表的时候已经写了特征颜色对数组,因此要先统计一下特征颜色对数组里已经//有多少有数值了,以便下次的写入可以接在后面,而不至于覆盖了前面的数值
//计算颜色对差值小于某个"
域值"
的这个域值
doubleave=0;
for(inte=0;
e<
e++){
ave+=o_dis[e];
ave=ave/8;
ave=ave*0.02;
//采取与子块周围颜色对的平均值的2%计为域值
//对该子块的颜色对表进行从大到小的排序,采取冒泡排序
intcount=8;
doubletemp;
for(i=count;
if(o_dis[j]
temp=o_dis[j];
o_dis[j]=o_dis[j+1];
o_dis[j+1]=temp;
//消除那些颜色对差值小于某个"
的颜色对,以消除那些没有意义的小对象
for(k=0;
k
if(fabs(o_dis[k]-o_dis[k+1])
for(intl=k+1;
l
o_dis[l]=o_dis[l+1];
count--;
k--;
o_dis[count]=-1;
//将该字块计算得到的颜色对表填入该图像的特征颜色对表
for(intscan=0;
scan<
scan++){
if(o_dis[scan]>
0){
pair[num].x=x;
pair[num].y=y;
pair[num].o_dis=o_dis[scan];
return1;
//计算该图像的最终确定的特征颜色对表
BOOLCBmpProc:
SortColorPair()
//32个数据项中有count个有实际数值
for(intcount=0;
count<
count++){
if(pair[count].x==-1)
break;
structcolor_pairtemp;
//对颜色对表从大到小排列序(冒泡排序法)
if(pair[j].o_dis
temp=pair[j];
pair[j]=pair[j+1];
pair[j+1]=temp;
//计算域值以消除差值小于这个值的颜色对
e
ave+=pair[e].o_dis;
ave=ave/count;
//消除差值小于域值的颜色对
if(fabs(pair[k].o_dis-pair[k+1].o_dis)
pair[l]=pair[l+1];
//置特征颜色对数目变量
pair_count=count;
returntrue;
将计算颜色直方图的代码表达如下:
//以下函数计算颜色直方图
CalculateColor(CDC&
dc)
if(!
IsValid())
returnFALSE;
ASSERT(m_pInfo);
ASSERT(m_pInfo->
bmiHeader.biSize==sizeof(BITMAPINFOHEADER));
//复制源图
CDCcompDC;
//创建与当前显示设备兼容的内存设备描述表
compDC.CreateCompatibleDC(&
dc);
compDC.SelectObject(this);
COLORREFclr;
//定义一个COLORREF结构,因为提取的象素点的颜色是以RGB形式表示的
intpix_color;
intred,green,blue;
intx,y;
for(intfd=0;
fd<
fd++)
for(intsd=0;
sd<
sd++)
for(inttd=0;
td<
td++){
Color[fd][sd][td]=0;
//计算颜色直方图
k++)
x=j*32+l;
y=i*32+k;
clr=compDC.GetPixel(x,y);
red=GetRValue(clr);
green=GetGValue(clr);
blue=GetBValue(clr);
//因为RGB颜色共256^3种,不可能都保存到数组中,因此要先进行一定的提取工作,因为人对亮度的感
//觉是最明显的,所以可以先将RGB颜色值转成亮度值,这个公式即转换公司,刚好亮度数值是256级的,//就可以统计颜色直方图了
pix_color=red*0.299+green*0.587+blue*0.114;
Color[i][j][pix_color]++;
//对该象素点的颜色直方图数组中的相信位置加一,是直方图的物理实现
以上三个函数实现对某一图像内部的具体计算,而对于基于颜色对方法的外部计算如下:
//计算用户确定的4块位置与其周围位置的颜色对(颜色对现采取用相邻两块的直方图的欧氏距离表示)
CalculateColorPair(obj_set.m_x1,obj_set.m_y1);
CalculateColorPair(obj_set.m_x2,obj_set.m_y2);
CalculateColorPair(obj_set.m_x3,obj_set.m_y3);
CalculateColorPair(obj_set.m_x4,obj_set.m_y4);
//其实在以上的4部计算中,已经形成了初步的颜色对表,在此只不过是将表中的数据从大到小排列出来//并且祛除差值小于某一域值的颜色对
//计算颜色对结束,形成颜色对表
SortColorPair();
//颜色对表计算出来,表中的数据既是用户输入的该图像的代表特征
//读取带比较的图像(在此初定15幅--现定义这15幅图像即图片数据库)
comp_pic
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- VC 实现 图像 检索 技术