IplImage* CCameraDS::QueryFrame() { …… m_pSampleGrabber->GetCurrentBuffer(&m_nBufferSize, (long*) m_pFrame->imageData); cvFlip(m_pFrame); return m_pFrame; }
演示程序CVMFC的图像输入输出采用OpenCV的cvLoadImage与cvSaveImage函数实现,而显示采用Windows API中的 StretchDIBits函数。为了能正常工作,图像读入后需作垂直镜像,图像存盘前也需作垂直镜像。也就是说,内存中存放的是经过垂直镜像的OpenCV位图。同样,因为结构相同,它也是DIB位图的像素数据。
BOOL CCVMFCDoc::Load(IplImage** pp,LPCTSTR csFileName) { IplImage* pImg=NULL; pImg = cvLoadImage(csFileName,-1); // 读图像文件 if (!pImg) return(false); cvFlip(pImg); // 使与 DIB 像素结构一致 if (*pp) cvReleaseImage(pp); (*pp)=pImg; m_Display=0; return(true); } BOOL CCVMFCDoc::Save(LPCTSTR csFileName,IplImage* pImg) { int bl; cvFlip(pImg); // 恢复原 OpenCV 位图结构 bl=cvSaveImage(csFileName,pImg); // 图像存盘 return(bl); }
对于大多数的图像处理算法来说位图的镜像与否没有什么影响。但是,对于某些OpenCV函数,例如涉及旋转方向以及需要往IplImage结构的位图上绘制图形、显示文字时就会使位置出错。这时就需要与存盘时一样先作垂直镜像,旋转角度反向,操作结束返回Windows视图显示处理结果时再转换回来。
驱动模式与人机交互
众所周知,DOS操作系统采用过程驱动与文本模式,Windows操作系统采用事件驱动与图形模式,它们分别使用键盘与鼠标器作为主要输入工具。OpenCV编程环境基于DOS操作系统,因此显示图像需要调用cvNamedWindow函数建立专门的窗口,然后调用cvShowImage函数进行显示。画面的保持则使用cvWaitKey(0)语句,或使用内含cvWaitKey语句的死循环来实现。为了避免出现死机故障,出现OpenCV函数所开窗口时,务必使用ESCAPE键关闭窗口并退出。注意:菜单中带 (ESC) 字样的命令必须使用ESCAPE键退出。
同时,OpenCV编程环境人机交互的功能有限,只有鼠标、键盘与滑动条。stretchdibits其中,鼠标与滑动条属于事件驱动,而键盘属于过程驱动。stretchdibits由于没有菜单功能,只能使用键盘命令控制程序走向并等待键盘输入选择不同功能。
在驱动模式方面为了便于比较,提供了两个[点集凸包]命令,一个采用过程驱动,另一个采用事件驱动,不妨比较具体功能及其实现的程序。
程序移植例
演示程序CVMFC中待处理图像与处理结果都放在工作位图workImg中。同时,工作位图workImg也是窗口画面显示的内容。所以,处理程序中仅源图像的获取与结果图像的显示与OpenCV中的程序有所不同,中间处理部分可以完全相同,现以《学习OpenCV》一书中的例2-6为例来作修改说明。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-30453-4.html
讲的很准确