在MFC中使用OpenCV的方法.docx

上传人:b****4 文档编号:4594514 上传时间:2022-12-07 格式:DOCX 页数:22 大小:34.97KB
下载 相关 举报
在MFC中使用OpenCV的方法.docx_第1页
第1页 / 共22页
在MFC中使用OpenCV的方法.docx_第2页
第2页 / 共22页
在MFC中使用OpenCV的方法.docx_第3页
第3页 / 共22页
在MFC中使用OpenCV的方法.docx_第4页
第4页 / 共22页
在MFC中使用OpenCV的方法.docx_第5页
第5页 / 共22页
点击查看更多>>
下载资源
资源描述

在MFC中使用OpenCV的方法.docx

《在MFC中使用OpenCV的方法.docx》由会员分享,可在线阅读,更多相关《在MFC中使用OpenCV的方法.docx(22页珍藏版)》请在冰豆网上搜索。

在MFC中使用OpenCV的方法.docx

在MFC中使用OpenCV的方法

在MFC中使用OpenCV的方法

 

 

————————————————————————————————作者:

————————————————————————————————日期:

 

在MFC中使用OpenCV

演示程序CVMFC

本程序是在MFC中使用OpenCV的演示程序,由3部分组成.

一、Windows下用MFC编制的程序框架

采用设备无关位图DIB实现Windows多文档模式下图像的显示,实现显示的关键函数StretchDIBits的原型如下:

intStretchDIBits(

HDChdc,//显示设备句柄

intXDest,//目标矩形区域左上角X坐标

intYDest,//目标矩形区域左上角Y坐标

intnDestWidth,//目标矩形区域宽度

intnDestHeight,//目标矩形区域高度

intXSrc,//源矩形区域左上角X坐标

intYSrc,//源矩形区域左上角Y坐标

intnSrcWidth,//源矩形区域宽度

intnSrcHeight,//源矩形区域高度

CONSTVOID*lpBits,//位图的像素存放首地址

CONSTBITMAPINFO*lpBitsInfo,//位图信息存放地址

UINTiUsage,//位图中的颜色类型,RGB模式用DIB_RGB_COLORS

DWORDdwRop//像素操作码,简单复制用SRCCOPY

);

由于OpenCV中的位图结构中的像素数据与DIB中的像素具有相同的存储结构,见表1中的像素部分。

所以,只要为它构造一个DIB的位图信息就可以调用API函数StretchDIBits实现它的显示了。

表1DIB位图参数与IplImage结构参数

参数

DIB(MFC)

IplImage(OpenCV)

宽度

biWidth

width

高度

biHeight

height

像素位数

biBitCount(1,4,8,16,24,32)=depth*nChannels

depth(8,16,32,64)

通道数

———

nChannels(1,2,3,4)

(单通道位图)调色板单元数

2biBitCount

(2,16,256)

二值图像显示为灰阶图像

256色彩色图像显示为真彩色图像

位图坐标原点

底-左

origin(0顶-左,1底-左)

像素分量存放方式

交叉存取(按像素为单位存放)

0交叉存取,1位平面方式

对齐方式(行像素数据凑整)

4字节对齐

4字节对齐或8字节对齐

每行字节数

(biWidth*biBitCount+31)/32*4

widthStep

像素字节数

((biWidth*biBitCount+31)/32*4)*biHeight

imageSize

像素存放地址

BYTE*pBits

char*imageData

感兴趣区域

-—-

roi

 

表中正体字母部分表示相同的参数,粗体字母表示参数部分相同时的交集,斜体加下划线表示结构特有的参数。

位图的宽度、高度、像素存放首地址、每行字节数、像素总字节数等5个参数在两种结构中相同。

像素位数、通道数、坐标原点位置、像素分量存放方式、对齐方式等5个参数在两种结构中部分相同,使用时可以取其交集,表中用粗体字表示。

有2个参数是两种位图各自独有的,感兴趣区域为IplImage结构所独有,调色板单元为DIB所独有.

从表1中可以看出,除了高精度图像(位深度16,32,64)外,这两种位图结构在图像处理的绝大部分应用中可以通用。

从以上比较中也可看出,IplImage结构适用于高精度处理,并且可以限制处理的区域;而DIB适用于Windows图形操作,并且可以存储低位数图像文件,如每像素一位的二值图像与像素8位的索引图像等。

另一种实现MFC的方法是采用CvvImage类,它有一个特点,就是其成员函数DrawToHDC可将位图全部经缩放后显示到窗口中。

这样,虽然能够察看全图,但当位图与窗口的长宽比不一致时会造成图像失真。

而采用DIB实现的显示比例可选择为1:

1,图像显示没有经过缩放,显示画面按窗口大小进行裁剪,并可使用滑动条选择显示部位,这比较符合图像采集与处理的使用习惯。

二、调用OpenCV函数实现处理

使用OpenCV函数处理图像在MFC环境下显示,实现功能为图像平滑、图像缩小与Canny边缘检测.根据《学习OpenCV》一书第2章的3个例子(例2—4,2—5,2—6)改编而成。

例2-4与2-5使用例图fruits.jpg,例2—6使用例图lena.jpg。

还增加了若干图像处理常用功能,详见下面表2菜单结构列表。

视频播放也用OpenCV函数实现,根据《OpenCV教程(基础篇)》中第3章的例3-5改编而成,用的是highgui函数,测试视频文件为globe.avi.

例图文件都在image\目录下。

三、用DirectShow编制的视频采集程序

采用DirectShow实现视频采集,其优点是支持高分辨率图像采集,最高分辨率由所用的摄像头决定,如罗技130万像素USB摄像头C300最高分辨率可达1280*1024,在MPEG模式下采集速度为每秒15帧.使用时CPU的时间占用率在15~30%之间。

通过多图像平均可以采集得到质量不错的图像,经过4幅图像平均采集所得图像的信噪比可提高一倍。

由于需要连续采集多帧图像,约需0.25秒,故适宜采集静态或缓慢移动对象的图像.

视频采集功能调用OpenCVChina网站下载的软件camerads中的函数实现。

主要内容

下面列出stdafx.h尾部集中的几个头文件,程序结构由此可见一斑.

#include"CVMFC。

h”//窗口管理

#include"cv.h”//OpenCV头文件

#include”highgui。

h”

#include"CameraDS。

h"//DirectShow(基于OpenCV)

#include”CVDSCap.h"//视频采集接口

CVMFC的菜单结构

程序分为文件、点处理、邻域处理、二值图像处理、形态学处理、综合处理例与视频采集播放等七、八个菜单条共70个功能,近半数功能由参考文献上的程序修改而成,为了便于找到相应参考材料进行对照,在程序中附上了它们的出处。

程序的菜单结构见表2,其中列出了演示程序的大多数功能.

表2CVMFC菜单结构

文件

点处理

邻域处理

二值图像处理

形态学处理

综合处理例

视频采集播放

打开图像

彩色变灰阶

邻域平均

选择阈值

腐蚀

图像缩小

启动摄像头

恢复图像

图像反相

Gauss滤波

自适应阈值法

膨胀

径向梯度

打开AVI文件

关闭当前窗口

垂直镜像

中值滤波

全局阈值法

开运算

Canny算法

视频解冻

保存当前位图

水平镜像

Sobel算法

外接矩形

闭运算

种子填充

视频冻结

最近文件

180度旋转

Laplace算法

最小面积矩形

形态学梯度

金字塔图像分割

多图像平均

恢复原始图像

30度旋转

点集凸包

顶帽变换

椭圆曲线拟合

关闭视频

当前画面存盘

亮度变换

区域凸包

波谷检测

Snake原理

选择分辨率

退出

图像直方图

轮廓跟踪

分水岭原理

动态边缘检测

直方图均衡化

距离变换

角点检测

L_K光流跟踪

典型例图

各类功能都有一定的特异性,为了突出各功能的实效,建议初次使用时先用表3中列出的例图进行处理。

这些例图在程序包的Image\目录下,表中也对一些功能作了简要的说明。

表3功能的典型例图

功能名称

典型例图

简要说明

外接矩形(BoundingRect)

ExampleL.bmp、

ExampleQ。

bmp

仅适用于单连通区域,

不能处理多连通区域与孔边界

最小面积矩形(MinAreaRect2)

区域凸包(ConvexHull2)

轮廓跟踪(FindContours)

ExampleC。

bmp、

SteelBar.bmp、pic3。

png

适用各类二值图像,使用范围较宽

图像反相后也可进行处理,得到不同结果

距离变换(DistTransform)

顶帽变换

ExampleD.bmp

为灰值形态学运算,波谷检测又称黑顶帽变换

图像反相后处理与另一方法直接处理等价

波谷检测

图像缩小

lena.jpg、fruits.jpg

径向梯度

lena.jpg、fruits.jpg

Canny算法

lena.jpg

Hough变换(直线)(HoughLines2)

pic1.png

Hough变换(圆)(HoughCircles)

stuff.jpg

平行四边形检测

pic1.png、pic2.png

种子填充(FloodFill)

fruits。

jpg

鼠标选种子,命令键C、M、R、S、F、G、8、4,ESC

金字塔图像分割(PyrSegmentation)

fruits.jpg

滑动条调节参数,任意键退出

椭圆曲线拟合(FitEllipse)

stuff。

jpg、rice.tif

滑动条调节参数,任意键退出

Snake原理(SnakeImage)

ring。

bmp、square。

bmp

滑动条调节参数,ESC退出

分水岭原理(Watershed)

fruits.jpg

鼠标绘制区域标记,R清除,W或Enter分割,ESC退出

角点检测(GoodFeaturesToTrack)

chessboard.jpg

滑动条调节参数,鼠标确定检测范围,任意键退出

人脸检测(HaarDetectObjects)

lena。

jpg

打开AVI文件

globe.avi

不能播放用Mpeg压缩的视频文件

L_K算法光流跟踪

鼠标选择跟踪点,命令键R、C、N,ESC退出

程序结构

程序采用VC++多文档结构,图像的存放与处理则采用OpenCV的结构与函数,图像的显示采用位图信息m_lpBmi实现,为了便于管理对m_lpBmi的操作集中在OnDraw程序中。

待显示位图结构发生改变时用m_dibFlag标志激发m_lpBmi的刷新。

除了文件结构与图像显示外,其余部分基本上是OpenCV程序。

位图数据:

CVMFCDoc中pImg(读入图像文件所得原始位图)

CVMFCView中workImg(工作位图)、saveImg(备份位图)

m_lpBmi(工作位图的位图信息)

CVDSCap中m_Frame(视频采集所得位图)

视图的显示:

voidCCVMFC0View:

:

OnDraw(CDC*pDC)

{

CCVMFCDoc*pDoc=GetDocument();

ASSERT_VALID(pDoc);

//TODO:

adddrawcodefornativedatahere

if(pDoc->pImg!

=NULL){//有磁盘输入图像

CSizesizeTotal;

sizeTotal=CSize(pDoc->pImg-〉width,pDoc—〉pImg-〉height);

SetScrollSizes(MM_TEXT,sizeTotal);

if(pDoc-〉m_Display==0){//输入图像尚未显示

newCloneImage(pDoc—>pImg,&saveImg);//复制到备份位图

m_dibFlag=newCloneImage(saveImg,&workImg);//复制到工作位图

m_ImageType=pDoc-〉pImg->nChannels;//设置标志

m_SaveFlag=m_ImageType;

pDoc—>m_Display=1;

}

}

if(m_dibFlag){//刷新DIB位图信息

if(m_lpBmi)

free(m_lpBmi);

m_lpBmi=CtreateMapInfo(workImg,m_dibFlag);

m_dibFlag=0;

}

if(workImg){//刷新窗口画面

StretchDIBits(pDC-〉m_hDC,0,0,workImg—>width,workImg->height,

0,0,workImg->width,workImg—〉height,

workImg-〉imageData,m_lpBmi,DIB_RGB_COLORS,SRCCOPY);

CCVMFC模块中增加了4个函数,即CtreateMapInfo、imageType、imageClone与imageReplace.CtreateMapInfo函数用于建立工作位图workImg的位图信息m_lpBmi,其特点是可以为单通道位图设置两种调色板,即黑白灰阶调色板与VGA默认调色板。

因为在OpenCV中二值图像显示为灰阶图像,imageType函数可从单通道位图中识别出二值位图。

ImageClone与imageReplace函数使用OpenCV函数实现位图的复制,自动释放老的指针所指向的存储单元以防止内存泄漏,同时返回的m_dibFlag标志可以用于激发刷新工作位图workImg的位图信息m_lpBmi.imageReplace与ImageClone相似,但不建立新位图,只用输入位图替换输出位图.

LPBITMAPINFOCtreateMapInfo(IplImage*workImg,intflag)

{//建立位图信息

BITMAPINFOHEADERBIH={40,1,1,1,8,0,0,0,0,0,0};

LPBITMAPINFOlpBmi;

intwid,hei,bits,colors,i;

RGBQUADColorTab[256];

wid=workImg—〉width;

hei=workImg-〉height;

bits=workImg—>depth*workImg-〉nChannels;

if(bits〉8)colors=0;

elsecolors=1〈

lpBmi=(LPBITMAPINFO)malloc(40+4*colors);

BIH.biWidth=wid;

BIH。

biHeight=hei;

BIH。

biBitCount=(BYTE)bits;

memcpy(lpBmi,&BIH,40);//复制位图信息头

if(bits==8){//256色位图

if(flag==1){//设置灰阶调色板

for(i=0;i〈256;i++){

ColorTab[i]。

rgbRed=ColorTab[i].rgbGreen=ColorTab[i].rgbBlue=(BYTE)i;

memcpy(lpBmi->bmiColors,ColorTab,1024);

}

elseif(flag==2){//设置默认调色板

memcpy(lpBmi->bmiColors,VgaDefPal,1024);

}

return(lpBmi);

}

intimageType(IplImage*p)//识别二值图像

{

inti,j,k,bpl,n,pg[256];

BYTE*buf;

k=p—〉nChannels;

if(k==1){//检查二值图像

for(i=0;i〈256;i++)pg[i]=0;

buf=(BYTE*)p-〉imageData;bpl=p—〉widthStep;

for(i=0;iheight;i++){

for(j=0;j

buf+=bpl;

for(i=0,n=0;i〈256;i++)

if(pg[i])n++;

if(n==2)k=—1;//二值图像

}

return(k);

}

intimageClone(IplImage*pi,IplImage**ppo)//复制IplImage位图(OpenCV)

{

if(*ppo)

cvReleaseImage(ppo);//释放原来位图

(*ppo)=cvCloneImage(pi);//复制新位图

return

(1);

}

intimageReplace(IplImage*pi,IplImage**ppo)//替换位图(OpenCV)

{

if(*ppo)

cvReleaseImage(ppo);//释放原来位图

(*ppo)=pi;//位图换名

return

(1);

像素数据地址的类型

从表1中可见,在OpenCV中像素存放地址imageData为char*类型.因此,在图像处理时就必须转换为BYTE*类型才可以使用。

例如,在上面的imageType函数中统计图像直方图非使用这种转换不可。

另外,图像类型参数m_ImageType用于菜单功能的使能(Enable),程序中用到了4种不同类型的图像,即真彩色图像、灰阶图像、二值图像与伪彩色图像,它们的m_ImageType值分别定义为3,1,-1,—2。

双操作数函数的参数顺序

本程序是WindowsAPI系统与OpenCV两种体系函数的混合使用,而它们的函数参数的书写习惯是不同的,极容易引起混淆.这里作一简要说明,请看下面例子:

目的参数Dest←源参数Src

C:

memcpy(pDest,pSrc,size);

WindowsAPI:

BitBlt(hDestDC,0,0,wid,hei,hSrcDC,0,0,SRCCOPY);

VC++:

pDestDC—>BitBlt(0,0,p—>wid,p—>hei,pSrcDC,0,0,SRCCOPY);

源参数Src→目的参数Dest

OpenCV:

cvCvtColor(pSrcImg,pDestcImg,CV_BGR2GRAY);

cvSmooth(pSrcImg,pDestcImg,CV_GAUSSIAN,3,0,0);

本程序中除了OpenCV函数采用后一书写形式外,其他函数都采用前一书写形式,千万注意不能混淆。

OpenCV函数很容易辨认,都以前缀cv-开头,如cvCvtColor、cvSmooth。

新增函数ImageClone与imageReplace因为调用OpenCV函数,故也采用后一书写形式.

图像处理程序的修改

本程序中待处理图像放在工作位图workImg中,处理结果也放在工作位图workImg中。

同时,工作位图workImg也是窗口画面显示的内容。

所以,处理程序中仅源图像的获取与结果图像的显示与OpenCV程序有所不同,中间处理部分可以完全相同,现以《学习OpenCV》一书中的例2—6为例来作修改说明。

《学习OpenCV》例2—6原始程序:

intmain(intargc,char*argv[])//Canny边缘检测

IplImage*pImage=NULL;

IplImage*pImgCanny=NULL;

IplImage*pImg8u=NULL;

IplImage*pImg8uSmooth=NULL;

pImage=cvLoadImage(argv[1]);//输入待处理图像

if(!

pImage)return0;

cvNamedWindow("Example6—in",CV_WINDOW_AUTOSIZE);

cvShowImage("Example6—in",pImage);

pImg8u=cvCreateImage(cvGetSize(pImage),IPL_DEPTH_8U,1);

pImg8uSmooth=cvCreateImage(cvGetSize(pImage),IPL_DEPTH_8U,1);

pImgCanny=cvCreateImage(cvGetSize(pImage),IPL_DEPTH_8U,1);

cvCvtColor(pImage,pImg8u,CV_BGR2GRAY);

cvSmooth(pImg8u,pImg8uSmooth,CV_GAUSSIAN,3,0,0);

cvCanny(pImg8uSmooth,pImgCanny,100,200,3);

cvNamedWindow("Example6-out”,CV_WINDOW_AUTOSIZE);

cvShowImage("Example6—out",pImgCanny);//显示处理结果

cvWaitKey(0);

cvReleaseImage(&pImage);

cvReleaseImage(&pImg8u);

cvReleaseImage(&pImg8uSmooth);

cvReleaseImage(&pImgCanny);

cvDestroyWindow(”Example6-in”);

cvDestroyWindow(”Example6-out”);

return0;

在CVMFC程序中修改为:

voidCCVMFC0View:

:

OnCannyBorddetec()//Canny边缘检测

{//根据《学习OpenCV》例2-6改编

//定义工作位图

IplImage*pImage;

IplImage*pImg8u=NULL;

IplImage*pImg8uSmooth=NULL;

IplImage*pImgCanny=NULL;

//**输入待处理图像**//修改部分1

pImage=workImg;

//建立辅助位图

pImg8u=cvCreateImage(cvGetSize(pImage),IPL_DEPTH_8U,1);

pImg8uSmooth=cvCreateImage(cvGetSize(pImage),IPL_DEPTH_8U,1);

pImgCanny=cvCreateImage(cvGetSize(pImage),IPL_DEPTH_8U,1);

//图像处理

cvCvtColor(pImage,pImg8u,CV_BGR2GRAY);

cvSmooth(pImg8u,pImg8uSmooth,CV_GAUSSIAN,3,0,0);

cvCanny(pImg8uSmooth,pImgCanny,10

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 初中教育 > 语文

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1