上次說到了如何在WINCE/WM移植Opencv1.10,這次就說說如何在WM手機(jī)上使用裁剪移植后的Open1.10的例子,在opencv上使用OpenSURF(OpenSURF在GoogleCode的地址:http://code.google.com/p/opensurf1/),先來看看本文程序運(yùn)行的截圖:
左圖為SURF算法找出的特征點(diǎn),右圖為兩個圖像相似特征點(diǎn)的匹配。
本文的代碼可以到http://www.rayfile.com/zh-cn/files/da4d4edc-8af5-11df-9dac-0015c55db73d/這里下載,代碼里包含了自己實(shí)現(xiàn)的MyHighGUI類,用于轉(zhuǎn)換/繪制/保存IplImage圖像,也包含了同時支持WINCE/WIN32的第三方BMP操作類庫----DIBSectionCE類(詳見http://www.codeguru.com/cpp/w-p/ce/bitmapsandthegdi/article.php/c3),接下來就貼出部分操作代碼:
view plaincopy to clipboardprint?
//*****************************************************************
//取得程序當(dāng)前文件夾路徑
//****************************************************************
CString GetCurrentDirectory()
{
wchar_t pBuf[256];
GetModuleFileName(NULL,pBuf,sizeof(pBuf)/sizeof(wchar_t));
CString strPath(pBuf);
strPath = strPath.Left(strPath.ReverseFind('\\') + 1);
delete pBuf;
return strPath;
}
void CtestDlg::OnBnClickedButton1()
{
//自定義的HighGUI,詳見MyHighGUI.h
MyHighGUI gui;
//網(wǎng)上的BMP操作類,支持WINCE/WIN32,地址:http://www.codeguru.com/cpp/w-p/ce/bitmapsandthegdi/article.php/c3
CDIBSectionCE ce;
//step1:讀取BMP,并轉(zhuǎn)換為IplImage格式
CString bmpPath=GetCurrentDirectory()+L"car1.bmp";
ce.Load(bmpPath);
int nChannels = ce.GetBitmapInfo()->bmiHeader.biBitCount /8 ;
IplImage* img = gui.BMP2Ipl((BYTE*)ce.GetDIBits(),ce.GetWidth(),ce.GetHeight(),nChannels);
ce.DeleteObject();
//step2:提取圖片中的特征點(diǎn)
IpVec ipts;
surfDetDes(img, ipts, false, 3, 4, 2, 0.0004f);
// step3:畫出特征點(diǎn)
drawIpoints(img, ipts);
gui.Show(img,::GetDC(this->m_hWnd),0,0,img->width,img->height);
//gui.WriteBmp(L"img33.bmp",(BYTE *)img->imageData,img->imageSize,img->width,img->height);
img=NULL;
}
void CtestDlg::OnBnClickedButton2()
{
//自定義的HighGUI,詳見MyHighGUI.h
MyHighGUI gui;
//網(wǎng)上的BMP操作類,支持WINCE/WIN32,地址:http://www.codeguru.com/cpp/w-p/ce/bitmapsandthegdi/article.php/c3
CDIBSectionCE ce;
//step1:讀取BMP,并轉(zhuǎn)換為IplImage格式
CString bmpPath=GetCurrentDirectory()+L"car1.bmp";
ce.Load(bmpPath);
int nChannels = ce.GetBitmapInfo()->bmiHeader.biBitCount /8 ;
IplImage* img1 = gui.BMP2Ipl((BYTE*)ce.GetDIBits(),ce.GetWidth(),ce.GetHeight(),nChannels);
ce.DeleteObject();
bmpPath=GetCurrentDirectory()+L"car2.bmp";
ce.Load(bmpPath);
nChannels = ce.GetBitmapInfo()->bmiHeader.biBitCount /8 ;
IplImage* img2 = gui.BMP2Ipl((BYTE*)ce.GetDIBits(),ce.GetWidth(),ce.GetHeight(),nChannels);
ce.DeleteObject();
//step2:提取圖片中的特征點(diǎn)
IpVec ipts1, ipts2;
surfDetDes(img1,ipts1,false,4,4,2,0.0002f);
surfDetDes(img2,ipts2,false,4,4,2,0.0002f);
//step3:特征點(diǎn)匹配
IpPairVec matches;
getMatches(ipts1,ipts2,matches);
//step4:畫出匹配的特征點(diǎn),并且連線
for (unsigned int i = 0; i < matches.size(); ++i)
{
drawPoint(img1,matches[i].first);
drawPoint(img2,matches[i].second);
int w = img1->width;
cvLine(img1,cvPoint(matches[i].first.x,matches[i].first.y),cvPoint(matches[i].second.x+w,matches[i].second.y), cvScalar(123,123,123),1);
cvLine(img2,cvPoint(matches[i].first.x-w,matches[i].first.y),cvPoint(matches[i].second.x,matches[i].second.y), cvScalar(123,123,123),1);
}
//畫到屏幕上
if(img1->height>img2->height)
{
gui.Show(img1,::GetDC(this->m_hWnd),0,0,img1->width,img1->height);
gui.Show(img2,::GetDC(this->m_hWnd),img1->width,img1->height-img2->height,img2->width,img2->height);
}
else
{
gui.Show(img1,::GetDC(this->m_hWnd),0,img2->height-img1->height,img1->width,img1->height);
gui.Show(img2,::GetDC(this->m_hWnd),img1->width,0,img2->width,img2->height);
}
}
//*****************************************************************
//取得程序當(dāng)前文件夾路徑
//****************************************************************
CString GetCurrentDirectory()
{
wchar_t pBuf[256];
GetModuleFileName(NULL,pBuf,sizeof(pBuf)/sizeof(wchar_t));
CString strPath(pBuf);
strPath = strPath.Left(strPath.ReverseFind('\\') + 1);
delete pBuf;
return strPath;
}
void CtestDlg::OnBnClickedButton1()
{
//自定義的HighGUI,詳見MyHighGUI.h
MyHighGUI gui;
//網(wǎng)上的BMP操作類,支持WINCE/WIN32,地址:http://www.codeguru.com/cpp/w-p/ce/bitmapsandthegdi/article.php/c3
CDIBSectionCE ce;
//step1:讀取BMP,并轉(zhuǎn)換為IplImage格式
CString bmpPath=GetCurrentDirectory()+L"car1.bmp";
ce.Load(bmpPath);
int nChannels = ce.GetBitmapInfo()->bmiHeader.biBitCount /8 ;
IplImage* img = gui.BMP2Ipl((BYTE*)ce.GetDIBits(),ce.GetWidth(),ce.GetHeight(),nChannels);
ce.DeleteObject();
//step2:提取圖片中的特征點(diǎn)
IpVec ipts;
surfDetDes(img, ipts, false, 3, 4, 2, 0.0004f);
// step3:畫出特征點(diǎn)
drawIpoints(img, ipts);
gui.Show(img,::GetDC(this->m_hWnd),0,0,img->width,img->height);
//gui.WriteBmp(L"img33.bmp",(BYTE *)img->imageData,img->imageSize,img->width,img->height);
img=NULL;
}
void CtestDlg::OnBnClickedButton2()
{
//自定義的HighGUI,詳見MyHighGUI.h
MyHighGUI gui;
//網(wǎng)上的BMP操作類,支持WINCE/WIN32,地址:http://www.codeguru.com/cpp/w-p/ce/bitmapsandthegdi/article.php/c3
CDIBSectionCE ce;
//step1:讀取BMP,并轉(zhuǎn)換為IplImage格式
CString bmpPath=GetCurrentDirectory()+L"car1.bmp";
ce.Load(bmpPath);
int nChannels = ce.GetBitmapInfo()->bmiHeader.biBitCount /8 ;
IplImage* img1 = gui.BMP2Ipl((BYTE*)ce.GetDIBits(),ce.GetWidth(),ce.GetHeight(),nChannels);
ce.DeleteObject();
bmpPath=GetCurrentDirectory()+L"car2.bmp";
ce.Load(bmpPath);
nChannels = ce.GetBitmapInfo()->bmiHeader.biBitCount /8 ;
IplImage* img2 = gui.BMP2Ipl((BYTE*)ce.GetDIBits(),ce.GetWidth(),ce.GetHeight(),nChannels);
ce.DeleteObject();
//step2:提取圖片中的特征點(diǎn)
IpVec ipts1, ipts2;
surfDetDes(img1,ipts1,false,4,4,2,0.0002f);
surfDetDes(img2,ipts2,false,4,4,2,0.0002f);
//step3:特征點(diǎn)匹配
IpPairVec matches;
getMatches(ipts1,ipts2,matches);
//step4:畫出匹配的特征點(diǎn),并且連線
for (unsigned int i = 0; i < matches.size(); ++i)
{
drawPoint(img1,matches[i].first);
drawPoint(img2,matches[i].second);
int w = img1->width;
cvLine(img1,cvPoint(matches[i].first.x,matches[i].first.y),cvPoint(matches[i].second.x+w,matches[i].second.y), cvScalar(123,123,123),1);
cvLine(img2,cvPoint(matches[i].first.x-w,matches[i].first.y),cvPoint(matches[i].second.x,matches[i].second.y), cvScalar(123,123,123),1);
}
//畫到屏幕上
if(img1->height>img2->height)
{
gui.Show(img1,::GetDC(this->m_hWnd),0,0,img1->width,img1->height);
gui.Show(img2,::GetDC(this->m_hWnd),img1->width,img1->height-img2->height,img2->width,img2->height);
}
else
{
gui.Show(img1,::GetDC(this->m_hWnd),0,img2->height-img1->height,img1->width,img1->height);
gui.Show(img2,::GetDC(this->m_hWnd),img1->width,0,img2->width,img2->height);
}
}
用戶可以根據(jù)本文的操作代碼,在WINCE/WM平臺上實(shí)現(xiàn)更多Opencv例子,不過,本文程序跑起來很慢(我用的是460MHz的K3方案 WM手機(jī)),因?yàn)橹挥脴?biāo)準(zhǔn)C的Math做運(yùn)算處理。在ARM9+DSP或者ARM11等手機(jī)上使用Opencv,建議在Opencv的運(yùn)算部分用上這些手機(jī)的專用運(yùn)算指令,這樣可以大大提高運(yùn)算速度。
(審核編輯: 智匯小新)