移动设备上使用opencv 1.10做图像识别的举例说明

时间:2011-08-24

 

  OpenCV于1999年由Intel建立,现在由Willow Garage提供支持。OpenCV是一个基于BSD许可证授权(开源)发行的跨平台计算机视觉库,可以运行在Linux、Windows和Mac OS操作系统上。它轻量级而且高效--由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。[1]版本是2.2.OpenCV致力于真实世界的实时应用,通过优化的C代码的编写对其执行速度带来了可观的提升,并且可以通过购买Intel的IPP高性能多媒体函数库(Integrated Performance Primitives)得到更快的处理速度。

  图形刺激作用于感觉器官,人们辨认出它是经验过的某一图形的过程,也叫图像再认。在图像识别中,既要有当时进入感官的信息,也要有记忆中存储的信息。只有通过存储的信息与当前的信息进行比较的加工过程,才能实现对图像的再认。人的图像识别能力是很强的。图像距离的改变或图像在感觉器官上作用位置的改变,都会造成图像在视网膜上的大小和形状的改变。即使在这种情况下,人们仍然可以认出他们过去知觉过的图像。甚至图像识别可以不受感觉通道的限制。例如,人可以用眼看字,当别人在他背上写字时,他也可认出这个字来。

  上次说到了如何在WINCE/WM移植Opencv1.10,这次就说说如何在WM手机上使用裁剪移植后的Open1.10的例子,在opencv上使用OpenSURF,先来看看本文程序运行的截图:

  左图为SURF算法找出的特征点,右图为两个图像相似特征点的匹配。

  代码里包含了自己实现的MyHighGUI类,用于转换/绘制/保存IplImage图像,也包含了同时支持WINCE/WIN32的第三方BMP操作类库----DIBSectionCE类。接下来就贴出部分操作代码:

  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,地址:https://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,地址:https://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,地址:https://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,地址:https://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的运算部分用上这些手机的专用运算指令,这样可以大大提高运算速度。

 



  
上一篇:如何在FPGA中实现Viterbi译码
下一篇:非隔离型反激LED驱动器

免责声明: 凡注明来源本网的所有作品,均为本网合法拥有版权或有权使用的作品,欢迎转载,注明出处。非本网作品均来自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

相关技术资料