




已阅读5页,还剩121页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
置顶 VC多媒体编程 分类: 软件开发 2007-04-28 14:09 14021人阅读 评论(8) 收藏 举报 编程nullmicrosoftwindowsgdi+文档-VC多媒体编程-Visual C+中基于多文档视窗模型的重叠图象拼接技术摘要 图象拼接是在全景视频系统、地理信息系统等应用中经常遇到的一个问题,本文基于网格匹配的方法对边界部分有重叠的图象提出了一种行之有效的对准算法,并通过平滑因子对图象实现了无缝拼接。并应用文档视窗模型实现了该算法,并完成了位图文件的显示、存储等操作,具有一定的普遍意义。 关键词: 图象拼接,算法,重叠图象,文档视窗,位图文件,图象显示 文章正文 一、多文档视窗模型概述 MFC的AppWizard可以生成三种类型的应用程序:基于对话框的应用、单文档应用(SDI)和多文档应用(MDI)。三种应用中,以多文档应用(MDI)最为复杂,其功能也最强大。当我们用AppWizard生成一个多文档应用时,系统由CMultiDocTemplate自动生成了一个从Cdocument类继承的文档类,一个从Cview类继承的视窗类,一个从CMDIChildWnd类继承的框架类。当我们每次建立一个新的文档时,程序根据文档模板生成一个新实例,这些我们均可不用关心AppWizard已经自动生成了代码。但如果我们要在程序中使用多个不同的文档类时,则需自己建立文档模板并控制文档实例的建立。假设我们要向一基于多文档的工程MDI中增加一Test的文档。具体步骤如下: 1、用Clazard建立一个框架类CTestFrame基类选CMDIChildWnd。 2、用Clazard建立一个文档类CTestDoc基类选CDocument。 3、用Clazard建立一个文档类CTestView基类选CView。 4、将三个类的头文件加入应用类CMDIApp中。 5、创建新文档模板,在CMDIApp:InitInstance()函数中加入如下代码 CMultiDocTemplate* pDocTemplate; pDocTemplate = new CMultiDocTemplate( IDR_TESTTYPE, RUNTIME_CLASS(CTestDoc), RUNTIME_CLASS(CTestFrame), RUNTIME_CLASS(CTestView); AddDocTemplate(pDocTemplate); 6、定义一菜单项ID号为ID_NEWTEST,利用Clazard将其处理函数加入应用类(或主框架类),在其处理函数CMDIApp:OnNewtest()函数中加入如下代码 POSITION curTemplatePos = GetFirstDocTemplatePosition(); while(curTemplatePos != NULL) /取下一个文档模板指针 CDocTemplate* curTemplate =GetNextDocTemplate(curTemplatePos); CString str; curTemplate-GetDocString(str, CDocTemplate:docName); /取文档名称 if(str = _T(Test) /判断当前文档文档是否Test类 curTemplate-OpenDocumentFile(NULL); /创建新的文档实例 return; 这样我们就建立了一个新的文档类。注意在5中创建文档模板时我们用到了一文档类型资源IDR_TESTTYPE,该资源ID在资源文件中定义如下(未包括图标和菜单的定义): STRINGTABLE PRELOAD DISCARDABLE BEGIN . IDR_TESTTYPE/nTest/nTest/n/n/nMDI.Document/nTest Document END 文档类型标识包括七个子串,包括窗口标题、文档名称、文件扩展名等。在6中curTemplate-GetDocString(str, CDocTemplate:docName);取的就是第二个子串,文档名称。文档建立之后我们就可以对其进行操作了。当然文档类和视窗类,文档类和主窗口类,以及不同文档类之间进行通信也是较为复杂的,并非几句话就能说清楚,如不熟悉文档视窗的读者请参看其它有关资料。 二、重叠图象拼接技术 1算法思想 在实现全景视频(Panoramic Video)系统、地理信息系统(GIS)及其它一些应用的过程中,我们通常会碰到这样的一个问题,就是要把几幅小的图象拼接成一幅大的图象。为了能让计算机自动对准图象我们要求待拼接的图象边界有部分重叠,计算机正是利用这些信息进行匹配对准。匹配算法的总体思想是既要保证对准的精度,又要保证运算量不至过大。这里算法利用了图象的自身特性,既在一般图象中,相邻的象素点的灰度值相差不大。因此,可在第二幅图象的边界取一个网格,然后将网格在第一幅图象上移动,计算所有网格点的两幅图象对应象素点的RGB值的差的平方和。记录最小的值的网格位置,即认为是最佳匹配位置。(如图1)为了减小运算量,我们将匹配分为两个步骤,第一步是粗略匹配,在该阶段网格每次水平或垂直移动一个网格间距。在完成粗略匹配之后,我们在当前最佳匹配点处进行精确匹配,在该阶段以当前最佳匹配点为中心,网格向上下、左右各移动一个小步长。初始步长为粗略拼接时移动步长的一半,即为半个网格间距。不断的与当前最小平方和进行比较,如果比当前值优,就替换当前最佳匹配点。循环进行这个过程每次步长减半,直到水平步长和垂直步长均为0为止。 2算法描述 procedure ImageMatching 输入FirstImage; 输入SecondImage; /获得两幅图象的大小 Height1=GetImageHeight(FirstImage); Height2=GetImageHeight(SecondImage); Width1=GetImageWidth(FirstImage); Width2=GetImageWidth(SecondImage); / 从第二幅图象取网格匹配模板 SecondImageGrid = GetSecondImageGrid(SecondImage); / 粗略匹配,网格在第一幅图象中先从左向右移动,再从下到上移动,每次移动一个网格间距,Step_Width 或Step_Height,当网格移出重叠区域后结束 y=Heitht1-GridHeight; MinValue = MaxInteger; While ( yHeight1-OverlapNumber)/当网格移出重叠部分后结束 x=Grid_Width/2; /当网格位于第一幅图象的最左边时,A点的横坐标。 While ( x(Width1-Grid_Width/2) ) FirstImageGrid=GetImgaeGrid(FirstImgaeGrid, x, y); differ=CaculateDiff(FirstImgaeGrid, SecondImageGrid);/计算象素值差的平 /方和 if (differ0 & Step_Width0)/当水平步长和垂直步长均减为零时结束 if(Step_Height=0)/当仅有垂直步长减为零时,将其置为1 Step_Height=1; If(Step_Width=0) /当仅有水平步长减为零时,将其置为1 Step_Width=1; temp_x = BestMatch_x; temp_y = BestMatch_y; for ( i= -1; i1; i+) for( j= -1; j1; j+) if (i=0&j!=0)|(i!=0&j=0) FirstImageGrid=GetImgaeGrid(FirstImgaeGrid, temp_x+i*Step_Width, temp_y +j*Step_Height); differ=CaculateDiff(FirstImgaeGrid, SecondImageGrid); if (differ3(1) 假设位数组的起始指针为lpStartBits屏幕坐标(x,y)在的象素值的指针可用下式计算。 lpBits=lpStartBits + (WidthBytes*(Height-y-1) + x*biBitCount);(2) 其中WidthBytes为(1)式计算的值,Height为图象的高度。 3、 不同文档类之间的数据交换的实现 不同文档类之间的数据交换我们可以通过应用程序类或主窗口类作为媒介进行。在文档类或视窗类可通过AfxGetApp()或AfxGetMainWnd()获得应用类和主窗口类的指针,在应用类和主窗口类则可以通过获得文档模板来获得文档类的指针来访问文档类的数据。这样我们可以通过应用类或主窗口类的成员变量进行数据交换了。 4、 图象的平滑连接 当找到最佳匹配点后,随后的工作将是把两幅图象合成一幅图象。对于重叠部分,我们如果只是简单的取第一幅图象或第二幅图象的数据,会造成图象的模糊和明显的边界,这是不能容忍的。即使取两幅图象的平均值,效果也不能令人满意。为了能使拼接区域平滑,保证图象质量,我们采用了渐入渐出的方法,即在重叠部分由第一幅图象慢慢过渡到第二幅图象,很自然我们可以想到设一渐变因子为0dget_Width(&hmWidth); pPic-get_Height(&hmHeight); double fX,fY; fX = (double)pDC-GetDeviceCaps(HORZRES)*(double)hmWidth/(double)pDC-GetDeviceCaps(HORZSIZE)*100.0); fY = (double)pDC-GetDeviceCaps(VERTRES)*(double)hmHeight/(double)pDC-GetDeviceCaps(VERTSIZE)*100.0); if(FAILED(pPic-Render(*pDC,0,0,(DWORD)fX,(DWORD)fY,0,hmHeight,hmWidth,-hmHeight,NULL) AfxMessageBox(渲染图像失败!); pPic-Release(); else AfxMessageBox(从流中装载图像失败!); 其中,显示工作主要是由IPicture接口对象的Render函数来完成的,该函数主要用来将图片的指定部分画到指定的设备环境的指定位置。原型如下: HRESULT Render( HDC hdc, /渲染图像用的设备环境句柄 long x, /在hdc上的水平坐标 long y, /在hdc上的垂直坐标 long cx, /图像宽度 long cy, /图像高度 OLE_XPOS_HIMETRIC xSrc, /在源图像上的水平偏移 OLE_YPOS_HIMETRIC ySrc, /在源图像上的垂直偏移 OLE_XSIZE_HIMETRIC cxSrc,/在源图像上水平拷贝的数量 OLE_YSIZE_HIMETRIC cySrc,/在源图像上垂直拷贝的数量 LPCRECT prcWBounds /指向目标图元设备环境句柄的指针); 小结:到此为止,通过上述代码已经能够在程序的客户区内显示JPEG、GIF等标准的图像了,但对于有多帧图片(即有动画)的GIF格式的图像,目前还只能显示第一帧,如要完整的显示GIF 动画的全过程,还需要外部Active X控件的支持。 -Visual C+实现Flash动画播放摘要: 本文通过在VC中将外格式文件内嵌为VC的内部资源,使其在程序运行过程中从资源动态释放到临时文件,从而实现VC对Flash动画的播放。 引言 Flash动画由于可以很方便地把用户的想象通过动画显现出来,使原本只属于专业制作人员的动画制作变的异乎寻常的快捷、方便。由于Flash制作的动画在层次、内容、表现形式等诸多方面均比较出色,因此在网络上得到迅猛的发展,更有不少厂商用Flash在互联网上做起了广告和产品演示,效果丝毫不比视频的差,而体积则要小的多。Flash不仅在网络上有广泛的应用,在普通的应用程序中也可以借助Flash实现一些VC、Delphi等编程语言所难以实现的特效,比如在一些演示版的程序中完全可以将程序运行前的闪屏用Flash来制作。本文下面将通过对内嵌资源的动态释放来实现VC对Flash动画的播放,并给出了部分实现代码。 内嵌资源的动态释放 Flash动画在此是作为程序的一个模块,虽然也可以以文件的形式作为一个外部资源来使用,但为了避免因外部模块遗失而造成程序的非正常运行,可将由Flash 5.0预先制作好格式的文件以资源的形式打包到应用程序中去,而在程序运行时再将其从资源恢复到文件,使用完毕再通过程序将其从磁盘删除。 在导入资源时由格式文件并非VC的标准资源,所以在导入时需要在Resource type栏指定资源类型,特别需要注意的是在此必须要包含引号。加入到资源后可以通过资源视图看到导入资源是以二进制形式保存的,一但加入就不能再通过资源视图对其进行编辑了。 在使用资源前首先要将其动态从应用程序中释放到文件中才可对资源做进一步的使用。可先通过宏MAKEINTRESOURCE()将资源标识号IDR转换成字符串Name,再分别通过FindResource()、LoadResource()函数查找、装载该资源到内存: CString Type=; HRSRC res=FindResource (NULL,Name,Type); HGLOBAL gl=LoadResource (NULL,res); 当资源加载到内存后,还要通过对资源内存的锁定来返回指向资源内存的地址的指针,并籍此实现资源从内存到磁盘的保存,至于存盘的操作则由文件函数CreateFile()、和WriteFile()来完成: LPVOID lp=LockResource(gl); /返回指向资源内存的地址的指针。 CString filename=Temp; /保存的临时文件名 / CREATE_ALWAYS为不管文件存不存在都产生新文件。 fp= CreateFile(filename ,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,NULL); DWORD a; /sizeofResource 得到资源文件的大小 if (!WriteFile (fp,lp,SizeofResource (NULL,res),&a,NULL) return false; CloseHandle (fp); /关闭句柄 FreeResource (gl); /释放内存 通过上述代码,可资源从应用程序中提取并释放到临时文件Temp中,在此后只对此临时文件操作,与程序内嵌资源无关。 Flash动画的播放 格式的Flash动画通常主要应用在网页上,也就是说IE浏览器本身可以支持Flash动画的播放。这样就不必再单独编写用于播文件的代码,从而大大减少编程的工作量。在VC + 6.0中新增了一个从CView派生的、用于处理网页的视类CHtmlView,由于该类是以Internet Explorer为后台支持,因此在创建工程时只需在最后一步指定视类从CHtmlView派生就可以使程序不编一行代码而具备IE浏览器的网页显示能力。 程序刚生成的时候缺省的连接主页是为微软公司的主页,需要对此修改,使程序在执行时立即显示刚才提取出来的Flash临时文件Temp。显示缺省主页的代码是在视类的初始化函数中进行的: void CEmbedModuleView:OnInitialUpdate() CHtmlView:OnInitialUpdate(); Navigate2(_T(),NULL,NULL); 显然要将Navigate2()函数的第一个参数改成Temp的存放路径。刚才在释放资源到文件时并没有指定绝对路径,因此释放出来的资源文件应当和应用程序处于同一目录。但是在此处如果不写明绝对路径是无法显示该临时文件的。获取该临时文件的绝对路径可用如下方法实现:先获取应用程序本身的绝对路径,然后去处应用程序全名(程序名和扩展名)此时得到的是应用程序和临时文件所处文件夹的路径,最后只需在此基础上加上临时文件的文件名Temp即可得到临时文件的全路径。下面是实现的主要代码: /获取应用程序的全路径 char exeFullPathMAX_PATH; GetModuleFileName(NULL,exeFullPath,MAX_PATH); /将其格式化为字符串 m_TempFile.Format(%s,exeFullPath); /去掉应用程序的全名(15为应用程序文件全名的长度) exeFullPathm_TempFile.GetLength()-15=/; /得到应用程序所在路径 m_TempFile.Format(%s,exeFullPath); /得到临时文件的全路径 m_TempFile+=Temp; 最后将得到的临时文件的全路径m_TempFile作为参数传递给Navigate2()即可在程序运行时把Flash动画作为主页而显示(如上图所示)。 由于临时文件Temp是在程序运行过程中从应用程序的资源中提取出来的,因此在程序退出之前需要将其删除。一般是在消息WM_DESTORY的响应函数里通过DeleteFile()函数来加以实现的。 小结 本文通过对CHtmlView和内嵌资源的动态释放实现了Flash动画在VC程序中的播放,并对资源的动态释放作了较为清晰的描述。通过类似的方法,可以将动态链接库、HTML文件等程序模块作为资源嵌入其中,在使用时再动态释放到临时文件,这样可有效避免文件模块过多时的杂乱以及程序模块丢失导致程序非正常运行等情况的发生。本文所述程序在Windows 98下,由Microsoft Visual C+ 6.0编译通过。Flash动画由 Macromedia Flash 5.0制作,所需浏览器支持为Internet Explorer 6.0。 -用RealPlayer控件制作的播放器本文介绍如何插入RealPlay控件实现媒体文件的播放,代码运行效果图如左: 下面简要介绍一下具体实现步骤: 一、建立基于对话框的程序 二、在对话框内添加RealPlayer G2 control的ActiveX控件 (工程-添加工程-compontent and controls-registed ActiveX controls )。 三、在对话框内添加源程序内所示的按钮和静态文本 分别用于控制打开播放等控制及显示歌曲信息 其ID号如源程序 四、用MFC映射各按钮消息 void CSunapplerealplayerDlg:OnOpen() char szFileFilter= RM File(*.rm)|*.rm| Mp3 File(*.mp3)|*.mp3| MPEG File(*.mpeg)|*.mpeg| Media File(*.asf)|*.asf| Video File(*.dat)|*.dat| MPGA File(*.mpga)|*.mpga| Wave File(*.wav)|*.wav| AVI File(*.avi)|*.avi| Movie File(*.mov)|*.mov| Mid File(*.mid;*,rmi)|*.mid;*.rmi| Wma File(*.wma)|*.wma| All File(*.*)|*.*|; CFileDialog dlg(TRUE,NULL,NULL,OFN_HIDEREADONLY,szFileFilter); if(dlg.DoModal()=IDOK) CString PathName=dlg.GetPathName(); PathName.MakeUpper(); m_player-SetSource(PathName); m_player-DoPlay(); SetDlgItemText(IDC_STATIC1,m_player-GetAuthor(); SetDlgItemText(IDC_STATIC2,m_player-GetTitle(); SetDlgItemText(IDC_COPYRIGHT,m_player-GetCopyright(); SetDlgItemText(IDC_SOURCE,m_player-GetSource(); void CSunapplerealplayerDlg:OnPlay() SetDlgItemText(IDC_STATIC1,m_player-GetAuthor(); SetDlgItemText(IDC_STATIC2,m_player-GetTitle(); SetDlgItemText(IDC_COPYRIGHT,m_player-GetCopyright(); SetDlgItemText(IDC_SOURCE,m_player-GetSource(); m_player-DoPlay(); UpdateData(false); SetTimer(1,20,NULL); void CSunapplerealplayerDlg:OnTimer(UINT nIDEvent) if(0&isRepeat) m_player-DoPlay(); CDialog:OnTimer(nIDEvent); void CSunapplerealplayerDlg:OnClose() /添加此代码时不要忘了在stdafx.h开头处添加前两行 AnimateWindow(GetSafeHwnd(),1000,AW_HIDE|AW_BLEND); KillTimer(0); / /此处采用DestroyWindow关闭窗口 /多谢杜修杏 老师指点 / this-DestroyWindow(); void CSunapplerealplayerDlg:OnFullscreen() m_player-DoPause(); m_player-SetFullScreen(); m_player-DoPlay(); void CSunapplerealplayerDlg:OnMp3down() ShellExecute(NULL,_T(open),,NULL,NULL,TRUE); void CSunapplerealplayerDlg:OnPause() m_player-DoPause(); void CSunapplerealplayerDlg:OnStop() m_player-DoStop(); KillTimer(0); void CSunapplerealplayerDlg:OnRepeat() m_player-SetLoop(true); if(isRepeat) isRepeat=FALSE; SetDlgItemText(IDC_REPEAT,循环); else isRepeat=TRUE; SetDlgItemText(IDC_REPEAT,正常); void CSunapplerealplayerDlg:OnLower() / TOD Add your control notification handler code here short volume=m_player-GetVolume(); m_player-DoPause(); m_player-SetVolume(volume-100); m_player-DoPlay(); void CSunapplerealplayerDlg:OnUpper() / TOD Add your control notification handler code here short volume=m_player-GetVolume(); m_player-DoPause(); m_player-SetVolume(volume+100); m_player-DoPlay(); void CSunapplerealplayerDlg:OnFloat() /TOD Add your command handler code here ShellExecute(NULL,_T(open),,NULL,NULL,TRUE); void CSunapplerealplayerDlg:OnPetroleum() / TOD Add your command handler code here ShellExecute(NULL,_T(open),,NULL,NULL,TRUE); 五、映射WM_CTLCOLOR消息,用于控制文本显示的颜色 HBRUSH CSunapplerealplayerDlg:OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) HBRUSH hbr = CDialog:OnCtlColor(pDC, pWnd, nCtlColor); if(nCtlColor=CTLCOLOR_STATIC) if(pWnd.GetDlgCtrlID()=IDC_VOLUME) pDC.SetTextColor(RGB(165,182,222); pDC.SetBkMode(TRANSPARENT); return (HBRUSH) m_brush.GetSafeHandle(); if(pWnd.GetDlgCtrlID()=IDC_STATIC1|pWnd.GetDlgCtrlID()=IDC_STATIC2 |pWnd.GetDlgCtrlID()=IDC_SOURCE|pWnd.GetDlgCtrlID()=IDC_COPYRIGHT) pDC.SetTextColor(RGB(0,0,255); pDC.SetBkMode(TRANSPARENT); return (HBRUSH) m_brush.GetSafeHandle(); if(pWnd.GetDlgCtrlID()=IDC_STATIC|pWnd.GetDlgCtrlID()=IDC_INFO) pDC.SetTextColor(RGB(255,0,0); pDC.SetBkMode(TRANSPARENT); return (HBRUSH) m_brush.GetSafeHandle(); / TOD Return a different brush if the default is not desired return hbr; 六、在APP类里的initInstance()里添加下面函数改变对话框背景。 SetDialogBkColor(RGB(206,227,99); 七、为了美观我们的外形可引入CButtonXP类,将个按钮类型设置为CButtonXP 好了,应该大功告成了!调试一下吧! 本程序在调试过程中要多谢杜修杏老师的指点 -Visual C+编程控制鼠标鼠标是现在计算机的标准配置,很多软件都有控制鼠标的功能,比如,有的保密软件可以使鼠标移动限制在一定范围以内,有的可以模拟鼠标的点击,有的可以使鼠标自己移动。要实现以上的功能,必须使用Windows的API函数。 我们以下面的程序例子,来说明如何控制鼠标。我们使用Visual C+6.0来写这个程序。打开Visual C+6.0,使用MFC AppWizard新建1个基于对话框的工程,工程名为Mouse,在对话框上加上2个button控件,一个标题为控制鼠标移动范围,另外1个的标题是释放鼠标在MFC Clazard中添加两个当我们使用鼠标单击这两个控件时响应的函数,标题
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年建筑结构设计师专业技能模拟题与答案详解
- 电信弱电知识培训课件
- 2025年玻璃熔化工中级实操考试面试指南及技巧
- 2025年物资仓库保管员招聘面试题详解实际案例与答题技巧
- 办公室文员实习工作报告
- 急性CO中毒的急救和护理
- 甲状腺手术的麻醉
- 甲流预防课件
- 《百年孤独(节选)》课件
- 田径跳高课件
- 医院 捐赠协议书
- 小学食堂供餐管理方案(3篇)
- 湖北省武汉市武昌区重点名校2026届中考语文全真模拟试题含解析
- 2.4抽象函数的周期性与对称性-讲义(原卷版)
- 养老院重要环境因素控制措施
- 藏文教学课件
- 血透室手卫生管理课件
- 风电场安全规程考试题库(附答案)
- DB11∕T 1205-2024 用能单位能源审计报告编制与审核技术规范
- 轨道工程制图教学课件
- 2025汽车智能驾驶技术及产业发展白皮书
评论
0/150
提交评论