Visual C++中基于多文档视窗模型的重叠图象拼接技术

原创 2004年08月30日 23:36:00

Visual C++中基于多文档视窗模型的重叠图象拼接技术<?XML:NAMESPACE PREFIX = O />

辽宁省抚顺石油学院计算机科学与技术系    李志刚 

摘要:

       图象拼接是在全景视频系统、地理信息系统等应用中经常遇到的一个问题,本文基于网格匹配的方法对边界部分有重叠的图象提出了一种行之有效的对准算法,并通过平滑因子对图象实现了无缝拼接。并应用文档视窗模型实现了该算法,并完成了位图文件的显示、存储等操作,具有一定的普遍意义。

关键词:

       图象拼接,算法,重叠图象,文档视窗,位图文件,图象显示

一、           多文档视窗模型概述

MFCAppWizard可以生成三种类型的应用程序:基于对话框的应用、单文档应用(SDI)和多文档应用(MDI)。三种应用中,以多文档应用(MDI)最为复杂,其功能也最强大。当我们用AppWizard生成一个多文档应用时,系统由CMultiDocTemplate自动生成了一个从Cdocument类继承的文档类,一个从Cview类继承的视窗类,一个从CMDIChildWnd类继承的框架类。当我们每次建立一个新的文档时,程序根据文档模板生成一个新实例,这些我们均可不用关心AppWizard已经自动生成了代码。但如果我们要在程序中使用多个不同的文档类时,则需自己建立文档模板并控制文档实例的建立。假设我们要向一基于多文档的工程MDI中增加一Test的文档。具体步骤如下:

1、ClassWizard建立一个框架类CTestFrame基类选CMDIChildWnd

2、ClassWizard建立一个文档类CTestDoc基类选CDocument

3、ClassWizard建立一个文档类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,利用ClassWizard将其处理函数加入应用类(或主框架类),在其处理函数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

    文档类型标识包括七个子串,包括窗口标题、文档名称、文件扩展名等。在6curTemplate->GetDocString(str, CDocTemplate::docName);取的就是第二个子串,文档名称。文档建立之后我们就可以对其进行操作了。当然文档类和视窗类,文档类和主窗口类,以及不同文档类之间进行通信也是较为复杂的,并非几句话就能说清楚,如不熟悉文档视窗的读者请参看其它有关资料。

二、           重叠图象拼接技术

1.算法思想

在实现全景视频(Panoramic Video)系统、地理信息系统(GIS)及其它一些应用的过程中,我们通常会碰到这样的一个问题,就是要把几幅小的图象拼接成一幅大的图象。为了能让计算机自动对准图象我们要求待拼接的图象边界有部分重叠,计算机正是利用这些信息进行匹配对准。匹配算法的总体思想是既要保证对准的精度,又要保证运算量不至过大。这里算法利用了图象的自身特性,既在一般图象中,相邻的象素点的灰度值相差不大。因此,可在第二幅图象的边界取一个网格,然后将网格在第一幅图象上移动,计算所有网格点的两幅图象对应象素点的RGB值的差的平方和。记录最小的值的网格位置,即认为是最佳匹配位置。(如图 1)为了减小运算量,我们将匹配分为两个步骤,第一步是粗略匹配,在该阶段网格每次水平或垂直移动一个网格间距。在完成粗略匹配之后,我们在当前最佳匹配点处进行精确匹配,在该阶段以当前最佳匹配点为中心,网格向上下、左右各移动一个小步长。初始步长为粗略拼接时移动步长的一半,即为半个网格间距。不断的与当前最小平方和进行比较,如果比当前值优,就替换当前最佳匹配点。循环进行这个过程每次步长减半,直到水平步长和垂直步长均为0为止。

<?XML:NAMESPACE PREFIX = V /><?XML:NAMESPACE PREFIX = W />wz049.4.jpg
 


       (a) 拼接前两幅图象                                                      b)拼接后合成的图象

1     网格匹配拼接示意图

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 ( y<Height1-OverlapNumber)//当网格移出重叠部分后结束

{

              x=Grid_Width/2; //当网格位于第一幅图象的最左边时,A点的横坐标。

              While ( x<(Width1-Grid_Width/2) )

{

                     FirstImageGrid=GetImgaeGrid(FirstImgaeGrid, x, y);

                differ=CaculateDiff(FirstImgaeGrid, SecondImageGrid);//计算象素值差的平

                                                              //方和

                     if (differ<MinValue)

                     {

                            BestMatch_x=x;

                            BestMatch_y=y;

                            MinValue = differ;

                     }

              x= x+Step_width;

              }

              y=y-Step_Height;

}           

//精确匹配

Step_Width= Step_Width/2;

Step_Height= Step_Height/2;

While ( Step_Height>0 & Step_Width>0)//当水平步长和垂直步长均减为零时结束

{

       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; i<1; i++)

              for( j= -1; j<1; 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 (differ<MinValue)

                            {

                                   BestMatch_x=x;

                                   BestMatch_y=y;

                                   MinValue = differ;

                     }

                     }

                    }

              Step_Height = Step_Height /2;

              Step_Width = Step_Width/2;

       }

}    

 

三、           基于多文挡视窗模型的重叠图象拼接技术

程序在Visual C++实现过程中有如下一些技术问题需要注意。

1、  位图文件的读取和显示

位图文件是一种最简单的图象文件,屏幕图象的每一点对应位图文件的几位数据。现有的标准有1位、4位、8位、24位。24位位图不含颜色表,每个象素用3个字节表示,依次表示RGB空间里的蓝、绿、红的灰度值。每种位图文件都由两部分组成,一部分是文件头和位图信息头,另一部分是图象的位数组。因此要想显示一个位图文件首先要声明一个CFile类实例将文件读入内存,然后根据文件头和位图信息头获得图象的相关信息和位数组的起始地址。调用SetDIBitsToDevice()函数即可把图象显示在屏幕上。

2、  位图文件中任意象素点颜色值的获取

要实现图象的处理,访问任意象素点的象素值是必需的操作。在访问位图文件时有两点需要注意,一是图象位数组的存储是按从下到上进行的。也就是说,图象的最底行的数据存在位数组的最开始位置。另一个特点是,图象的每行象素所占的空间是双字的整数倍,不足的用零填充。每行象素的实际存储大小可由以下公式加以计算。

    WidthBytes=(((biWidth*biBitCount)+31)&~31)>>3                       1

    假设位数组的起始指针为lpStartBits屏幕坐标(x,y)在的象素值的指针可用下式计算。

lpBits=lpStartBits + (WidthBytes*(Height-y-1) + x*biBitCount);                       (2)

    其中WidthBytes为(1)式计算的值,Height为图象的高度。

3、  不同文档类之间的数据交换的实现

不同文档类之间的数据交换我们可以通过应用程序类或主窗口类作为媒介进行。在文档类或视窗类可通过AfxGetApp()AfxGetMainWnd()获得应用类和主窗口类的指针,在应用类和主窗口类则可以通过获得文档模板来获得文档类的指针来访问文档类的数据。这样我们可以通过应用类或主窗口类的成员变量进行数据交换了。

4、  图象的平滑连接

当找到最佳匹配点后,随后的工作将是把两幅图象合成一幅图象。对于重叠部分,我们如果只是简单的取第一幅图象或第二幅图象的数据,会造成图象的模糊和明显的边界,这是不能容忍的。即使取两幅图象的平均值,效果也不能令人满意。为了能使拼接区域平滑,保证图象质量,我们采用了渐入渐出的方法,即在重叠部分由第一幅图象慢慢过渡到第二幅图象,很自然我们可以想到设一渐变因子为0<d<1,对应的前后两幅图象为image1image2,结果为image3,则image3=d*image1+(1-d)*imge2其中d的值由1渐变到0,它与该点距重叠边界的距离有关。

 

四、           多文挡视窗模型的重叠图象拼接程序框架

1.  程序构成

程序除应用类、主窗口类以外,还包括CFristImageDoc, CSecondImageDoc, CThirdImageDoc类用来保存第一幅、第二副以及拼接后图象的数据。还有与其相连的文档类和框架类。

2.  程序流程

程序的主要工作在应用类中完成,首先打开第一幅图象,图象的显示等操作由CFirstImageDoc 类和与其相关的视窗类及框架类完成,并将图象的位数组指针和图象大小传给应用类成员变量。再打开第二幅图象同样完成显示等操作,也将位数组指针和图象大小传给应用类成员变量。在应用类中完成图象的匹配对准工作,最后实现图象的合成。将合成后的图象传给CThirdImageDoc类进行显示当用户对拼接结果基本满意后,可以选择平滑连接将两幅图象平滑的连接起来。用户可将最后的结果保存成bmp文件。

五、           总结

图象拼接中,图象对准是前提和关键,程序基于网格匹配的方法实现了图象对准,应用了交互技术让用户可以对网格点的多少,网格间距大小,均可调整,还允许用户输入重叠范围使拼接过程有的放矢,缺省是较小图象高度的1/3。该程序实现了对位图图象文件的各种操作,具有普遍意义,还引入了不同文档类型的多文档视窗模型,并在不同文档类间实现了数据交换,具有一定的实用价值。为了使程序简单易用,只实现了对24位位图的拼接,也未提供垂直方向的拼接,只提供了水平方向的拼接。如要对不符合条件的图象进行拼接我们只需在Windows提供的画笔中将图象转化一下即可。

全景视频拼接(四):循环将两幅图像拼接为全景图片

项目要求:利用双摄像头同时采集两个视频,离线拼接,将两个视频拼接成一个视频。 该部分代码实现功能:循环将两幅图像拼接为全景图片,储存为有顺序的图像序列,方便后续拼成视频。 方法:以stit...
  • haikuotiankong7
  • haikuotiankong7
  • 2017年11月19日 11:36
  • 225

C++服务器重叠I/O+事件通告模型

#include #include #include #include using namespace std; #pragma comment(lib,"Ws2_32.lib") #pragma ...
  • riyuedangkong1
  • riyuedangkong1
  • 2016年06月22日 21:14
  • 906

SIFT Match 图像拼接 计算两幅图像的重叠区域

问题描述:已知两幅图像Image1和Image2,计算出两幅图像的重叠区域,并在Image1和Image2标识出重叠区域。 算法思想: 若两幅图像存在重叠区域,则进行图像匹配后,会得到一张完整的全...
  • hqh45
  • hqh45
  • 2014年05月06日 15:47
  • 2872

多个视频画面拼接技术

____YUV主要采样格式理解 主要的采样格式有YCbCr 4:2:0、YCbCr 4:2:2、YCbCr 4:1:1和 YCbCr 4:4:4。其中YCbCr 4:1:1 比较常用...
  • wirelessdisplay
  • wirelessdisplay
  • 2017年02月17日 18:19
  • 1081

json单对象、多对象拼接方式

应用一: [ { "ID":"1", "Name":"jsonName", "c1": [ { "ProductTypeID": "1098",...
  • qq285679784
  • qq285679784
  • 2017年03月03日 16:04
  • 639

图象压缩技术

 MPEG-1 MPEG视频 压缩编码后包括三种元素:I帧(I-frames)、P帧(P-frames)和B帧(B-frames)。在MPEG编码的过程中,部分视频 帧序列压缩成为I帧;部分压...
  • sunjn_jz
  • sunjn_jz
  • 2014年04月23日 11:05
  • 391

概率图模型-原理与技术 第二章 基础知识 学习笔记

概率图模型 第二章 基础知识 学习笔记
  • icefire_tyh
  • icefire_tyh
  • 2017年01月11日 14:13
  • 690

图像拼接算法的基本原理

转自:http://blog.csdn.net/yuyin86/article/details/6690423 全景视频是一种利用360 度全景图象建立虚拟环境的新方法。全景图象是通过将...
  • lina_suda
  • lina_suda
  • 2015年05月06日 18:55
  • 4881

相对简单的SURF全景拼接(七)

在opencv为我们提供的拼接demo程序里使用的是SURF拼接算法(详情见文章一),如果你打算深究该算法,可是Opencv的源码阅读有困难,以下这篇文章由浅至深,介绍了拼接的流程,检测特征点->计算...
  • wys2011101169
  • wys2011101169
  • 2016年12月29日 11:32
  • 927

概率图模型-原理与技术 更新计划及总目录

概率图模型更新计划及总目录 作为一个爱做习题的旁听生,“升级后提交”这几个字真是让我心碎 近阶段学习感想从在coursera上发现概率图模型这门课起,到现在也零零碎碎看了不少时间。学习一门课程介...
  • icefire_tyh
  • icefire_tyh
  • 2017年01月05日 01:43
  • 1184
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Visual C++中基于多文档视窗模型的重叠图象拼接技术
举报原因:
原因补充:

(最多只允许输入30个字)