基于颜色的图像检索学习系统

来源:互联网 发布:linux 小数计算 编辑:程序博客网 时间:2024/05/16 02:56

截图:

【检索前】


【检索后】


功能:

单击【查找目录】会随机显示当前目录下的6张图像,如果当前目录下小于6幅,则全部显示。

单击【选择】,会将测试图像显示在【选择】按钮上方。

单击【检索】,会将与当前图像颜色最接近的6幅图像显示在下方。



思路:

将图像的RGB空间映射到HSV空间,并将其H、S、V均划分为12个区间。这样图像得到3*12个属性。

对选取的测试图像和所有的待检索图像均进行上述处理。

计算测试图像与检索图像之间的距离,将得到的距离按照从小到大的顺序排序,将排序靠前的6张图像显示在检索框中。

距离的计算可以采用典型的欧氏距离。

步骤:

1.将计算测试图像的HSV属性。

2.计算当前目录下每一个图像的HSV属性,并计算其与测试图像HSV属性之间的距离。

3.将得到的距离进行排序。

4.按照排序结果显示图像。

部分代码:

【查找目录】

void CCBIRLSDlg::OnBnClickedButton2(){// TODO: Add your control notification handler code here//使用BROWSEINFO结构,打开通用对话框,获取用户选中目录的信息BROWSEINFO browse;ZeroMemory(&browse,sizeof(browse));browse.hwndOwner = NULL;browse.pszDisplayName = SPath.GetBuffer(MAX_PATH);//browse.lpszTitle=s;//返回选择文件夹的信息LPITEMIDLIST lpItem = SHBrowseForFolder(&browse);if(lpItem == NULL) return ;SPath.ReleaseBuffer();//SHGetPathFromIDList把项目标志符列表转换为文档系统路径if(SHGetPathFromIDList(lpItem,SPath.GetBuffer(MAX_PATH)) == false) return;SPath.ReleaseBuffer();SPath.Trim();////////////////////待处理int tempi=0;counts=0;//计数器清零////////////////////待处理//AfxMessageBox(SPath);//检索库中图像个数放入counts中,其路径放入temp[100]中BOOL flag; CFileFind find; char tempFileFind[200]; //sprintf_s(tempFileFind,"%s\\*.bmp",SPath); sprintf_s(tempFileFind,"%s\\*.bmp",SPath); flag = find.FindFile(tempFileFind); //在当前目录下查找BMP文件LPWSTR myFileName;//path.SetWindowTextA(SPath);   //path关联文本框。while(flag) { flag = find.FindNextFile(); char foundFileName[200];//临时存储查找到的图像名//strcpy_s(foundFileName,find.GetFileName().GetBuffer(200));//获取图像名//strcpy(foundFileName,find.GetFileName().GetBuffer(200));//获取图像名//strcpy_s//myFileName=find.GetFileName().GetBuffer(200);strcpy_s(foundFileName,find.GetFileName().GetBuffer(200));//strcpy_s(foundFileName,find.GetFileName().GetBuffer(200));//AfxMessageBox(foundFileName);//path.SetWindowTextW(foundFileName);//strcpy(foundFileName,&myFileName);if(!find.IsDots()) //过滤缺省目录{ char tempFileName[200];sprintf_s(tempFileName,"%s\\%s",SPath,foundFileName);//CString strfilepath1;//strfilepath1.Format("%s",tempFileName);//获取图像完整路径ImageSource[counts] = new CString(tempFileName);//保存图像完整路径counts++;//AfxMessageBox(ImageSource[counts],MB_ICONINFORMATION|MB_OK);//AfxMessageBox(ImageSource[counts]);//databaseImage.Load(ImageSource[counts]);//AfxMessageBox(*ImageSource[counts]);//path.SetWindowTextA(ImageSource[counts]);} } find.Close(); //CString temps;//temps.Format("该目录下共有%d幅图像!",counts);// AfxMessageBox(temps,MB_ICONINFORMATION|MB_OK);//AfxMessageBox("您选择的目录为:"+SPath,MB_ICONINFORMATION|MB_OK);//strcat("当前路径为:",SPath);//随机显示其下面的图像,如果小于六幅,全部显示;大于6幅,随机显示六幅//CString result;/*pic[1]="Result1";pic[2]="result2";pic[3]="result3";pic[4]="result4";pic[5]="result5";pic[6]="result6";*///将当前目录下的图片显示,显示获取的前6幅图像,如果小于6幅,则仅显示存在的图像if(counts<6)showCounts=counts;elseshowCounts=6;for(int i=0;i<counts;i++){IS[i]=*ImageSource[i];//AfxMessageBox(*ImageSource[i]);}id=1006; //这里result2的id是1006,依次类推,result6的是1011for(int i=0;i<showCounts;i++){if(!databaseImage.IsNull())//判断图象是否为空,如果不为空则先释放掉databaseImage.Destroy();//databaseImage.load(IS[i]);databaseImage.Load(IS[i]);CRect rect;CWnd *pWnd = GetDlgItem(id++);CDC *pDC = pWnd->GetDC();//第1个控件pWnd->GetClientRect(&rect); //取得客户区尺寸pDC->SetStretchBltMode(STRETCH_HALFTONE); //保持图片不失真databaseImage.Draw( pDC->m_hDC,rect); //已控件尺寸大小来绘图ReleaseDC( pDC );}//path.SetWindowTextW(SPath);   //path关联文本框。此处在文本框内显示设置的搜索路径。path.SetWindowTextA(SPath);   //setWindowTextW为单字符集下使用的函数}

【选择】

void CCBIRLSDlg::OnBnClickedButton1(){// TODO: Add your control notification handler code hereCFileDialog fileDlg(TRUE,NULL,NULL,OFN_ALLOWMULTISELECT,_T("Picture Files (*.bmp *.jpg)|*bmp;;*jpg||"),AfxGetMainWnd());CString pathName;if(fileDlg.DoModal () == IDOK){  POSITION mPos = fileDlg.GetStartPosition();if(mPos!=NULL)  {  pathName = (LPCTSTR)fileDlg.GetPathName();if(!myImage.IsNull())//判断图象是否为空,如果不为空则先释放掉myImage.Destroy();myImage.Load(pathName);}   }  CRect rect;CWnd *pWnd = GetDlgItem(IDC_MY_PIC2);CDC *pDC = pWnd->GetDC();//第1个控件pWnd->GetClientRect(&rect); //取得客户区尺寸pDC->SetStretchBltMode(STRETCH_HALFTONE); //保持图片不失真myImage.Draw( pDC->m_hDC,rect); //已控件尺寸大小来绘图ReleaseDC( pDC );//myImage.Destroy();}


【检索】

void CCBIRLSDlg::OnBnClickedButton3(){// TODO: Add your control notification handler code here/*if(myImage.IsNull()){AfxMessageBox(_T("请先选择要检索的图像"));return;}if(SPath.IsEmpty()){AfxMessageBox(_T("请先选择要检索的路径"));return ;}*/COLORREF color;double h=0,s=0,v=0;long myGraph[3][13]; //用于存储HSV空间值double sourceFeature[3][12];//待检索图像的颜色特征double tempFeature[3][12]; //用于存储检索目录下文件的特征int maxX,maxY;int totalNum;for(int i=0;i<3;i++)for(int j=0;j<13;j++){myGraph[i][j]=0;}maxX=myImage.GetWidth();maxY=myImage.GetHeight();totalNum=maxX*maxY;for (int i=0; i<maxX-1; i++) {for (int j=0; j<maxY-1; j++) {color=myImage.GetPixel(i,j);RGB2HSV(GetRValue(color),GetGValue(color),GetBValue(color),&h,&s,&v);int result_h=(int)(6*h/3.1415926);int result_s=(int)(s*12); int result_v=(int)(v*12);myGraph[0][result_h]++;myGraph[1][result_s]++;myGraph[2][result_v]++;}}for(int i=0;i<3;i++)for(int j=0;j<12;j++){sourceFeature[i][j]=((float)myGraph[i][j])/((float)totalNum);}//计算每幅图像与待检索图像的距离。for(int i=0;i<counts;i++)distance[i]=0;for(int ch=0;ch<counts;ch++){for(int i=0;i<3;i++)for(int j=0;j<13;j++){myGraph[i][j]=0;}if(!databaseImage.IsNull())//判断图象是否为空,如果不为空则先释放掉databaseImage.Destroy();//databaseImage.load(IS[i]);databaseImage.Load(IS[ch]);//测试,是否显示了正确的图像  AfxMessageBox(IS[ch]);maxX=databaseImage.GetWidth();maxY=databaseImage.GetHeight();totalNum=maxX*maxY;for (int i=0; i<maxX-1; i++) {for (int j=0; j<maxY-1; j++) {color=databaseImage.GetPixel(i,j);RGB2HSV(GetRValue(color),GetGValue(color),GetBValue(color),&h,&s,&v);int result_h=(int)(6*h/3.1415926);int result_s=(int)(s*12); int result_v=(int)(v*12);myGraph[0][result_h]++;myGraph[1][result_s]++;myGraph[2][result_v]++;//此处未对等于12的情况进行处理,概率很小,可是仍旧可能报错,需要注意。}}double distanceTemp=0;  //此处,曾被定义为int类型,错错!!!for(int i=0;i<3;i++){for(int j=0;j<12;j++){tempFeature[i][j]=((float)myGraph[i][j])/((float)totalNum);distanceTemp+=(tempFeature[i][j]-sourceFeature[i][j])*(tempFeature[i][j]-sourceFeature[i][j]);}distance[ch]+=sqrt((double)distanceTemp);distanceTemp=0;}//开始对图像进行置乱,然后显示。///////////////////测试位置/*CString str;//double w=0.33;str.Format("%lf",distance[ch]);  AfxMessageBox(str);*////////////////////测试位置}//排序,让距离较小的图像显示在较前的位置上。//ImageSourceResult=ImageSource;for(int i=0;i<counts;i++){ImageSourceResult[i]=*ImageSource[i];//AfxMessageBox(*ImageSource[i]);}double tempDis;CString tempPic;///////////测试/*for(int i=0;i<counts-1;i++)if(distance[i]=distance[i+1]){AfxMessageBox("game error");}if(distance[0]==0)AfxMessageBox("game error");//AfxMessageBox(distance[0]);CString   str  ;for(int i=0;i<counts;i++){str.Format("%d",distance[i]);  AfxMessageBox(str);}*////////////测试for(int i=0;i<counts;i++){for(int j=i+1;j<counts;j++){if(distance[i]>distance[j]){//AfxMessageBox("game error");tempPic=ImageSourceResult[i];tempDis=distance[i];ImageSourceResult[i]=ImageSourceResult[j];distance[i]=distance[j];ImageSourceResult[j]=tempPic;distance[j]=tempDis;}}}id=1006;  // 设置显示的picture control控件起始ID号for(int i=0;i<showCounts;i++){if(!databaseImage.IsNull())//判断图象是否为空,如果不为空则先释放掉databaseImage.Destroy();//databaseImage.load(IS[i]);databaseImage.Load(ImageSourceResult[i]);CRect rect;CWnd *pWnd = GetDlgItem(id++);CDC *pDC = pWnd->GetDC();//第1个控件pWnd->GetClientRect(&rect); //取得客户区尺寸pDC->SetStretchBltMode(STRETCH_HALFTONE); //保持图片不失真databaseImage.Draw( pDC->m_hDC,rect); //已控件尺寸大小来绘图ReleaseDC( pDC );}AfxMessageBox("检索完成!");}

【部分函数等】

CImage CCBIRLSDlg::RGB2HSV(void){return CImage();}CImage CCBIRLSDlg::RGB2HSV(CImage * sourceImage){return CImage();}void CCBIRLSDlg::RGB2HSV(int r , int g , int b , double *h, double *s, double *v){*h=acos((r-g+r-b)/(2.0*sqrtf((float)(r-g)*(r-g)+(float)(r-b)*(g-b))));if(b>g)*h=2*3.1415926-*h;*s=(MAX(r,g,b)-MIN(r,g,b))/(float)MAX(r,g,b);*v=MAX(r,g,b)/255.0;}int CCBIRLSDlg::MAX(int a, int b, int c){int m;if(a>b)m=a;elsem=b;if(m<c)m=c;return m;}int CCBIRLSDlg::MIN(int a, int b, int c){int m;if(a<b)m=a;else m=b;if(m>c)m=c;return m;}void CCBIRLSDlg::OnBnClickedButton4(){// TODO: Add your control notification handler code hereCDialog::OnCancel();}




实现环境:

VS2010



参考资料:

Visual C++数字图像处理典型案例详解,第8章,图像检索系统。


2 0