首页 人脸建模软件 毕业论文(初稿)

人脸建模软件 毕业论文(初稿)

举报
开通vip

人脸建模软件 毕业论文(初稿)人脸建模软件 毕业论文(初稿) 目 录 1 引言 ........................................................................................................................ 1 2 概述 ............................................................................................................

人脸建模软件  毕业论文(初稿)
人脸建模软件 毕业 论文 政研论文下载论文大学下载论文大学下载关于长拳的论文浙大论文封面下载 (初稿) 目 录 1 引言 ........................................................................................................................ 1 2 概述 ........................................................................................................................ 2 2.1 人脸建模软件概述 ....................................................................................... 2 2.2 本 设计方案 关于薪酬设计方案通用技术作品设计方案停车场设计方案多媒体教室设计方案农贸市场设计方案 思路 ........................................................................................... 2 2.3 研发方向和技术关键 ................................................................................... 3 2.4 主要技术指标 ............................................................................................... 4 3 软件 设计 领导形象设计圆作业设计ao工艺污水处理厂设计附属工程施工组织设计清扫机器人结构设计 ................................................................................................................ 5 3.1 软件框架的搭建 ........................................................................................... 6 3.2 特征点的选取 ............................................................................................... 6 3.3 OpenGL环境下3D模型的显示 .................................................................. 7 3.4 建模方法 ...................................................................................................... 8 3.5 模型文件格式 ............................................................................................... 9 3.6 其他说明 ...................................................................................................... 9 4 软件框架的实现................................................................................................... 10 4.1 框架概要 .................................................................................................... 10 4.2 图形用户界面的实现 ................................................................................. 10 4.3 OpenGL环境的实现 .................................................................................. 12 4.4 照片和特征点的实现 ................................................................................. 15 5 核心算法的实现................................................................................................... 17 5.1 算法概要 .................................................................................................... 17 5.2 数学归化算法 ............................................................................................. 17 5.3 拉普拉斯变形算法 ..................................................................................... 18 5.4 Mask透明截图算法 ................................................................................... 21 6 调试 ...................................................................................................................... 24 7 结论 ...................................................................................................................... 26 致谢............................................................................................................................ 27 参考文献 .................................................................................................................... 28 1 引言 人脸是人类日常情感表达和交流最重要、最直接的载体。人脸的计算机建模应用非常广泛,比如说电影、广告人物动画、电脑游戏、视频会议、人机接口、面部外科手术、电视节目、计算机辅助手语教学以及心理学、认知科学等许多领域。 一个具有真实感的人脸模型能够丰富人机接口,增强系统非口语语言通信及表情信号的能力,使人机接口更令使用者感兴趣,且更易于使用。 通过计算机生成具有真实感的三维人脸拥有广阔的应用前景,而且这项技术是近年来计算机图形学、计算机视觉、人工智能等领域中最具挑战性的问题之一。其实,早在20世纪70年代关于人脸建模及动画的研究便开始了。这个开创性的工作是由Parke起步的。接着Waters等人提出了广泛应用的肌肉模型方法。Cohen和Massaro以及其他很多研究者对可视化语音合成进行了初步的尝试。随着网络技术的普及,世界上第一个网上虚拟播音员Ananova在伦敦发布,计算机合成的Ananova可以一天24小时发布新闻。人脸建模的应用现在已经非常广泛,模型的真实程度也较以前有了很大的飞跃。 利用三维扫描仪获取三维形状数据和纹理信息是一种直接的人脸建模方法,通常具有较高的精度,但是存在硬件设备造价高、不灵活等不足,一般只适用于某些特殊场合;当前的研究热点主要集中在根据图像和视频序列进行人脸重建,现有基于多张图像的方法普遍存在特征点匹配复杂、效率低等不足。根据单张人脸照片上的少量特征点能够快速、自动地实现特定人脸的建模,是目前三维人脸建模研究中一个极具潜力的研究方向。 本设计就是制作一个基于单张人脸照片的快速、自动建立个性化人脸模型的应用软件。其目标是以较少的输入和交互操作,自动建立人脸3D数据模型,所建立的模型与人脸照片中的样本具有较高的相似度。 1 2 概述 2.1 人脸建模软件概述 一般的,人脸建模软件的设计包括以下3个过程:脸部数据的获取、3D人脸几何建模、纹理图像的合成提取。通过人体测量学对相似的面部进行测量,对其结果进行统计,生成脸的统计学数据。这些统计学数据被当作对参数化表面的约束。对特定人脸的建模依然需要用户输入大量的数据,但现在也可以通过激光扫描仪和立体摄像机等自动实现。 人脸几何建模就是把真实人脸的框架标准化,然后用网格表示出来。这也是本次毕业设计的难点,因为真实人脸几何建模非常困难并且很耗时间,真实的人脸是高度光滑且形状复杂的,并且人们对它的每一个细节都非常熟悉. 对于3D人脸几何建模,通常情况下,为了把脸表达得更加详细、生动,总是希望网格数越多越好,但是考虑到计算代价,又不可能把网格数无限制地增加.3D人脸几何建模的最基本要求是,能够表达清楚脸部的明显特征,同时希望网格数尽可能的少.脸部模型生成方法大致可以分为3种:多边形建模技术、曲面建模技术和体网格建模技术. 人脸纹理图像的生成也是很重要的一个环节,对模型附加纹理可以极大的提高模型和真实源的相似度,因为纹理图像可以表现出模型本身很难表达出的信息,比如说像睫毛这样细小的细节。通过人脸照片可以直接提取人脸的纹理特征,主要应用的技术有Mask图,Alpha透明度合成等。 软件中的建模方法用到了标准人脸变形法,这个方法是将一个已经完成建模的3D人脸模型数据,根据特征化人脸照片及其特征点位置,利用一定的变形算法,通过一般化人脸到特征化人脸的变形来完成建模的。这个方法属于多边形建模法,而且理解起来比较容易,具备一定的可行性。但缺点是模型变形的控制有限,不能还原所有的3D数据。变形完成以后的模型,通过Mask图提取照片中的纹理特征,在提取照片之前还应注意照片中人脸大小的标准化。对提取的特征使用Alpha调节透明度,使之融合在标准的人脸纹理上。 本毕业设计中其他的工作点在于软件界面的设计和制作上。为了实现较好的人机交互功能,必须设计好软件的输入和输出操作。因为输入和输出操作是直接对用户可见的。而其他软件操作则是只有软件本身可见的,不对用户开放。所以用户可以不用关心模型的实际建模过程。 2 2.2 设计 方案 气瓶 现场处置方案 .pdf气瓶 现场处置方案 .doc见习基地管理方案.doc关于群访事件的化解方案建筑工地扬尘治理专项方案下载 思路 本设计中最主要的要点在于1.软件界面的设计和制作;2.图片的导入;3.特征点的调整;4.3D模型的显示;5.对3D模型的交互;6.标准3D模型的变形算法;7.纹理特征图像的提取合成;8.特征点数据的三维化;9.模型文件和纹理文件的保存。 1. 利用MFC的框架设计和制作软件界面; 2. 利用文件的读取来完成照片图片的导入; 3. 通过建立特征点的数据结构,利用MFC提供的图形图像接口完成特征点的显示和控制; 4. 建立OpenGL的图形环境,通过文件打开3D模型的OBJ文件,建立3D模型的数据结构,在OpenGL的环境中显示3D模型; 5. 使用MFC提供的消息处理机制,完成OpenGL和消息的互动,由此对3D模型进行交互; 6. 通过特征点的相对位置,采用拉普拉斯变形算法解决3D模型的变形问题; 7. 通过特征点的相对位置,缩放原始照片图像,再用mask图对人脸照片的特征纹理进行提取和合成; 8. 利用特征点的2维相对位置,寻找3维模型正面视图的边界点,通过寻找到的边界点完成2维数据的3维化。 9. 在建模过程中生成特征模型所需的数据,并建立临时文件,以便保存文件数据。 2.3 研发方向和技术关键 (1)建立友好的图形用户界面,方便用户操作; (2)面向对象的软件编程,MFC的API; (3)OpenGL的环境搭建和消息的传递; (4)3D模型的显示、交互以及拉普拉斯变形; (5)特征点2维数据的3维化; (6)纹理特征的提取和合成。 3 2.4 主要技术指标 (1)软件运行环境: 操作系统: Microsoft Windows XP\Microsoft Windows 7 内存: 2GB 硬盘: 50MB 软件环境: glmf32.dll; glu32.dll; glut32.dll (2)模型顶点数: 863个 (3)模型纹理顶点数: 900个 (4)模型面片数: 1630个 4 3 软件设计 人脸3D模型的建模过程主要包括3部分,第一步是用户输入人脸照片并调整特征点的位置,接着建立3D模型的数据结构和纹理合成,最后将建立好的人脸模型以文件的形式输出,保存到电脑上以便其他建模软件应用。根据建模过程可以将软件分为5个模块:输入模块;模型数据模块;纹理数据模块;核心算法模块(数据处理模块)和输出模块。具体的模块图可参见图3-1: 核心算法模块 输入模块模型数据模块纹理数据模块输出模块 图3-1 人脸建模软件模块图 输入模块主要为用户提供人脸正面照片的导入功能,以及在导入照片后自动显示人脸特征点,并使用户可以执行修改这些特征点的操作。输入模块还提供给用户直接打开模型文件的功能。 模型数据模块的功能是保存用户导入的人脸模型数据和标准人脸模型数据,为这些数据建立数据结构。这些数据常驻内存,方便软件时刻对数据进行修改和保存。 纹理数据模块为人脸模型的纹理图形建立数据结构,并且纹理数据包括用户输入人脸照片的图像数据。 核心算法模块(数据处理模块)的功能是利用数学算法对模型数据和纹理数据进行操作。操作的依据是用户输入的照片图像以及用户调整后的人脸特征点的相对位置。由特征点相对位置调整人脸标准模型数据各个顶点的三维坐标,再由用户输入照片的图像数据合成人脸模型的纹理数据,并将这些数据保存至模型数据模块和纹理数据模块。 输出模块的功能有OpenGL的显示及交互,它为用户提供良好的模型显示效果以及对模型的控制功能,包括平移、旋转、缩放;还有用户导入照片以及人脸特征点的显示。输出模块的另一个作用是将模型文件(OBJ文件)保存到硬盘。 5 3.1 软件框架的搭建 人脸建模软件第一步需要的是一个具有较好交互性的图形用户界面。所有的输入和输出功能,必须体现在所设计的界面元素上。 首先,输入功能包括:打开模型文件、建立模型文件、导入照片、对模型显示界面的控制操作、特征点的调整。 其次,输出功能包括:保存模型文件、照片列表视图、显示3D模型的OpenGL视图、调整特征点用的照片视图。 其中,打开模型文件、建立模型文件、保存模型文件作为软件界面的工具栏元素;导入照片和照片列表视图为照片列表元素;对模型显示界面的控制操作和显示3D模型的OpenGL视图属于模型界面元素;特征点的调整和调整特征点用的照片视图属于特征点调整界面元素。 对软件的界面设计如下图(图3-2)所示: 图3-2 个性化真实感人脸建模软件界面 最上面有两个图像按钮的一层为软件界面的工具栏元素,最左侧显示小照片和照片名称的列表为照片列表元素,中间显示3D人脸模型的就是模型界面元素,最右面用于调整特征点的即是特征点调整界面元素。 3.2 特征点的选取 人之所以能够通过视觉区别不同的人,主要是因为人面部的特征各有不同。经过专家计算分析,人面部光正面的关键特征点总数就达70个之多。这么多的特征点,对于如何从照片中提取是一个复杂的问题。 6 本设计使用的方法是人工调整这些特征点,那么太多数量的特征点势必增加用户的工作量,而且太多的特征点在数据结构的建立和计算上的难度很大。所以必须使用数量既少,又能较好表现人脸关键特征的特征点。 在对其他人脸面部建模软件的调研中发现,FaceGen人脸建模软件使用了11个正面人脸的特征点。这些特征点的位置如下: 颧骨的左右两个边界点,这两个特征点相当于是人脸部正面的左右两个边界,直接决定了人面部的宽度。 下巴最下部的特征点,这个点即是人面部的下边界。 两侧脸颊的中央拐点,这两个点确定了人面部的曲线由颧骨到下巴的趋势,是人面部形状的重点特征。 两个眼睛的眼球中点,这两个点直接表示了人双眼的位置。 左右两侧鼻翼的边界点,这两个特征点表示了人鼻子的宽度和在面部的位置,通过人眼睛的两个特征点计算,还可以大致判断鼻子的长度。 左右嘴角的两个边界点,同鼻翼两侧边界一样,这两点确定了嘴巴的宽度和位置。 具体的特征取样如下图3-3所示(以软件中标准面部模型为例): 图3-3 标准面部模型正面全部特征点,绿色亮点为特征点标记 3.3 OpenGL环境下3D模型的显示 为了较好的显示3D模型,软件使用了OpenGL作为3D模型绘制的接口。所以必须要配置OpenGL的图形环境,设置好该环境下的各项数据。 7 首先设置OpenGL的显示环境,确定OpenGL的显示视图,视图的长、宽以及长宽比,还有显示的最小深度和最大深度,确定显示像素的属性。其次是导入模型数据,调用OpenGL绘制函数,将模型的顶点、面片在图形显示视图上显示出来。最后打开纹理图像,为图形赋予纹理,同样须通过OpenGL的接口。 其中需要注意的是,OpenGL的显示环境在配置好以后不宜任意改变,所以对于不可改变的显示环境,并不能匹配所有的模型文件。这样的话就不能提高软件的适用范围,而且局限了软件能够使用的模型文件。 这样的话,我们在导入模型数据以后,为了使模型的数据适应到OpenGL的显示环境,必须对这些数据进行归化。本软件使用的归化方法是将所有的顶点坐标控制在[-1, 1]之间,这样OpenGL环境配置只需要考虑完全显示[-1, 1]之间的信息就可以了。 3.4 建模方法 本设计应用到的建模方法是标准化模型变形建模法。软件自身含有一个标准的人脸模型,通过对这个标准模型的面部形状和纹理进行特征化的变形合成后,生成一个具备一定特征的人脸模型。这个方法中最重要的部分就是如何使用用户照片中的人脸数据。 首先,通过用户自己完成对特征点的调整。具体的调整方法参照3.2中叙述的特征点位置的选取。 之后,使用提取到的顶点坐标,将坐标值归化在[-1, 1]之间。如此是为了使2维坐标与3维坐标相对应。3维坐标在显示模型时已经进行了[-1, 1]之间的归化。这样的话就可以将2维的数据信息映射到3维视图中了,通过这些信息标定3维顶图形对应顶点的目标位置,通过这个位置,就可以对3维顶点进行操作了。 最后,使用拉普拉斯变形,将对应顶点移动到标定的位置即可。 以上为3维模型的数据建模过程,建模方法中还应有一步,即提取和合成照片中人脸的纹理图像。提取纹理过程的前两步和建模时的相同,都是对特征点信息的操作,方法也是一样的。 纹理提取还应注意的是特征点的划分,因为特征点的位置具有一般性,所以必须将每个特征点位置的含义了解清楚。比如,哪个特征点是眼睛,哪个是鼻子。 将特征点划分好后就可以分块截图了。分块做的目的主要是为了准确的提取特征,因为每个人的面部特征都是不尽相同的,不可能用一个标准的模子提取出准确的特征。 之后就可以提取具体特征了,使用制作好的mask图。每张mask图都对应一张分块截图,使用mask图提取的特征即可以合成到纹理图像上了。 8 这里的合成方法是半透明合成法,分别取特征和标准纹理的50%进行合成,这样合成的纹理既可以保持一定的特征性,又可以和标准纹理相融合,比较符合建模的要求。 3.5 模型文件格式 本软件支持的模型文件格式为OBJ格式的文件,OBJ格式为三维模型文件的一般格式。它主要保存的信息有:模型注释信息;3维点集;2维纹理点集;3维面片集;2维纹理面片集。OBJ文件是未经压缩的模型数据文件,这些数据的编码为ASCII码。 一般来说,对于点、面片数量庞大的模型文件,OBJ格式的文件读取速度较慢。但就信息查询来说,它能直观的反应点和面片的数据信息,对调试程序有很大的帮助。而且本软件用到的高模人脸模型的总记录数约在25200-27200之间。但就读取文件来说不会对性能造成太大的影响,所以本软件以OBJ文件作为模型的输入输出文件。 下面介绍详细的文件格式: 数据标识符 介绍 详细说明 # 注释信息 注释信息 o 模型来源 说明模型的制作软件 g 纹理名称 纹理图像名称的前缀 s 分组信息 将模型从1开始分组 v 模型顶点 模型的空间坐标(x, y, z) vt 纹理顶点 模型的纹理图像坐标(x, y) f 面片 模型面片所含顶点的序号 / 面片分隔符 左边为模型序号,右边为纹理序号 表格3-1 标准面部模型正面全部特征点 3.6 其他说明 本软件使用的编程环境是visual studio 2008下的MFC,所用到的图像操作接口除了MFC提供的之外,还有CXImage。 CXImage是一款免费的图像操作接口,它的功能非常强大,这里主要用到了它对图像数据的操作,如:图像裁剪,图像提取等等。需要注意的是CXImage中对于图像(0, 0)点的位置与MFC中窗口的默认原点不同,CXImage使用左下角第一个点作为它的原点。在CXImage与windows窗口进行图像数据传递时必须进行图像坐标的转换。 9 4 软件框架的实现 4.1 框架概要 本软件的框架内容如第3章软件设计中介绍的那样,包含图形用户界面和基本的输入、输出功能。具体实现时,我们把它分开成3个模块:第一模块为界面模块,即软件的图形用户界面的实现;第二模块为OpenGL环境模块,它代理所有有关OpenGL的接口调用;第三模块为照片和特征点模块,这个模块管理用户导入的人脸照片、并提供给用户调整特征点的接口。 上述为了软件基础框架的实现所分成的3个模块与设计中依据功能划分的模块不同,这3个模块的划分主要是为了编程的实际操作的方便划分的,这3个模块在实现时会同时完成功能模块中提到的内容。那么下面就围绕具体实践来介绍这3大模块的编程实现。 4.2 图形用户界面的实现 对于现在的软件程序,图形用户界面的编写非常的容易,因为所有的接口都已经被设计好,并且我们只需要调用它的方法就好了。尤其对于基于MFC的程序来说,图形界面的编程非常的方便,很多方法visual studio 2008已经代劳。那么我在这里将不再赘述一个windows环境下软件图形窗口的建立,而是直接介绍用于窗口排版的程序接口,以便大家了解窗口的样式是如何实现的。 软件的界面在第3章已为大家展示过了,为了方便阅读,仍然在下面附上软件的截图,并换张明星的照片以防审美疲劳。 图 4-1 软件界面 10 如上图所示:软件的框体按界面元素分可以分成3个部分:第一部分是菜单栏,第二部分是工具栏,第三部分是分隔栏分割成的3个视图。菜单栏和工具栏的创建都是MFC自动完成的,其实MFC自动完成的还应该有窗口底层的状态栏,我在软件中屏蔽了状态栏的生成。 我想在这里主要说一下自定义工具栏的实现和分割视图的方法,让它们以上图所示的布局出现主要依靠了两个类,分别是CToolBar以及CSplitterWnd。 因为工具栏系统已经生成好了,所以我们在这里的自定义工具栏只要重新设置一些参数就好了。当然也可以新建一个工具栏类,这样的话就可以在其他程序里方便的使用自定义的工具栏了。 这里需修改的参数主要有,工具栏的大小,工具栏的贴图。修改工具栏大小很简单,在资源视图中打开工具栏属性直接就能修改,我这里设置的大小是宽64p,高48p。而且资源视图也提供工具栏图像的修改,但是它提供的色彩范围有限,只提供了256色,所以为了界面的美观,还是以贴图形式来美化工具栏的好。 制作图片的步骤在此略过,只论贴图方法吧。为CToolBar贴图需要在修改程序,添加贴图函数。添加贴图函数的过程如下:首先制作的图像需要保存到一个CImageList中;之后我们需要让CToolBar产生一个消息“CToolBar.SendMessage (TB_SETIMAGELIST, 0, (LPARAM)CImageList.m_hImageList)”,让这个消息告知程序来显示我们自定义的工具栏图标;产生消息后,要释放CImageList资源,以便减轻内存负担。如此,我们就实现了自定义工具栏的制作。 CSplitterWnd是实现视图分割的系统类,人脸建模软件里的视图被分成了1行3列的3块,分别显示了照片列表,人脸模型和含特征点的照片。视图切割是这样执行的。首先,所分成的三个视图是不同的视图,需要我们重新定义它们的类结构。例如显示模型的视图我们定义它的类为CModelView,并继承CView类,在主函数中定义这些视图的变量。创建好它们3个不同的视图类后,我们就可以初始化CSplitterWnd了。通过函数CreateStatic将总视图划分为1行3列的结构,接着利用CreateView 函数将视图绑定到相应的位置,例如CModelView在中间,那么它的位置就是0行1列(行号、列号从0开始计算)。我们最后将创建好的视图利用GetPane赋值给我们在主函数定义的视图变量就完成视图创建了。 需要注意的是,所有的代码需在OnCreateClient消息里完成,即在窗体空间开始创建之前。而且如果创建的分割有行中列或列中行的情况则需要一个新的CSplitterWnd类来分割上一个CSplitterWnd的子视图。 11 4.3 OpenGL环境的实现 为了观察一个3D模型,我们必须为软件配置一个能够展示三维效果的显示环境,我们选择OpenGL作为3D模型的显示环境。OpenGL是一个图形用户接口,它里面定义了大量的函数,可以方便的调用,而且它是跨平台的,功能非常强大。为了使用OpenGL,首先需要配置OpenGL的运行环境。 配置环境的循序是这样的,首先要获取视图对象,从中得到HDC,这样OpenGL就可以利用HDC来绘制图形了;接着设置OpenGL绘图的像素格式,这是为了控制OpenGL的显示信息,例如颜色的位数,Alpha通道之类的设置等等;下一步是把OpenGL中的HRC关联到视图的HDC上;接着需要设置场景信息,例如场景的显示大小长宽,可见的最大最小距离,视口的长宽比等等。现在我们的OpenGL环境就初始化完成了。 不过为了达到好的显示效果,我们还可以继续为OpenGL的环境添加内容。一般的模型都会贴附一些纹理图像,我们在初始化OpenGL时往往会将这些需要用到的纹理也一同创建好。在创建纹理时,我们首先要打开计算机中的纹理图像文件,将这些图像按OpenGL的图像结构绑定,接着设置好纹理的显示方式就好了。 OpenGL中常用到的设置还有阴影显示效果、背景颜色、深度缓存、透视修正方式、模型材质和光照等等。为了提高模型的显示效果,我们可以把这些设置提高,不过这样必然导致显示速度会变慢。一般来说这些设置应该对用户可见,即用户可以根据自己设备的性能选择到底是显示优先还是速度优先。 完成了OpenGL的配置,我们就可以绘图了,利用OpenGL提供的glBegin、glEnd就可以绘制图形了,下面是我绘制人脸面片的一段代码,由于既有三角面片又有矩形面片,所以程序在绘制时分开讨论了: glPushMatrix(); for(int i=1, index=0; i<=pts.m_nFNum; i++) { if(i == pts.m_nIndexFlat[index]) { // 选择纹理 glBindTexture(GL_TEXTURE_2D, pts.m_TextureIndex[index]); index ++; } if(pts.m_nFlat[i][3] == 0) // 三角面片 12 { glBegin(GL_TRIANGLES); glTexCoord2f(pts.m_fVertexTexture[pts.m_nFlatTexture[i][0]][0], pts.m_fVertexTexture[pts.m_nFlatTexture[i][0]][1]); glVertex3f(pts.m_fVertex[pts.m_nFlat[i][0]][0], pts.m_fVertex[pts.m_nFlat[i][0]][1], pts.m_fVertex[pts.m_nFlat[i][0]][2]); glTexCoord2f(pts.m_fVertexTexture[pts.m_nFlatTexture[i][1]][0], pts.m_fVertexTexture[pts.m_nFlatTexture[i][1]][1]); glVertex3f(pts.m_fVertex[pts.m_nFlat[i][1]][0], pts.m_fVertex[pts.m_nFlat[i][1]][1], pts.m_fVertex[pts.m_nFlat[i][1]][2]); glTexCoord2f(pts.m_fVertexTexture[pts.m_nFlatTexture[i][2]][0], pts.m_fVertexTexture[pts.m_nFlatTexture[i][2]][1]); glVertex3f(pts.m_fVertex[pts.m_nFlat[i][2]][0], pts.m_fVertex[pts.m_nFlat[i][2]][1], pts.m_fVertex[pts.m_nFlat[i][2]][2]); glEnd(); } else // 矩形面片 { glBegin(GL_QUADS); glTexCoord2f(pts.m_fVertexTexture[pts.m_nFlatTexture[i][0]][0], pts.m_fVertexTexture[pts.m_nFlatTexture[i][0]][1]); glVertex3f(pts.m_fVertex[pts.m_nFlat[i][0]][0], pts.m_fVertex[pts.m_nFlat[i][0]][1], pts.m_fVertex[pts.m_nFlat[i][0]][2]); glTexCoord2f(pts.m_fVertexTexture[pts.m_nFlatTexture[i][1]][0], pts.m_fVertexTexture[pts.m_nFlatTexture[i][1]][1]); glVertex3f(pts.m_fVertex[pts.m_nFlat[i][1]][0], pts.m_fVertex[pts.m_nFlat[i][1]][1], pts.m_fVertex[pts.m_nFlat[i][1]][2]); glTexCoord2f(pts.m_fVertexTexture[pts.m_nFlatTexture[i][2]][0], pts.m_fVertexTexture[pts.m_nFlatTexture[i][2]][1]); glVertex3f(pts.m_fVertex[pts.m_nFlat[i][2]][0], pts.m_fVertex[pts.m_nFlat[i][2]][1], pts.m_fVertex[pts.m_nFlat[i][2]][2]); glTexCoord2f(pts.m_fVertexTexture[pts.m_nFlatTexture[i][3]][0], pts.m_fVertexTexture[pts.m_nFlatTexture[i][3]][1]); glVertex3f(pts.m_fVertex[pts.m_nFlat[i][3]][0], pts.m_fVertex[pts.m_nFlat[i][3]][1], pts.m_fVertex[pts.m_nFlat[i][3]][2]); 13 glEnd(); } } glPopMatrix(); //交换缓冲显示图像 SwapBuffers(m_hDC); 这里的交换缓冲显示图像很重要,如果没有这行代码,绘制的模型将不会显示在视图中。当然这里的绘制只能绘制了3D模型的一种显示角度,对于不同角度的显示须有用户的交互来实现。对模型的平移,旋转和缩放才是3D环境的真谛,下面我们来谈谈如何实现OpenGL中对于镜头的操作。 我们可以把OpenGL视图看做一个摄像机的镜头,如果我们想观察物体的其他角度,要么使物体改变,要么就改变我们自己这台摄像机,当然也这两种改变也可以同时存在。在我的程序中平移和缩放是通过改变摄像机来实现的,而旋转是通过改变模型来实现的。其实我们应该尽可能的使用摄像机来完成交互,因为改变物体的坐标系会使模型坐标变得复杂,容易引发错误而难以纠正。不过我们的3D显示比较简单,只有一个人脸模型,直接旋转物体比旋转摄像机控制起来容易,所以我才用直接旋转物体的方法来做旋转交互。 了解了以上方法,我们就可以直接调用OpenGL的函数来实现交互了。利用gluLookAt()实现平移与缩放,利用glRotatef()实现旋转。首先来看gluLookAt()函数,这个函数的参数是9个立体坐标,分别代表视点,观察点和向上向量。视点就是我们摄像机所在的位置啦,观察点顾名思义,就是我们视觉中心。通过视点和观察点可以决定一个向量,这个向量就代表我们摄像机的朝向。向上向量就是摄像机所在坐标系的纵轴向量。通过摄像机的朝向向量、向上向量,OpenGL就可以计算得出摄像机自身的坐标系,而OpenGL正是通过这个坐标系来计算摄像机的一些数据的。我们移动摄像机,就是改变这个坐标系,平移就是同时等量的改变视点和观察点,缩放就是沿摄像机的朝向减少或增加视点到观察点的距离。而对于旋转中用到的glRotatef()函数,则只要简单的定义旋转的角度和旋转轴就可以了,不需要经过三角函数的计算,这一点比通过gluLookAt()实现要方便。 以上便是OpenGL环境的实现,纵观所述,3D界面编程主要包括三维环境的初始化,图形绘制和用户交互三个方面,而这三方面都要用到OpenGL所提供接口,所以才称之为OpenGL的环境实现。 14 4.4 照片和特征点的实现 照片和特征点的功能包括:打开图片文件,显示图片和特征点以及对特征点的操作。其中打开图片文件和显示图片都是用到了CxImage的接口;特征点的显示图片是我用PS制作的,是一个绿色的十字标志;对特征点的操作包括拖动单一特征点到指定位置,还有拖动所有特征点到指定位置。 用CxImage打开图片非常简单,这里还借助了MFC提供的CFileDialog类,可以通过我们习惯的对话框的方式打开文件。我想要详细介绍的是显示图片和特征点的功能以及对特征点的交互功能。 单纯的显示一张图片文件非常方便,而我们不仅仅要在图片区域显示原始的照片,更重要的是要显示特征点,以便我们对其进行操作。这样的话就需要对打开的图片文件进行一定的修改,为其附加上特征点,使他们融合成为一张新的图片。一方面我们可以利用软件计算来绘制一个指定颜色的十字标志,这样做的好处是不用另外保存特征点图像文件,但这样做对图像的绘制速度是有影响的。如果利用计算完成绘制,在我们拖动特征点时会有“卡”的感觉,所以我选择了第二种方法,就是保存一张十字标志的图片,这样绘制时的速度就有了保证。 但是保存的图片在导入资源后是BMP格式的,也就是说,这张图片不存在透明区域,直接复制在照片上时,照片上将多出一个矩形,而不是单纯的十字标志。这样的话,就需要引入一个Mask图作为控制透明区域的图像。Mask就是一张灰度图像,我们这里用到的就是一张只有黑和白的Mask图,而更灵活的应用我将在下一章的Mask图透明截图算法中再详细介绍。一张Mask图像,黑色部分表示不透明,白色表示全透明。其原因是这样的:在计算机中,保存色彩信息的RGB格式,黑色的数据是(0,0,0),白色的是(255,255,255),转换成二进制的话,黑则全0,白则全1。如果我们利用这张“黑白分明”的图片对原始照片做“与”操作的话,那么原始照片上与Mask白色对应的部分将没有任何改变,而黑色的对应部分将全部变黑,就好像挖了一个洞一样。再利用Mask图做透明处理时,我们绘制特征点图像的时候也是有技巧的,透明区域的颜色必须表示成黑色。这是因为,我们为原图附加Mask了以后也要附加特征点图像,而这步操作用到的是“或”运算。想想看,原图上的色彩或上特征点图像上黑色的点,则色彩不改变,而原图黑色部分的色彩则会完全变成特征点图像上的颜色。这也正是我们在附加Mask图时把待填充区域变成黑色的一个原因。如此,单纯的与或操作就实现了图片的透明化处理。下图为十字标志透明化贴图的示意图: 15 图4-2 利用Mask图实现透明化贴图 当然,光显示特征点是不够的,我们显示的目的还是为了交互。交互的实现需要我们为显示照片的View添加消息,即鼠标左键按下OnLButtonDown、鼠标移动OnMouseMove和鼠标左键抬起OnLButtonUp。按下左键后,我们首先要根据鼠标位置搜索对应的特征点,如果找到,则标记该特征点,如果没有则标记所有特征点(因为我们在没有选择任何特征点并按下鼠标时,将视为改变所有特征点位置)。之后我们记录鼠标按下的布尔值为真并记录鼠标位置。当鼠标移动时,我们首先判断鼠标是否按下的布尔值,若值未假则不作任何处理,若值为真,则记录鼠标位置,通过之前记录的位置作比较求的鼠标的位移,以此位移值来确定控制点的位置。左键按下后,我们只需要将标记点的标记去掉并记鼠标按下的布尔值为假就好了。 16 5 核心算法实现 5.1 算法概要 本软件涉及到的算法主要是基于图形学的数学算法。其中包括数学归化,拉普拉斯变形算法,Mask透明截图算法等。 数学归化是用来统一数据单位长度的算法,其作用是将一个一般化的数学模型统一化到一个固定的坐标系里,这样做有利于对数据的处理和比较。 拉普拉斯变形算法是用于对3D人脸模型变形的算法,它主要实现了改变一个顶点并影响与该顶点相关的其他顶点的功能。这样做的好处是可以通过对尽量少的顶点的操作来完成模型整体的变形。 Mask透明截图算法是提取图像中指定位置像素值的算法,透明截图即通过Mask掩膜的灰度来判断图像的透明度。Mask透明截图算法可以较好的提取出照片中的人脸特征图像,以提供给合成纹理图片操作。 5.2 数学归化算法 本软件使用数学归化的目的是将一个任意坐标系的模型坐标缩放到[-1, 1]的坐标范围内。对于2维图像坐标,即将x坐标和y坐标缩放到[-1, 1]的坐标范围,对于3维的模型坐标,即将x坐标、y坐标和z坐标缩放到[-1, 1]的坐标范围。 缩放方法是这样的,假设我们要缩放一个2维的图像坐标。我们第一步需要找到这个图像坐标系的极值,即比较坐标系的宽度和长度,选取其较长的一边,取它两端的极值max,min。设归化前得坐标为X,归化后的坐标为x,那么将其缩放到[-1, 1]的坐标范围的公式是: 2(min)X, x,,1 maxmin, 证明:利用等比性质,缩放后的x减最小极值-1比缩放前X减最小极值min的值等于2比原始坐标系的极值长度,即max-min。需要注意的是,使用这个公式的话,较短边得坐标起点必然从-1开始,而较短边的最大点不在+1处。 数学归化算法的软件实现较为简单,首先遍历所有坐标,找到x、y还可能有z的极值,利用极值求的max和min。然后再遍历一边,将所有的数据直接公式带入就可以了。 例,模型3维坐标的归化函数: void CModelPointSet::NormalizeCoordinate() { 17 // 寻找最值点 for(int i=1; i<=m_nVNum; i++) { if(m_fVertex[i][0] < m_fXmin) m_fXmin = m_fVertex[i][0]; if(m_fVertex[i][0] > m_fXmax) m_fXmax = m_fVertex[i][0]; if(m_fVertex[i][1] < m_fYmin) m_fYmin = m_fVertex[i][1]; if(m_fVertex[i][1] > m_fYmax) m_fYmax = m_fVertex[i][1]; if(m_fVertex[i][2] < m_fZmin) m_fZmin = m_fVertex[i][2]; if(m_fVertex[i][2] > m_fZmax) m_fZmax = m_fVertex[i][2]; } // 寻找最长边 float lenX = m_fXmax - m_fXmin; float lenY = m_fYmax - m_fYmin; float lenZ = m_fZmax - m_fZmin; float longer = lenX > lenY ? lenX : lenY; float longerp = lenX > lenY ? m_fXmin : m_fYmin; float longest = lenZ > longer ? lenZ : longer; float longestp = lenZ > longer ? m_fZmin : longerp; // 归化 for(int i=1; i<=m_nVNum; i++) { m_fVertex[i][0] = (2.0f*(m_fVertex[i][0]-longestp))/(longest) - 1.0f; m_fVertex[i][1] = (2.0f*(m_fVertex[i][1]-longestp))/(longest) - 1.0f; m_fVertex[i][2] = (2.0f*(m_fVertex[i][2]-longestp))/(longest) - 1.0f; } } 5.3 拉普拉斯变形算法 本软件中,由于构成个模型的顶点非常多,不可能逐一去细微调整每一个顶点 的位置。如果能只改变一点的位置,同时又能使其他的点进行相适应的变化就好 了。拉普拉斯变形算法就解决了这一问题。 算法中,改变的标准是基于模型顶点与一环邻域的一个标准值。如果模型中一 个点变化了,为了保证标准值不变,变化点的一环邻域点必定相应改变。紧接着, 18 一环邻域点的一环邻域点也要改变其自身位置,由此,实现了“牵一发而动全身”的效果。 标准值的定义很简单,假设标准值为δ,x为变化点坐标,x-x是一环邻域点0n坐标,那没求δ的公式即为: n ,,,nxx,i i,1 由于这种变化是全域性的,一个点的变化必定引起所有点的变化,这样的话,我们必须规定一些不变的点来控制模型的整体变化。 总之,拉普拉斯变形算法是以一个或几个点的值的变化或不变来求解其他点的最终位置的算法,这个算法的本质是求解方程组,那么计算机里实现求解方程组的方法即构造矩阵求解。拉普拉斯算法的求解矩阵如下: aaaax,,,,1112131n1,,,,aaaax2122232n2,,,, ,,,, ,,,,aaaa,x,,nnnnn123n1,,,,,,,,,,aaaax,(1)1(1)2(1)3(1)nnnnn,,,,n12,,,,,,,,,,,,,,,,,,,,aaaax()1()2()3()nmnmnmnmn,,,,nmn,,,,,,,,aaaax,,,,(1)1(1)2(1)3(1)nmnmnmnmn,,,,,,,,nm1,,,,,, ,,,,,,,,aaaax()1()2()3()nmlnmlnmlnmln,,,,,,,,nml,,,,,,()1nml,,,nnml(),,, 对于等式左边左侧n*(n+m+l)的矩阵来说,最上面的n行是求一环邻域时就确定的。取第i行,其中a为其一环邻域的度数,对于其他的项,如果该项对应的ii 顶点为a一环邻域上的点,那么该项为-1,如果不是,该项为0。 i 中间的m行作为控制点出现,即中间的m行定义了m个位置不改变的顶点。其中列标等于不变点序号的项为1,其他的点为0。相应的右侧矩阵的对应x值为原始模型坐标的x值。 下面的l行是变化点的控制行,即下面的l行定义了l个位置改变的顶点。其中列标等于不变点序号的项为1,其他的点为0。相应的右侧矩阵的对应x值为变化后的x值。 等式左边右侧(n+m+l)*1的矩阵为求解矩阵,它上面的n行是最终要求解的坐标值,而下面的m+l行是控制顶点的坐标值。 19 等式右边矩阵即为一环邻域标准值δ。 -1对于矩阵方程Ax=B来说,可以用求逆矩阵的方法求解,即x=BA。可是拉普拉斯矩阵非常的复杂,又是一个n行n+m+l列的矩阵。要直观的求解这种复杂的矩阵可以应用LDU分解来完成。 LDU是3个矩阵的缩写,其中L代表下三角矩阵,D代表对角阵,U代表上三角矩阵。LDU分解即是将一个矩阵分解成LDU三个矩阵相乘的形式,即A=LDU。就n行n+m+l列的拉普拉斯矩阵来说,分解后的L为n行n列,D为n行n+m+l列,U为n+m+l行n+m+l列。如此对于方程Ax=B就可以变换成LDUx=B, -1-1-1那么方程的解x=UDLB。而对于LDU这三个特殊矩阵来说,求逆是非常方便的。 通过调试分析,在实际的计算中,虽然LDU的算法可以正确分解矩阵,但是随着不变点和改变点的添加,计算结果却并非正确。通过很多次的修改和纠正,终于发现拉普拉斯矩阵本身是一个对称矩阵,在添加控制行后将变得不对称,也就是这种不对称性导致了变形数据的错误。因此,我们对矩阵方程Ax=B稍作处 TT理,是一个不对称的矩阵A变为对称矩阵。方法就是乘以A的转置,即AAx=AB。 T这样由于AA是一个对称矩阵,在对其分解求逆后计算出的坐标值正确的实现了预期的变形效果。其实拉普拉斯方程本是正确的,只不过由于算法的局限性,必须进行相应的调整,在保证数学等式成立的情况下进行调整以适应算法,是我这次毕业设计所得到的重要经验。 以上就是拉普拉斯变形的数学原理,而拉普拉斯变形算法的编程实现起来相对比较复杂。算法的求解过程是这样的:首先要遍历得到一环邻域的系数矩阵,再求解一环邻域标准值矩阵。得到这两个矩阵以后就基本完成了拉普拉斯矩阵方程的初始化,下面的步骤就是确定模型的变化点和不变点了,不变点的定义是通过调试的方法慢慢确定的,变化点啊的数据要通过用户输入的特征点位置确定。这样我们就得到了拉普拉斯矩阵方程,剩下的就是方程求解了。求解方法就用LDU分解法求解。下面介绍编程中用到的函数: // 一环邻域赋值: private void SetFactorMatrix(int mid, int pre, int nxt); // 导入顶点坐标: private void SetSolutionMatrix(int index, float x, float y, float z); // 求一环邻域标准值: private void SetEpsilonMatrix(); // 把矩阵转化为单位阵 void InitToUnits(); // LDU分解 20 void GetLDU(); // 获取上三角矩阵的逆矩阵 void GetInverseUpTrg(); // 获取下三角矩阵的逆矩阵 void GetInverseDownTrg(); // 获取对角阵的逆矩阵 void GetInverseDiagonal(); // 矩阵相乘 void Multiply(CMatrix& mat2); 下面详细说明一下一环邻域赋值的函数是如何实现的。一环邻域指的是3D模型上的任一顶点周围与其直接相邻的顶点的集合。我们所求的一环邻域就是所有顶点的与其相邻顶点的序号,再在矩阵中对应的序号位置赋值。 总体设计里讲到的obj文件格式,对应了一种很好的数据结构,这种数据结构可以很容易的求模型顶点的一环邻域。在这种数据结构里,存储了所有顶点的面片,而面片的存储方式是构成这个面片的顶点序号。也就是说,所求的顶点所在的一个面片中,肯定可以找到它的两个相邻的顶点序号。通过这个性质,我们遍历所有的面片,对每个序号相邻的两个顶点记录到矩阵里。同时,对于重复的顶点序号我们略过不考虑。就通过这样的方法计算所有顶点一环邻域。 5.4 Mask透明截图算法 要得到一个相似度较高的模型光靠模型形状的相似是不够的,如果对建好的模型贴附纹理,就可以大大的提高模型的显示效果,提高图形模型与真实模型源的相似度。Mask透明截图算法就可以解决如何提取用户输入人脸照片中人脸图像特征信息的问题。 介绍算法前首先要说明的是什么事Mask图。Mask又可以叫掩膜,或者蒙板。你要是熟悉PhotoShop的话,那么马上就能和Mask亲近许多,因为PS中蒙板实现的原理就是Mask图。追根溯源,人们在用喷枪作图时,所用的刻出一个图形空洞的模板就是现实中的Mask图了。这模板的作用就是控制着色范围,只有镂空部分下面的纸面才会被上色。同理,我们就可以用Mask图来控制提取纹理图像的范围啊。那么到底怎么做才能实现这种范围控制的效果呢? 我们使用的Mask图是灰度图,也就是说,Mask图里只存在黑白灰三种颜色。灰度表示的是亮度信息,越是暗的地方就越黑。我们就以纯黑色(0, 0, 0)为不透明色,以纯白色(255, 255, 255)为全透明色。即Mask图中越是暗的地方,遮盖的比例就越大。也就是说,我们将提取Mask明亮处图像,而忽略暗处的部分。当然,这种忽略是有比例的忽略。为了达到较好的溶图效果,我们以灰度分级,越是明亮,我们提取该处色彩的比例就越高,相反的,越是黑暗,提取的色彩比例就越低。 21 这样的话,提取处像素点的色彩就可以用下面的公式计算得到: GRAYGRAY ()(1)CCC,,,neworifrom 256256 其中C是提取的颜色,C是提取源的颜色,C是融合图的背景颜色。neworifrom GRAY是灰度值,256是灰度分级。 以上介绍了Mask图以及Mask图的使用方法,下面具体说明本软件对纹理特征图像的提取和合成。如公式,纹理合成需要三张图片,即背景图,Mask图和信息源图。我们用一张标准模型的标准纹理作为我们的背景图,Mask是根据标准纹理绘制的灰度图,信息源图就是用户输入的照片啦。 之所以用背景图的原因就是,用户输入的照片不可能包含所用建模时需要的纹理信息,比如说侧脸、头顶,后脑勺部位的图像。为了建好的模型达到较高的完整度,我们就需要事先做好这些部分的纹理图像,也就是所谓的标准纹理图像。我们用这个图像作为纹理特征提取的背景图像,将提取到的纹理融合到这张背景图像上,模型纹理贴附的就是已融合好提取特征的标注纹理图像。 Mask图当然就不用再多介绍了,软件中用到的Mask图以50%灰度为上限,即最多提取信息源图中50%的色彩。这也为的是控制与背景图的色差,使纹理看起来不会太过分离,毕竟人的肤色千差万别。在我现有的技术上不太容易完成对标准纹理色相,对比度的调整,以适应用户导入的人脸照片。所以才一这种这种的方法制作Mask图的。 信息源图作为纹理的提取源,由用户导入。为了提取更准确的特征信息,利用用户调整后的特征点进行人脸的区域分块。因为人脸各不相同,不可能用一张大Mask图来提取所有正确的特征,必须通过将人脸特征分区域提取才能保证得到的特征是正确的。我将人脸划分为8个特征,分别是额头、左颧骨、右颧骨、鼻子、左脸颊、右脸颊、人中和下巴。这8个分块可以较为正确的提取人脸各部分的特征。分块以后,我们先缩放这些分块,然后根据Mask图(同样是8张)制作8张提取后的特征图像,再将这8张特征图像合成到一开始的背景图上,这就是整个特征提取和和合成的过程。除了人脸部特征以外,还要提取人的眼睛特征。 下面为人脸部部分分块的Mask图和提取特征后的临时的特征图像: 22 图5-1 鼻子、额头和左脸颊的Mask图和特征提取图 有了特征提取图就可以进行纹理合成了。需要注意的是合成时也要用到Mask图,Mask图是决定图片透明度一个标准,是图像提取和合成时不可缺少的要素。合成时要先确定好特征提取图在背景图上的位置,然后根据Mask图的灰度按比例贴附至背景图上。下图为背景图和完成图示例: 图5-2 背景图和完成图 23 6 调试 6.1 特征点坐标的定位 在特征点的交互功能上,最重要的一点就是定位特征点坐标的位置。由于MFC中图像坐标系的原点在视图的左上角点,一开始我就参照软件窗口的左上角点来建立特征点的坐标。但窗口的左上角坐标并非视图的原点,所以在定位特征点时必须加上视图相对窗口原点的坐标偏移。虽然说在显示人脸照片图像时,由于图像的长宽比不同,缩放后照片所在视图中的位置也不一样,但这并不影响特征点的定位,因为这里的定位重在给用户一个良好的交互感,而真正建模用到的定位则需要对特征点的位置进行规划,和另外一系列的调整。 6.2 CxImage的原点坐标 在对照片进行分块截图时,由于一开始以为CxImage处理图像的原点设定和MFC一样,这就导致截取的图像显得非常奇怪。进行debug后发现,图像上横坐标点的位置与预期的相同,而出错的位置全都在纵坐标上。可是计算公式都验证过了,是没问题的。于是猜测可能CxImage中的原点位置在左下角,如此再改变计算公式,果然能够在正确位置截图了。通过CxImage处理时,我们必须重新计算图像纵坐标y的值,定义图像的高度为H,那么在MFC中的纵坐标Y在CxImage中的纵坐标就是H-Y。 6.3 Mask图的制作 其实在截图方法完成以后,最重要的工作就不再是编程,而是Mask图的制作。软件的截图的绝大部分取决于Mask图像数据,对于不同的Mask图,软件生成的纹理图像也不尽相同。这些数据控制了截图的像素色彩比例,渐变,衔接等等。而且这项工作的性质是实验性的,它需要的不只是思路,也要通过一次一次的调试来优化。在对Mask图处理时,遇到的主要问题有Mask图重叠,边界明显,衔接处有断层等等。有的时候感觉,要么就是特征获取的太少,要么就是特征与原始纹理过度不够自然,很难协调好这两者之间的关系。总之,Mask图制作总是有着进步的余地,是需要不断调整和设置的。 6.4 拉普拉斯矩阵的调试 最痛苦的调试就是拉普拉斯矩阵方程了,全都是复杂的矩阵操作,而且顶点数量庞大,计算公式又很多。这里直接设断点看数据非常的麻烦而且说明不了问题,所以我又重新添加了很多调试函数进去,一步一步的跟踪矩阵的赋值,分解,求逆,相乘这些运算。在赋值后,我重新检查赋值的正确性,并让矩阵方程重新 24 求解,查看解是否为原值;我又将分解后的矩阵重新计算,看看是否能回归为原始的矩阵;求逆的话,我用了两种方法,一种是求逆后与原矩阵相乘,然后判断结果是否为单位阵,第二种时求逆后再求逆,看看是否为原矩阵。为了调试矩阵的基本算法,我还重新写了一个矩阵计算的小程序,通过这个小程序来判断矩阵相乘,求逆等函数是否正确。拉普拉斯矩阵方程的求解非常复杂,中间的一个小错误就导致了所有的结果出错,短短的原始代码加上调试用到的函数就增长到了上百行。由这里我真是深深的 体会 针灸治疗溃疡性结肠炎昆山之路icu常用仪器的管理名人广告失败案例两会精神体会 到Debug在软件制作中所占的比重之重了。 6.5 2D-3D对应公式 如何将照片里特征点的位置转化到3D模型上是一个比较难解决的问题,严格的说,从2D到3D的转换除了平面上各点的位置,还要考虑到阴影的情况。我这里没做那么复杂,只是单纯的在模型上改变了特征点的位置。在推导公式时,一开始考虑的太简单了,只考虑到模型在归化时的旋转。而事实要更复杂,因为我们的模型还包含了脖子,所以必须还要考虑到缩放。在求缩放比例时,还要注意到3维坐标系下线段长度的求法。经过调试,初步定下了对应关系的公式。我们以人脸额头到下巴的直线段长度为基准,定义为L;在模型和照片中L的比例,即缩放比,定义为γ;特征点到下巴的距离记为l;我们的目的就是在模型中依旧保持照片中的人脸比例,这个比例就是l/L。所以当我们求得l时,为了保持这个比例,直接使模型中的特征点到下巴的距离为γl即可。 25 7 结论 本设计软件基本完成了人脸自动建模的算法,主要包括人脸照片的导入和显示,在人脸照片上调整特征点,拉普拉斯模型变形,纹理的分块提取和合成,显示3D人脸模型,输出格式为obj的模型文件。 (1)软件完成的图形化的用户界面,包含框架的搭建,并完成了用户对于软件的基本交互功能; (2)在调整特征点位置的功能上,实现了利用图像文件绘制透明化的特征点,以及可单一调整特征点位置和可全部调整特征点位置的功能; (3)完成了拉普拉斯变形算法,可以根据照片中特征点的位置定位3D模型上顶点的坐标,实现了模型变形。 (4)纹理提取利用分块的特征提取方式,在特征点位置正确的情况下能够准确的提取出人脸特征,并和原始纹理融合,实现了纹理的特征提取。 (5)软件的文件输出绑定在建模功能上,会直接生成Temp文件,包含模型所需的obj文件和纹理图像文件。 由于时间、水平和经验有限,虽然各功能的算法已经完成,但还有很大的优化空间。就模型建模来说,虽然模型有所改变,但没有按照绝对坐标改变,而是利用比例完成的,所以在对特征点操作时,仅仅是一个点的变化,就会牵动整个模型的变化。而且模型特征点的选取也存在问题,因为照片图像上各点是在同一个平面上的,而模型上的并非如此,所以在变形时要做不同的处理。 纹理图像的提取也有待增强,比如说皮肤的颜色调整,由于标准纹理的色彩局限使得提取的纹理很难与原始纹理进行过渡,这就应该利用照片中皮肤的色彩对整张纹理图片上的皮肤色彩进行调整。而且纹理图像的合成中,对于特征图像的遮盖,融合顺序都要进行进一步的优化。 总之,这次毕业设计对于我来说,是一个新的学习过程,也是一次挑战。通过这次的毕业设计,我学到了很多东西,通过自己的实践,提高了编程能力。通过实际工程的设计也使我了解到书本知识和实际应用的差别。在实际应用中遇到很多的问题,这都需要我对问题进行具体的分析,并一步一步地去解决它。 26 参考文献 [1] 徐 琳, 袁保宗, 高 文. 真实感人脸建模研究的进展与展望[J]. 软件学报. 2003. 804 – 810. [2] 张青山, 陈国良. 具有真实感的三维人脸动画[J]. 软件学报. 2003. 643 – 650. [3] 彭天强, 王聪丽. 可视化工具包应用研究[J]. 信息工程大学学报. 2003. 69 – 72. [4] 姚俊峰. 三维动漫游戏人物角色仿真技术[M]. 科学出版社. 2009. 3 – 47. [5] 裴玉茹. 人脸形状分析和视频驱动三维语音动画研究[D]. 北京: 北京大学. 2006. [6] 梅丽. 基于图象的人脸重建及视频驱动的表情动画[D]. 杭州: 浙江大学. 2001. [7] 王强. 人脸面部运动分析与真实感动画研究[D]. 北京: 清华大学. 2003. [8] 王进. 基于视频的人脸表情建模研究[D]. 杭州: 浙江大学. 2003. [9] Parke FI, Waters K. Computer Facial Animation[M]. Wellesley, MA: A. K. Peters, 1996. 1 – 365. [10] Kähler K, Haber J, Yamauchi H, Seidel H-P. Head shop: Generating animated head models with anatomical structure.[J] In: Proceedings of the ACM SIGGRAPH Symposium on Computer Animation. New York: ACM Press, 2002. 55 – 64. 27 28 29
本文档为【人脸建模软件 毕业论文&#40;初稿&#41;】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_614050
暂无简介~
格式:doc
大小:157KB
软件:Word
页数:38
分类:企业经营
上传时间:2017-11-14
浏览量:16