多媒体3.docx
- 文档编号:26585145
- 上传时间:2023-06-20
- 格式:DOCX
- 页数:32
- 大小:464.49KB
多媒体3.docx
《多媒体3.docx》由会员分享,可在线阅读,更多相关《多媒体3.docx(32页珍藏版)》请在冰豆网上搜索。
多媒体3
在《OpenCV教程-基础篇》的2.8节中,所创建的MFC图像显示是直接放在对话框面板的左上角的,感觉不大美观;《MFC中快速应用OpenCV》则是介绍用SDI(单文档界面)来显示图像,《Astep-by-stepguidetotheuseofMicrosoftVisualC++andtheIntelOpenCVlibrary》使用VS2005来进行图像和视频的读取和处理,但是其图像和视频的显示界面不是在对话框里面的,而是新建一个窗口来做。
所以下面我们就来看看怎么在对话框里使用Picture控件来显示和处理图像。
一、创建MFC
首先创建一个MFC对话框应用程序(Dialog-basedApplication)如下:
在VS2005和2008里,我们可以用一个Solution来组合几个Project(每个Project基本上只包含一个Program),当我们要构建一个多Program的应用时(例如一个客户端程序加一个服务器应用程序),利用Solution可以将这些Projects组合起来、并且共享文件和函数库。
通常需要为Solution创建一个主路径,其中包含了所有Projects的路径。
不过在这篇文章里,我们只构建一个简单的Project,所以在创建MFC的NewProject对话框里,不用勾选“Createdirectoryforsolution”这个选项。
点击OK--Next进入下一步,在这里我们创建一个Dialog-basedApplication,大部分选项按默认设置就行,不过最下面的“UseUnicodelibraries”最好去掉。
如果勾选了这个选项,程序代码就会使用16bit的Unicode字符集来编码,但是很多函数虽然使用char*(ASCIIstings)类型字符,而将字符串从Unicode转换到ASCII是非常麻烦的。
使用Unicode在编译时可能会遇到下列错误:
cannotconvertparameter1from'CString'to'constchar*'
cannotconvertfrom'constchar[11]'to'LPCWSTR'
这意味着在Unicode和Multi-byte字符串的转换中出现了问题。
在上一篇学习笔记中,就提到“成员函数LoadBMP其输入参数类型应为constchar*”,那应该只是一个治标的方法,这里的去掉“UseUnicodelibraries”选项,才是治本之道。
往后的几步设置,可以根据自己的需要来操作,我的设置如下:
二、编写代码
在ResourceView面板->mymfc(工程名称)->mymfc.rc->Dialog双击IDD_MYMFC_DIALOG,可以看到一个初始的GUI界面,往里面添加两个Button和一个Picture控件,如下:
选中单个控件、右击选择属性(Properties),可以看到控件的ID号,这个号可以自行编辑,例如Picture控件的ID号我设置为 IDC_ShowImg,这个ID号在后面的图像显示函数中要用到。
首先在项目属性中加载lib文件:
菜单Project->Properties->ConfigurationProperties->Linker–>Input->additionaldependencies中加入cxcore200.libcv200.libhighgui200.lib。
然后在mymfc.h的#include"resource.h" 下加入如下代码:
#include"cv.h"
#include"highgui.h"
#defineIMAGE_WIDTH256
#defineIMAGE_HEIGHT256
#defineIMAGE_CHANNELS3
在ClassView面板右击CmymfcDlg,选择Add–>AddVariable,添加一个IplImage*类型的变量TheImage;再点击CmymfcDlg,在下面窗口的列表中双击OnInitDialog,在“//TODO:
Addextrainitializationhere”下面添加TheImage的初始化代码:
CvSizeImgSize;
ImgSize.height=IMAGE_HEIGHT;
ImgSize.width=IMAGE_WIDTH;
TheImage=cvCreateImage(ImgSize,IPL_DEPTH_8U,IMAGE_CHANNELS);
然后双击OnPaint,在if(IsIconic())…的else里添加以下代码,用来重绘窗口:
CDialog:
:
OnPaint();//重绘对话框
CDialog:
:
UpdateWindow();//更新windows窗口,如果无这步调用,图片显示还会出现问题
ShowImage(TheImage,IDC_ShowImg);//重绘图片函数
接着在CmymfcApp下面的成员列表中双击InitInstance,在两个“//TODO:
Placecodeheretohandlewhenthedialogis…”下面添加:
cvReleaseImage(&dlg.TheImage);
即按下“OK”或“Cancel”时,释放TheImage占用的内存。
接下来就是写读取和处理图片的功能函数了。
回到mymfc的GUI编辑界面中,右击按钮ReadImg,选择AddEventHandler,建立按钮点击的消息响应程序:
句柄名设置为OnBnClickedReadimg,主要的响应操作包括弹出对话框选择图片文件、读入图片文件、对图片统一缩放至256*256的大小、显示图像,代码如下:
//TODO:
Addyourcontrolnotificationhandlercodehere
CFileDialogdlg(
TRUE,_T("*.bmp"),NULL,
OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST|OFN_HIDEREADONLY,
_T("imagefiles(*.bmp;*.jpg)|*.bmp;*.jpg|AllFiles(*.*)|*.*||"),NULL
);//选项图片的约定
dlg.m_ofn.lpstrTitle=_T("OpenImage");//打开文件对话框的标题名
if(dlg.DoModal()!
=IDOK)//判断是否获得图片
return;
CStringmPath=dlg.GetPathName();//获取图片路径
IplImage*ipl=cvLoadImage(mPath,1);//读取图片、缓存到一个局部变量ipl中
if(!
ipl)//判断是否成功载入图片
return;
if(TheImage)//对上一幅显示的图片数据清零
cvZero(TheImage);
ResizeImage(ipl);//对读入的图片进行缩放,使其宽或高最大值者刚好等于256,再复制到TheImage中
ShowImage(TheImage,IDC_ShowImg);//调用显示图片函数
cvReleaseImage(&ipl);//释放ipl占用的内存
其中包含了两个新的成员函数ResizeImage和ShowImage,前者的作用是对读入的不同大小的图像进行缩放,再通过设置ROI的方式将图像存入256*256的TheImage中;后者是将图像TheImage显示到图片显示控件IDC_ShouImg窗口的正中部位。
为了实现这两个功能,首先在ClassView面板右击CmymfcDlg,选择Add–>AddFunction,创建两个函数:
voidShowImage(IplImage*img,UINTID)和voidResizeImage(IplImage*img)。
以下是这两个函数的实现代码:
voidCmymfcDlg:
:
ResizeImage(IplImage*img)
{
//读取图片的宽和高
intw=img->width;
inth=img->height;
//找出宽和高中的较大值者
intmax=(w>h)?
w:
h;
//计算将图片缩放到TheImage区域所需的比例因子
floatscale=(float)((float)max/256.0f);
//缩放后图片的宽和高
intnw=(int)(w/scale);
intnh=(int)(h/scale);
//为了将缩放后的图片存入TheImage的正中部位,需计算图片在TheImage左上角的期望坐标值
inttlx=(nw>nh)?
0:
(int)(256-nw)/2;
inttly=(nw>nh)?
(int)(256-nh)/2:
0;
//设置TheImage的ROI区域,用来存入图片img
cvSetImageROI(TheImage,cvRect(tlx,tly,nw,nh));
//对图片img进行缩放,并存入到TheImage中
cvResize(img,TheImage);
//重置TheImage的ROI准备读入下一幅图片
cvResetImageROI(TheImage);
}
voidCmymfcDlg:
:
ShowImage(IplImage*img,UINTID)//ID是PictureControl控件的ID号
{
CDC*pDC=GetDlgItem(ID)->GetDC();//获得显示控件的DC
HDChDC=pDC->GetSafeHdc();//获取HDC(设备句柄)来进行绘图操作
CRectrect;
GetDlgItem(ID)->GetClientRect(&rect);
intrw=rect.right-rect.left;//求出图片控件的宽和高
intrh=rect.bottom-rect.top;
intiw=img->width;//读取图片的宽和高
intih=img->height;
inttx=(int)(rw-iw)/2;//使图片的显示位置正好在控件的正中
intty=(int)(rh-ih)/2;
SetRect(rect,tx,ty,tx+iw,ty+ih);
CvvImagecimg;
cimg.CopyOf(img);//复制图片
cimg.DrawToHDC(hDC,&rect);//将图片绘制到显示控件的指定区域内
ReleaseDC(pDC);
}
函数ResizeImage是参考了学习笔记(5)中单窗口显示多幅图像的函数cvShowMultiImages修改而成的,函数ShowImage则是参考了帖子《OpenCV如何把图像显示到MFC的picture控件上》的代码,另外下面几个帖子也可以参考:
1、《MFCpicturecontrol畫框的問題》
2、《MFCpicturecontrol控件实现(隐藏)文字显示》
3、《MFC在PictureControl中显示图片(jpg)遇到的问题》
4、《vc怎样在picturecontrol中显示jpg,jif,bmp格式图象》
5、《使用PictureControl显示BMP图片》
最后是要对读入的图像做简单的Canny边缘处理,为此,建立一个按钮EdgeDetect,相应的响应代码如下:
voidCmymfcDlg:
:
OnBnClickedEdgedetect()
{
//TODO:
Addyourcontrolnotificationhandlercodehere
IplImage*gray=0,*edge=0;
gray=cvCreateImage(cvSize(IMAGE_WIDTH,IMAGE_HEIGHT),IPL_DEPTH_8U,1);
edge=cvCreateImage(cvSize(IMAGE_WIDTH,IMAGE_HEIGHT),IPL_DEPTH_8U,1);
cvCvtColor(TheImage,gray,CV_BGR2GRAY);
cvCanny(gray,edge,30,100,3);
cvCvtColor(edge,TheImage,CV_GRAY2BGR);
ShowImage(TheImage,IDC_ShowImg);//调用显示图片函数
cvReleaseImage(&gray);
cvReleaseImage(&edge);
}
这里主要是参考了《OpenCV教程-基础篇》P33的代码,不过并没有像书中那样创建新的MyIplClass类来进行图像的读取和处理操作。
我觉得这篇文章中直接对TheImage进行处理可能不大妥当,按照教程那样新建一个类来处理才是比较稳妥吧。
这里涉及到函数返回对象实例的过程、深拷贝和浅拷贝、拷贝构造、动态内存的使用、opencv相关接口的代码等方面,以后还要进一步深入学习和理解!
最后我们还可以在ResourceView面板->mymfc(工程名称)->mymfc.rc->Version中修改程序的产品版本、名称等信息。
来看看程序生成后的效果:
分享到:
上一篇:
OpenCV学习笔记(8)VS2008MFC下使用OpenCV2.0进行简单图像处理
下一篇:
压缩传感的系列论文和点评
查看评论
44楼 sheerwang 2012-05-1011:
06发表 [回复]
感谢一下啦,那个资源视图就打不开了。
。
43楼 sheerwang 2012-05-1011:
05发表 [回复]
为啥我的工程文件转换成vs2010后就打不开了。
。
42楼 programmer2018 2012-03-3021:
10发表 [回复]
代码下载下来了,运行似乎有点问题,慢慢调吧。
楼主代码很好很强大!
41楼 fireflypd 2012-03-2813:
01发表 [回复]
邹博士,你好!
我运行了一下你的有摄像头的MFC程序,编译通过,并出现了界面。
但点摄像头run的时候出现了“cannotopencamera”的提示,始终找不到原因,不知道是怎么回事。
。
。
希望能得到你的指点!
十分感谢!
注:
我连的是CCD相机,通过图像采集卡和电脑相连的
40楼 a254060992 2012-03-2617:
26发表 [回复]
我的出现了这种unresolvedexternalsymbol_cvCreateImage
testPicControlDlg.obj:
errorLNK2001:
unresolvedexternalsymbol_cvReleaseImage
testPicControlDlg.obj:
errorLNK2001:
unresolvedexternalsymbol_cvSetZero
你有做好的能给我发一份吗512868516@
39楼 yufentang 2012-03-1620:
20发表 [回复]
您好,我在添加voidShowImage(IplImage*img,UINTID)和voidResizeImage(IplImage*img)这两个函数参数的时候系统提示“无效或重复的参数名”,这是什么意思?
怎么解决?
还有,函数名和参数名的返回值是什么类型呢?
38楼 zhifengjing 2012-03-1412:
30发表 [回复]
你好,能不能写一篇介绍怎么显示视频的文章
37楼 forester_2008 2012-01-0314:
53发表 [回复]
楼主是大牛啊,有木有QQ啊。
希望交流下。
36楼 hujilin1229 2011-10-1719:
24发表 [回复]
你好,你的笔记对我一个新手来说非常有用,这两天我就在琢磨你这个例子,并照样画葫芦的进行了模拟。
图片和视频那块正常了,可是在摄像头读取那块:
1.我自己模拟的那个程序,不过出现的问题是我的COMOBOX的下拉菜单中没有摄像头的名字,调试了你附的程序,是有的。
可是我貌似好像已经跟你的是一摸一样了。
不知道问题出在哪里,请指教!
2.问题应该出现在这块:
__time64_trawtime;
structtm*timeinfo;
errno_terr;
//Gettimeas64-bitinteger
_time64(&rawtime);
//Converttolocaltime
err=_localtime64_s(timeinfo,&rawtime);
//ConverttoanASCIIrepresentation
asctime_s(timestr,26,timeinfo);
CStringstrTime;
strTime.Format("%s",timestr);
strTime.Replace("\n","");
rawtime=time(NULL);
timeinfo=localtime(&rawtime);
char*p=asctime(timeinfo);
程序上,你附上的代码,在第2行使用的是structtmtimeinfo;即就一个结构体,可是但用这个的时候,在timeinfo=localtime(&rawtime)时编译会报错。
所以我就改成了structtm*timeinfo;后面的代码也有些改动。
但是这个编译能通过了,能生成界面了,可是Run-TimeCheckFailure#3-Thevariable'timeinfo'isbeingusedwithoutbeinginitialized.出现这个错误,导致摄像头开启后就程序中断了。
以上两个问题还请不吝赐教!
谢谢
35楼 jxusthusiwen 2011-09-1418:
53发表 [回复]
你好,我按照你所写得步骤,出现了一个常见的错误:
errorC2664:
“cvLoadImage”:
不能将参数1从“CString”转换为“constchar*”
1>没有可用于执行该转换的用户定义的转换运算符,或者无法调用该运算符
怎么解决呀?
谢谢你的回复。
Re:
jxusthusiwen 2011-09-1419:
14发表 [回复]
回复jxusthusiwen:
自己解决了,谢谢lz,很好的教程呀
Re:
jxusthusiwen 2011-09-1418:
55发表 [回复]
回复jxusthusiwen:
出错代码:
IplImage*ipl=cvLoadImage(mPath,1);
Re:
xiaojian0302 2011-11-2410:
51发表 [回复]
回复jxusthusiwen:
请问您这个问题怎么解决的呀?
谢谢
Re:
xiaojian0302 2011-11-2410:
58发表 [回复]
回复xiaojian0302:
O(∩_∩)O哈哈~搞定!
很好
34楼 nwpu304 2011-09-0612:
04发表 [回复]
看了楼主的日志,真的很不错,但是我查询了网上的很多资料,还没有讲到OPENCV2.3和VS2008中利用picture控件显示图像和视频的教程,我现在使用的方法还是利用MFC中缓冲的方法,喜欢楼主能研究一下,cvvimage的东西貌似是在opencv2.3中就没有了,怎么解决这个问题啊?
33楼 huxiongge 2011-03-1521:
57发表 [回复]
好资源,下载来学习学习
32楼 sussii 2011-01-1513:
17发表 [回复]
请问,为什么我在mfc里面按照《MFC中快速应用OpenCV》里面配置openCV,在Doc的函数里面键入CImagem_image后CImage下面有波浪线,提示说“CImage”isambiguous.编译也通不过。
我的是vs2010+openCV2.1
请问这是怎么一回事呢?
31楼 paipai880429 2011-01-0201:
53发表 [回复]
请问运行代码时说丢失cv.dll文件咋办呀?
30楼 yangnan2011 2010-12-3121:
53发表 [回复]
你好我想请教一下利用picture读取摄像头视频时,我现在能实现读视频并显示,但鼠标在窗口上点击时没反应,就是窗口上的按钮点击不了,看了您的视频的例子程序还是不知道原因所在不知道是在窗口重绘时的问题还是别的请您给点思路多谢了
Re:
chenyusiyuan 2011-01-0113:
29发表 [回复]
应该是你没有用cvNamedWindow创建视频窗口、直接把图像放大Picture控件上显示所造成的,OpenCV的cvWaitKey只有在cvNamedWindow创建了窗口之后才起作用,在循环中等待键盘/鼠标输入事件。
直接把图像放Picture控件的话,程序就会一直在循环里转,没有空出时间来检查鼠标输入,所以鼠标在窗口上点击是没有反应的。
可以考虑用Timer定时器来取代cvWaitKey。
Re:
yangnan2011 2010-12-3121:
55发表 [回复]
回复yangnan2011:
您好我补充一句是不是多线程的问题如果是要在哪个函数里面加呢谢谢
29楼 daisyhaohao 2010-12-1521:
41发表 [回复]
你好,我用VWF采集了视频流,现在想用opencv来对每一帧图像进行处理,应该怎么做呢?
不知道在哪里进行帧图像的处理。
。
。
28楼 charleyjt 2010-12-0715:
21发表 [回复]
有了师兄这个教程学习起来真是突飞猛进啊
27楼 zijiegao 2010-11-1616:
07发表 [回复]
邹博士你好像好久没来了,我按着你的讲述做后,在VC6.0和OpenCV1.0环境下,出现一些很相似的问题:
errorC26
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 多媒体
![提示](https://static.bdocx.com/images/bang_tan.gif)