1. 程式人生 > >基於顏色的圖像檢索學習系統

基於顏色的圖像檢索學習系統

函數 you ret 保持 ble 映射 搜索路徑 推斷 cfi

截圖:

【檢索前】

技術分享

【檢索後】

技術分享

功能:

單擊【查找文件夾】會隨機顯示當前文件夾下的6張圖像。假設當前文件夾下小於6幅。則所有顯示。

單擊【選擇】,會將測試圖像顯示在【選擇】button上方。

單擊【檢索】,會將與當前圖像顏色最接近的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;
	else
		showCounts=6;
	for(int i=0;i<counts;i++)
	{
		IS[i]=*ImageSource[i];
		//	AfxMessageBox(*ImageSource[i]);
	}
	id=1006; //這裏result2的id是1006,依次類推。result6的是1011
	for(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 here
	CFileDialog 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;
	else
		m=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 here
	CDialog::OnCancel();
}




實現環境:

VS2010



參考資料:

Visual C++數字圖像處理典型案例具體解釋。第8章,圖像檢索系統。


基於顏色的圖像檢索學習系統