上次说到了如何在WINCE/WM移植Opencv1.10,这次就说说如何在WM手机上使用裁剪移植后的Open1.10的例子,在opencv上使用OpenSURF(OpenSURF在GoogleCode的地址:http://code.google.com/p/opensurf1/),先来看看本文程序运行的截图:
左图为SURF算法找出的特征点,右图为两个图像相似特征点的匹配。
本文的代码可以到http://www.rayfile.com/zh-cn/files/da4d4edc-8af5-11df-9dac-0015c55db73d/这里下载,代码里包含了自己实现的MyHighGUI类,用于转换/绘制/保存IplImage图像,也包含了同时支持WINCE/WIN32的第三方BMP操作类库----DIBSectionCE类(详见http://www.codeguru.com/cpp/w-p/ce/bitmapsandthegdi/article.php/c3),接下来就贴出部分操作代码:
view plaincopy to clipboardprint?
//*****************************************************************   
//取得程序当前文件夹路径   
//****************************************************************   
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;   
    //网上的BMP操作类,支持WINCE/WIN32,地址:http://www.codeguru.com/cpp/w-p/ce/bitmapsandthegdi/article.php/c3   
    CDIBSectionCE ce;   
    //step1:读取BMP,并转换为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:提取图片中的特征点   
    IpVec ipts;   
    surfDetDes(img, ipts, false, 3, 4, 2, 0.0004f);   
  
    // step3:画出特征点     
    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;   
    //网上的BMP操作类,支持WINCE/WIN32,地址:http://www.codeguru.com/cpp/w-p/ce/bitmapsandthegdi/article.php/c3   
    CDIBSectionCE ce;   
    //step1:读取BMP,并转换为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:提取图片中的特征点   
    IpVec ipts1, ipts2;   
    surfDetDes(img1,ipts1,false,4,4,2,0.0002f);   
    surfDetDes(img2,ipts2,false,4,4,2,0.0002f);   
  
    //step3:特征点匹配   
    IpPairVec matches;   
    getMatches(ipts1,ipts2,matches);   
  
    //step4:画出匹配的特征点,并且连线   
    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);   
    }   
  
}  
//*****************************************************************
//取得程序当前文件夹路径
//****************************************************************
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;
 //网上的BMP操作类,支持WINCE/WIN32,地址:http://www.codeguru.com/cpp/w-p/ce/bitmapsandthegdi/article.php/c3
 CDIBSectionCE ce;
 //step1:读取BMP,并转换为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:提取图片中的特征点
 IpVec ipts;
 surfDetDes(img, ipts, false, 3, 4, 2, 0.0004f);
 // step3:画出特征点  
 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;
 //网上的BMP操作类,支持WINCE/WIN32,地址:http://www.codeguru.com/cpp/w-p/ce/bitmapsandthegdi/article.php/c3
 CDIBSectionCE ce;
 //step1:读取BMP,并转换为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:提取图片中的特征点
    IpVec ipts1, ipts2;
    surfDetDes(img1,ipts1,false,4,4,2,0.0002f);
    surfDetDes(img2,ipts2,false,4,4,2,0.0002f);
 //step3:特征点匹配
    IpPairVec matches;
    getMatches(ipts1,ipts2,matches);
 //step4:画出匹配的特征点,并且连线
 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);
 }
}
 
用户可以根据本文的操作代码,在WINCE/WM平台上实现更多Opencv例子,不过,本文程序跑起来很慢(我用的是460MHz的K3方案 WM手机),因为只用标准C的Math做运算处理。在ARM9+DSP或者ARM11等手机上使用Opencv,建议在Opencv的运算部分用上这些手机的专用运算指令,这样可以大大提高运算速度。
(审核编辑: 智汇小新)
 
			 
			 
			