手嶌葵拯救世界

如果说,手嶌葵是六年前的《地海战记》迄今为止给人们留下的唯一记忆的话,同样的评价送给《虞美人盛开的山坡》恐怕也没多少人会提出异议。然而必须承认,宫崎吾朗的二次登场的确令人耳目一新,看似俗套的少女漫画情节,影片最终展现出的信息却远超出这个范畴。毫无疑问,我们都被影片和她的主题歌声完全治愈了。

仅从观影的角度来说,影片的主线情节可以说毫无新意,即使单是吉卜力在近二十年里也已拍了不少类似的主题,观者可能会感到比较乏味。不过如果换一个方向,会发现影片丝毫不含蓄地表达着一种积极向上的氛围,这一点却是同类型片中所少见的。正如《萤火虫之墓》展现给我们一个焦灼的日本一样,《虞美人盛开的山坡》所展现的是短短二十年后一个全新的社会。许多中国人都对五六十年代的日本感兴趣,以至于有关彼国六十年代经济腾飞的著述迄今都颇受欢迎,然而恐怕许多人(包括我)至今都为此感到困惑,如今幸好一部2011年本土票房冠军的影片能够给我们以管中窥豹的机会。

故事原设于公元1963年,恰好是东京第十八届夏季奥运会的前一年。阿海和阿俊几乎在同一时间内都遇到了“人生的重要挑战”,一是“拉丁楼事件”,二是关于自身的身世之谜。然而二人自始至终都未言放弃,一方面成功使得作为历史见证的活动大楼免遭校方为了“迎接奥运”而进行的拆毁重建;另一方面,同时也颇具戏剧性的是,历史真相的唯一见证人恰好在片末出现,吐露出了阿俊身世的秘密,并且终于卸下了重压在两人身上的历史包袱。如果仅仅从青春爱情故事的视角去鉴赏影片,有些情节可能经不起推敲,于是宁愿称之为一种朦胧的、尚未成熟的情感加以附会,但叙事手法上就显然比不上早年的《侧耳倾听》。事实上,从《地海战记》中我们就可以发现,宫崎吾朗的思想深度其实不亚于老爹,广度上则可能要更甚一些。然而他的劣势在讲故事的能力上,导演没能像上一辈的几部经典作品(当然宫老也并非只是传说)那样能够抓住观众,这种小遗憾现在看来恐怕仍然是不可避免的。

不过,导演真正希望传递的信息可能不止于此。其实,真正令人惊讶的是片中人物所共有的思维方式。例如,作为全剧线索的“拉丁楼事件”,即使在争辩双方矛盾非常尖锐的情况下,依然能够齐心协力维护大家得来不易的自由。学生们甚至喊出了“少数服从多数,即是多数人对少数人的暴力”这样颇具智慧的政治口号:这些桥段无一不体现着当时日本社会的整体风貌。另一方面,阿海和阿俊都是非常严肃地看待两人之间的微妙关系,哪怕是后来所谓的“兄妹疑云”,也没有发生任何情绪化事件,相反二人都在尽力追求真正的谜底:相比之下,在五十年后的现代社会,这样的“死理性派”是否太少了点呢?

如果对故事的所有事件追根溯源,则要归结于立花洋和泽村雄一郎两位长辈在战时的先后离世。阿俊每天驾着拖船驶过阿海家门前的一片水域,不经意间发现少女每天准时升起祈愿平安的U.W信号旗,于是撰下诗篇并发表在校园刊物上:

少女扬起了旗帜  何故  要将思念寄语晨风  呼唤著远方  伴著一时心血来潮的老鸦  少女啊  那藏青色围绕下红白相间的旗帜今日也在风中飞扬

命运就那样巧合。阿海偶然读到诗文,从此记住了松间俊这个名字,也为二人相识奠定了命运的基础。最后,唯一历史亲历者小野寺善雄的出现,使得尘封十余年的故事最终浮出水面,拖船缓缓驶向岸边,夕阳下的阿海和阿俊终于如释重负:对阿俊而言当然是得知了自己的真实身世;另一方面则包含了阿海对父亲的怀念;而当下乃至未来的意义则是不言自明了。片末,阿海完成了人生中迄今为止最为宁静的一次升旗,镜头回到姐姐的那副画作,正是不远处水域上航行的那艘拖船,船头也挂起了“答语U.W”。对导演来说,战后的日本社会长期受到历史遗留问题的困扰,而同样作为战争受害者的普通民众则受之更甚:人们需要通过某些方式得到彻底解脱,才能坦然面对未来并开始新的生活。实际上,六十年代的日本国民不仅做到了,而且还比其他亚洲国家要出色的多。或许这才是导演的真正意图:唤醒国民对美好时代的回忆与憧憬,而且不应仅仅是怀念而已。

手嶌葵的歌声在片尾响起,其实是翻唱自森山良子在七十年代的一首老歌《さよならの夏(告别之夏)》,宫氏招牌式的完美结局,在手MM的伴奏下逾显动人了(也彻底填补了影片末尾与《侧耳倾听》之间存在的思想差距)。

附歌词:

光る海に かすむ船は

さよならの汽笛 のこします

ゆるい坂を おりてゆけば

夏色の风に あえるかしら

わたしの爱 それはメロディー

たかく ひくく 歌うの

わたしの爱 それはカモメ

たかく ひくく 飞ぶの

夕阳のなか 呼んでみたら

やさしいあなたに 逢えるかしら

だれかが弾く ピアノの音

海鸣りみたいに きこえます

おそい午後を 往き交うひと

夏色の梦を はこぶかしら

わたしの爱 それはダイアリー

日々のページ つづるの

わたしの爱 それは小舟

空の海をゆくの

夕阳のなか 降り返れば

あなたはわたしを 探すかしら

散歩道に ゆれる木々は

さよならの影を おとします

古いチャペル 风见の鶏(とり)

夏色の街は みえるかしら

きのうの爱 それは涙

やがて かわき 消えるの

あしたの爱 それはルフラン

おわりのない言叶

夕阳のなか めぐり逢えば

あなたはわたしを 抱くかしら

(完)

Comments

Kinect的三维重建(1)

有关Kinect应用开发正日新月异,稍有懈怠就会被远远甩在身后。不过,Kinect目前带给我们的仍只是一个充满无限可能的远景,正如App store能吸引年仅11岁的开发者一样,Kinect未来将对“全民开发者”产生重要推动作用。另一方面,一些基于Kinect的应用研究仍颇复杂,主要是因为一些关键环节的滞后而导致的。2011年的siggraph talks上,KinectFusion首次展示了实时、廉价、轻便的室内场景三维重建,使得我们向着“无处不在的数字化”迈进了一大步。该项目主要由微软剑桥研究院的研究人员发起实施,研究小组目前公开发表了两篇文章:

Shahram Izadi, David Kim, Otmar Hilliges, David Molyneaux, Richard Newcombe, Pushmeet Kohli, Jamie Shotton, Steve Hodges, Dustin Freeman, Andrew Davison, and Andrew Fitzgibbon, KinectFusion: Real-time 3D Reconstruction and Interaction Using a Moving Depth Camera, ACM Symposium on User Interface Software and Technology, October 2011

Richard A. Newcombe, Shahram Izadi, Otmar Hilliges, David Molyneaux, David Kim, Andrew J. Davison, Pushmeet Kohli, Jamie Shotton, Steve Hodges, and Andrew Fitzgibbon, KinectFusion: Real-Time Dense Surface Mapping and Tracking, in IEEE ISMAR, IEEE, October 2011

除了Microsoft Research外,国内外大量机构都借助Kinect进行相关研究。仅就实时场景三维重建这项应用而言,由开源机器人研发公司Willow Garage在2011年发起的Point Cloud Libary (PCL)就吸引了全世界数十家著名科研机构参与、十余家公司提供经济支持。PCL是一项集点云获取与处理、滤波、特征提取、关键点标定、表面重建和点云配准以及点云融合等功能为一体的开源点云处理库,PCL使用OpenNI作为系统IO接口,实际成为KinectFusion的开源实现项目,该项目的相关论文发表在ICRA2011上。

上述文献可以说是迄今为止有关Kinect的三维重建应用的最佳切入点了。应注意的是这两篇文章讨论重点的区别,前者先是对KinectFusion整个项目进行了流水式说明,随后解释了文中采用的经典算法的GPU实现,开发者可能会比较感兴趣;而后一篇文章则重点讨论了新的并行算法的形式化描述和性能分析,这部分可能会更吸引一部分研究者。我们将采用一种自上而下的方法先对这两篇文章进行简要介绍。

 概述

有关Kinect的结构光技术读者可以参考这篇文章或直接去Google下PrimeSense的专利,这里不再赘述。不过,尽管Kinect在获取深度图方面几乎是达到了性能与质量的完美结合,但仍无法避免深度图中大量抖动的产生,如果我们直接对单张深度图进行bilateral filter双边滤波然后重建出网格模型,会发现重建出的模型表面质量较低,甚至出现孔洞的情况。更重要的是,单张深度图能够获得的只是模型在某个视角下所展现出的一部分,而非表示完整的模型。因此,如何改善基于Kinect深度图的模型重建质量,并实现物体的完整重建成为该项技术的关键。

KinectFusion的首要任务就是克服该难题,它允许用户手持Kinect设备在室内场景自由移动,并实现场景的高质量三维重建。同时,KinectFusion还提供了精彩的AR应用,包括前景、背景和人体的分割与重建、以及AR世界中的多点触摸识别技术。

场景重建

基于上述需求,KinectFusion允许用户手持Kinect设备自由探索室内环境,系统将自动跟踪Kinect摄像头的6DOF姿态,然后融合不同时序的深度图数据并重建出场景的全局模型。由于视角的不断变化,Kinect反馈的深度图也会发生改变,这里采用了类似图像超分辨率技术对深度图进行了细节优化,从而提高模型的重建质量。最后利用Kinect自带的RGB数据进行场景纹理映射。

首先如何利用单Kinect摄像头去跟踪它自己的6DOF姿态?这里采用点云模型的刚性配准对齐来计算摄像头在空间中的6DOF变换,点云配准首选经典的ICP[Besl92, RusinKiewicz01]。之前需要将深度图像数据变换至摄像机的空间坐标系中,并计算其对应点的法线信息;然后逐帧采用基于GPU的ICP实现进行模型配准和6DOF计算;在重建部分,KinectFusion并没有直接融合点云或生成网格模型,而是采用了[Curless96]的体集成算法,最终在全局坐标系中生成一个三维体素网格并进行不断更新,每个体素内最终保存了一段时间内从该体素到物理表面上某一点的平均距离。最后使用Raycast给出隐式表面的渲染结果,另一方面,以摄像机位置作为视点做Raycasting,同样能够得到一个具有真实细节的高质量的合成深度图,然后再对其进行下一轮ICP迭代。这就允许我们能够利用合成深度图与下一帧的深度图进行配准,使重建结果的精度不断提高。

具体算法实现采用了CUDA并行架构,算法基本流程如下:

1)深度坐标变换,对于每个像素启用一只CUDA线程,给定一个Kinect红外摄像头的内部校准矩阵K,使用如下公式

计算坐标变换;相应的顶点法线则直接取其右、下邻向量的外积,并进行归一化。时间i时的6DOF摄像机姿态使用一个刚性变换矩阵T表示,其中T包括了摄像机的旋转矩阵R和平移矩阵t。变换后的顶点和法线通过T即可再变换至全局坐标系中。

2)摄像机跟踪,该部分的主要目的就是计算6DOF姿态。核心的ICP即迭代最近点算法,首要是需要逐帧计算不同朝向的点集的相关度。这里采用了projective data association方法计算相关度。

3)体集成,针对已配准的点云数据,需要执行后续的融合处理,这里采用了经典的[Curless96]体集成方法融合这些点云数据。

4)光线投射渲染,采用光线投射渲染前步生成的隐式表面。

上述整个管线均采用了并行GPU实现,在下文中,我们将重点解析上述算法的CUDA实现细节。

Comments

TangleTracer(Basic edition/B) 1.0 Beta开源发布

TangleTracer是一个实验性光线跟踪渲染平台,目的在于为真实感绘制技术的初学者提供完备的学习例程和友好的实验接口。系统设计思路主要源于Kevin Suffern的《Ray tracing from the Ground Up》一书,同时部分参考了著名的真实感绘制圣经《PBRT 2nd》。从今年三月中旬起我们就开始了前期的技术储备工作,该项目由四月初正式开始,截至目前完成代码近9万行,系统框架基本完善,实现并调试通过了440个demo或Kevin书中的习题(这部分代码超过4万行)。与K书中提供的原型系统不同,项目开发平台选择了Microsoft Visual Studio 2010和Qt framework 4.7.3,为快速开发提供了良好基础。 由于系统和部分框架来源于K书,我们循例采用GPLv2开源发布。此次发布的主要内容是系统的代码部分,为便于大家测试,我们稍后会提供基于win32平台的二进制版本(目前正在进行兼容性测试),运行系统内置的全部例程需要同时满足以下条件: 1.下载例程所需的纹理包:http://www.raytracegroundup.com/downloads/TextureImages.zip%EF%BC%9B 2.下载例程所需的模型包:http://www.raytracegroundup.com/downloads/PLYFiles.zip%EF%BC%9B 3.确保纹理包的TextureFiles目录和模型包的PLYFiles目录与程序二进制文件位于同一目录下; 4.部分模型需要下载stanford的原始文件并进行替换(具体请阅读README及代码注释):http://www-graphics.stanford.edu/data/3Dscanrep/%EF%BC%9B 此次发布的是TangleTracer的Basic edition/B版本,其目的在于提供思路清晰的CPU渲染技术,但实际渲染性能较低。我们正在进行系统的并行迁移实现,并力求在下半年提供TangleTracer的GPU edition/G版本。详情请关注项目github主页:http://mp77.github.com%E3%80%82

Comments

《武训传》的现实意义

我对所谓的“国产禁片”并不感冒。其原因在于真正要被禁的影片根本不可能启动拍摄,而已经拍出来的所谓“禁片”注定是褪去了核心思想的阉货,顶多被允许在课堂上当教学片放,还需得是遮遮掩掩的那种。不过,当听到《武训传》要出数码修复版时又不禁小兴奋了一下,突然对这部筹划于上世纪四十年代初、成片于1950年并在中国当代史上扮演了重要角色的“第一禁片”十分好奇起来。尽管寻找片源时颇费了一番周折,好在终于在周末第一次看完时长197分钟的全片。

使我对该片产生好奇的第一个问题是,《武训传》在今天仍不失影响力,那么是因为传主事迹确实称得上“感天动地”、堪得流芳百年?还是由于该片后来“意外地”成为了首个思想文化批判与改造运动的漩涡中心,以致于迄今为止仍有许多人们念念不忘,难以释怀?我们知道,影片创作最初源于民国著名教育家陶行知先生对“武训精神”的推崇和力行,并随段承泽和漫画家孙之俊两位先生的《武训先生画传》而广为人知(1950年李士钊和孙之俊又重新出版了一套《武训画传》)。据《武训画传》载,武训(武七)幼年丧父,与母亲以讨饭为生,年少时先后在自己的姨夫家和李地主家做工,饱受欺辱。由于没上过学,被地主骗光了三年工钱。经过几番沉重打击后,武训意识到只有读书才能改变穷孩子们的命运,才能真正帮助穷人摆脱这种不公正。经过近四十年行乞的勤劳与节俭,武训先后创办“崇贤”、“杨二庄”以及“御使巷”三家义塾,免费供贫困子弟上学。武训事迹轰动山东,最终得到清廷嘉奖并授予“义学正”。总的来说,武训事迹是真其人、确其事的贫民教育典范,理应作传以传后世。不过,当漫画版传记到银幕则产生了原因复杂到令人难以理解的后果。

昆仑公司出品的《武训传》成片于1950年,实际上影片曾断断续续拍了几年时间,周恩来等领导人都曾经对拍摄中的剧本进行了修改和建议。不过,影片的编导对原《画传》的核心思想进行了改编,我认为这恐怕是为创作团队带来日后横祸的重要原因,但也不得不佩服孙瑜导演及其他主创对待文艺创作的理性态度和勇气。影片新引入的一条主要线索是前太平军周大的经历,北伐失利的周大与武训一同在张举人家里做工,最终与武训共同逃离,不过他的选择和武训大相径庭,后者选择兴办“义学”,而周大则去做了响马,其理想是将地主“抢光”、“杀光”,有意影射清末数量庞大的农民起义运动。影片中武训的态度很清楚:“读书改变命运”,一味烧杀并不能解决问题。但在片末,农民运动达到了高潮,响马们履行诺言回来复仇,武训看着一切只能又标志性地挠了挠头,但影片没有给出事件的最后结局。批判者指责影片推崇“改良”,在某种程度上说并不完全错误,同时这也是至今影片仍存争议的原因。不过,关于所谓的“路线”争执是自百年前至今都确实存在的,只是取决于我们怎样对待这种应当仅存于学术层面的争论。

然而影片中武训的担心也未必没有道理,当狂热到丧失理性之时,原本就缺乏思考的人们会变成怎样可怕的怪兽?君不见,当代中国又横遭了多少磨难?我对影片与《画传》的一处细节差别印象深刻,首先片中强调“张举人”的读书人身份,后来又编出什么“没收武训所积造文昌帝庙,以明读书人之修身齐家的志愿”?读书人是不完美,但人始终无完人,影片着重渲染了一干“读书轻义”的当权者,与武训到处跪求贫困家庭送子入学形成了明显矛盾,尽管片中也给出了几个开明乡绅的形象。而当武训听到对“学而优则仕”的解释时又大为困惑起来,是顺带批评了当时的知识分子么?可见,影片所带给人的思考余地是非常广阔的。

现在回去看《武训传》所遭遇的不公正待遇,我认为这正是影片创作者们的担心终成现实的结果,甚至可能丝毫不出他们所预料。当然恐怕有更多的人宁愿相信这些卓越的文艺创作者们是犯了某些错误,至少是某一“特定历史时期”下的错误。但我始终觉得这些说辞只会是无力面对历史的辩解之词,看似轻描淡写,实则是一个讳疾忌医的病人罢了。

最后,针对《武训传》的当代史研究在最近30多年里已经著述颇丰,我认为要了解一段历史,必须行史学家的态度去阅读文献,在此之前不应轻下结论,否则必然是一叶障目。本文不提非官方的野史故事,理由一是资料真假难辨,有失严谨;二是希望现今的人们能继续从本质上对武训及这部影片展开讨论,当然这种讨论必须是完全理性的、有意义的观点和看法。尽管我们长久以来避而不谈,但历史终究会使我们不得不去思考,今后的路朝哪里走。

Comments

参数化设计/建模及其在艺术创作领域的应用前景

一、概述

迄今为止,参数化设计/建模仍代表一种理念,尽管这种理念已经经历了CAD/CAM近五十年的发展历程。系统化的CAD/CAM技术包含两种基本思路,一是使用二维几何原语如点、线或样条表示三维物体,如Bezier、De Casteljau以及Sutherland这些先驱们的工作;明暗处理的需求接着被提出,从而出现了早期着色模型的研究(本文将不涉及这部分内容);即使是目前最广泛使用的Nurbs,也是A.R. Forrest早在1980年就已经完成了。

另一种思路是使用体素构造表示(CSG)进行实体建模(该技术实际上也诞生于60年代初期),其基本方法是使用一组基本几何体,如球、柱体、椎体等,对其执行交、并、补等布尔运算序列,从而构建复杂三维物体,通常再使用B-Reps表示最终生成的三维模型。这种方法由于能够保持模型拓扑的欧拉示性数V-F+E,有助于满足三维物体的基本几何特征,因而得到了广泛应用。

现在看来,CAD/CAM的关键技术似乎早在30年前就已经比较完整了,那么继续该领域的研究还存在哪些意义?事实上,CAD/CAM目前仍面临许多瓶颈,这些瓶颈已经影响了目前广泛采用此类技术的汽车制造、电子和建筑等行业的进一步发展。例如面向三维模型的可编辑性,模型编辑的目的通常有两类:一是用户设计意图发生变化,需要变更现有设计;二是模型的适用条件发生变化,不得不做出调整以适应新变化:如某些工业组件所面临的不同规格需求。在参数化设计提出之前,针对三维模型的编辑主要采用直观交互式的方法进行,其复杂程度甚至超过最初的建模过程。一些行业专家分析,模型编辑的主要难点在于该过程既要保持原组件的局部特征,还要适应新的条件,同时还要确保这种编辑不会影响组件之间的相互关系;特别重要的是,在整个设计、建模、编辑的过程中要保证一定的数据精度。提高可编辑性一度成为现有CAD/CAM技术的重要研究方向。

二、参数化设计的发展和现状

参数化设计的最初目标就是解决CAD/CAM的上述问题,并取得了一定成果,特别是在建筑业。参数化设计的本质就是使用一系列参数定义三维模型的基本特征,包括基本尺寸、各组件间关系等。在一些文献中,参数化设计也被称为关系型建模或是变量化设计。在参数化设计中,建模原语通过一组参数表示,如使用位置、长度和方向参数表示空间线段,而如果仅涉及到这部分,那么参数化设计似乎与传统的交互式设计并无不同。更进一步,为了保证模型在一定条件下的可编辑性,参数化设计要求用户建立建模规则的参数化表示。如AutoDesk推出的AutoLisp语言,实际上是通过编写脚本制定规则,而把输入参数转化成三维模型的应用在目前已经十分流行了。然而对于绝大多数设计师而言,学习编程语言其实没有太多必要,同样对于一些复杂模型的构造,编程实现会真正意味着缘木求鱼。因此参数化设计需要进一步的形式化、领域化和直观化,才有可能被大多数设计师所接受。

“约束”是参数化设计的一个重要概念,不过其提出要比“参数化设计”本身还早。约束表示针对一个或一组实体的行为关系限定。实体可看作是三维模型的一个组件,实体行为则代表该组件在不同参数下表现出的状态。例如”一组线段相互平行、垂直或共线”就是一种约束描述,每条线段受相应参数控制其行为,而各线段的参数却受到“平行、垂直或共线”的关系限定。在带约束的设计和建模过程中,无论是施约束端还是受约束端,都需要得到完整的参数列表才能进行,由于约束的存在,某些参数实际上需要通过“推理”进行估计和计算,这种推理估算参数的过程在很大程度上影响了建模效率。当前应用中普遍存在两类约束:几何约束和物理或称工程约束。平行、垂直、共线、相邻、尺寸等都属于几何约束,此外包括一些物理方程、条件关系等则属于后者。这类方法需要用户在建模初期提供实体类型、空间位置和尺寸参数,然后通过一些具体方法描述实体关系,如前面所述的编程脚本。

1982年,Gossard和Light首次提出了“变量化设计”的概念。此后十年间,由于几何造型、自由曲面和实体建模技术的迅速发展,出现了愈多针对交互性及可编辑性的改进需求。大量工作开始致力于该领域中,如前面介绍的变量化编程的提出,通过编写一段程序脚本控制建模过程,这种方法实际上并不能有效解决存在的问题。而为了保证用户设计意图的准确实现,直观交互通常是必须的,因此提供领域化的参数化设计工具是较为合理的选择。

1、基于时序的约束建模,即记录用户交互式建模时产生的参数集时序变化,在修正设计时,通过随机选取并更改时序中的参数变化内容,实现参数化设计。这种方法要求模型的构建过程保证良好的层次性;

2、变量几何和变量化设计,即通过构建基于参变量的建模公式进行参数化设计,例如利用简单解析式创建二次曲面。对于复杂模型而言,其构建公式的有效性就成为实现参数化设计的基础;

3、基于规则的变量化设计,前面两种方法在实际应用中很难真正实现,出于实用的考虑,人们首先建立基本规则库,利用人工智能方法进行推理并最终得出约束条件。例如,对于两个实体而言,系统内置了有关实体位置参数的规则,通过推理即可得出实体间的相对位置关系(对于直线段可能就是平行、垂直、共线、相交或其它情况)。实际上,该方法目前仍是参数化设计的研究热点之一;

4、基于特征的参数化设计,从视觉上看,特征指模型在某些观察角度下所呈现出的特殊现象。而在参数化设计中,特征包括了与其相关的实体、参数和关系式,特征是相对于变量或规则的更高级别的语义描述,例如描述物体表面有一处“凹陷”,这就是一种特征。但是,良好的基于特征的设计需要精心设计特征库。

三、参数化设计的应用现状

尽管参数化设计目前已经深入工业设计和制造业,但最令人瞩目的则是其在建筑设计领域中的应用。应注意的是,由于建筑设计本身带有艺术气质和时代特征,引领前端的通常都是著名研究机构或设计公司,而更多的从业人员仅仅是采用稍成熟方法满足需求即可,因此参数化设计在该领域存在着两种截然不同的应用思路。

毫无疑问,最早提出的变量化编程已经为大多数CAD建筑设计师所知了,如AutoLisp。另一方面,参数化设计在这一阶段的主要工作是实现2D和3D的协同设计,具体方法可以是时序法或变量几何。在这期间许多计算机科学家努力向领域专家们推荐各种工具和应用,如William Mitchell于1987年推出的《The Art of Computer Graphics Programming. A structured introduction for Architects and Designers》,书中使用了流行的Pascal语言描述建模脚本。

在许多人看来,上述编程建立三维模型的应用过于抽象,可行性极低。事实亦如此,变量化编程目前已经成为参数化设计领域的非主流技术,而对我们来说更加常见的可能就是诸如ArchiCad或3DStudio Max:直观的交互式界面,以及大量参数输入对话框,该模式至今仍占据绝对优势。后者的缺点是,用户很难针对复杂模型整体进行参数化考虑,除非建模阶段存在非常精妙的参数设计,而这往往是不现实的。一种解决方法是确保层次化建模,例如K. Martini试图采用面向对象程序设计中的层次化类结构模拟建模过程。由此我们可以联想到一系列层次化方法,如集合、树等;另一方面,考虑到层次化建模的可行性尚未得到证明,我们还可以考虑使用图表示参数化设计中实体之间的约束关系。针对这方面的讨论目前仍是非常开放的问题。

四、艺术创作中的参数化设计思想和实践

首先,这里所说的艺术创作实际上包括前文提到的工业设计;另一方面,我们希望能在更多的艺术设计领域引入参数化的元素,其目的在于:1、大部分现有的艺术创作实际上与商业应用相关,原创效率和大规模应用能力将成为关键的风险因素;2、参数化设计为创作前所未有的艺术形式提供了新途径,而并非字面上的对艺术创作施加“约束”的意思。

达芬奇的《维特鲁威人》堪称把建筑学和人体解剖学相结合的传世名著,而这种艺术上的联系同样也反映到现代CAD/CAM技术中。香港中文大学的王昌凌(Charlie C. L. Wang)就在现代服装设计中引入参数化设计技术,并提出了一种新的基于人体特征的参数化设计方法。该方法从人体点云中提取相关特征,并在参数化模型(注意这里的参数化与“参数化设计”的区别)的基础上使用参数化设计创建新的模型。其中人体模型的参数化包含两个主要阶段,首先使用激光扫描仪获取人体点云,根据语义特征提取并重构人体的特征线框;其次,对人体网格曲面的对称信息进行建模,在特征线框上通过曲线插值生成Gregory曲面片。然后利用一种体素算法在G1连续的曲面上添加细节点云;最后再调整网格曲面的对称性。在完成人体模型参数化后,根据用户输入参数采用参数化设计方法把样例模型映射至参数化模型中,同时对样例模型的选用需依据相关策略进行。与普通的数值插值函数相比,该方法具有较低的出错率,能够保证参数化模型的正确性。基于正确的参数化模型,即可在人体上自动导入使用参数化设计方法在样例模型上设计的服装模型。

事实上,关于服装的参数化设计在最近十年已成为CAD的热点之一,并取得了一些研究成果,但仍鲜见规模化应用。而对于参数化设计技术本身而言,能否继续扩展其应用范围、并在此过程中完善自身的方法论,将成为CAD发展的一个未知数。不过,进一步扩展出有效的杀手级应用则是当务之急。

Comments

新海诚的云和他的孩子们

克查尔特把所有的记忆寄托在歌声里留下,歌声将改变形状一直流传着,在空气的振动中不断下去,不知不觉融合在我们的身体,如此在世界的某个地方永远留存下来。

[singlepic id=45 w=480 h=320 float=]

影片《追逐星星的孩子们》充满吉卜力式的风格和桥段,乍一看让人觉得影片监督和宫老有着千丝万缕的联系,然而漂浮在天空的云却在不断提醒着我们完全不同的事实。新海诚把英文片名定为《Children who Chase Lost Voices from Deep Below》,相比于日语片名恐怕更贴近故事情节,而就后者来说,来自雅戈泰的迦南族人瞬恐怕是唯一真正“追逐星星”的孩子,其余的主角么,当然是为了寻找位于菲尼斯·特拉生死门另一端的灵魂了。本片正是一部讴歌生命的唯美之作。

事实上,这个星球上的每一个人在新海诚眼里都是影片所讲述的孩子,自出世起就受到了来自雅戈泰神明的诅咒,从而死亡就成为生命必须的部分,灵魂最终被融入雅思特拉里。然而总会有许多人无法真正面对死亡,甚至希望故人能够得以重生。生命之船谢库纳·威玛纳的回应是要求一个完整的肉身以及一只许愿人的眼睛——这恰恰体现出一种绝对公平,所谓的复活也根本毫无意义。人类所需要做的,即是背负着愈来愈多的离别与思念度过一生,也是女主角明日菜最终意识到自己执意进入雅戈泰的原因:生活除了日复一日的单调重复,其余的就是想念了。毫无疑问的是,这次生命之旅让女主角卸下了曾经的包袱,从此更加乐观地面对生活。付出沉重代价并再次失去理莎的森崎老师也逐渐走出了十余年前亡妻的阴影。心也彻底摆脱了失去哥哥瞬的心结。

而对于另一个男主角瞬而言,他原本就属于跟随克查尔特在数万年前进入地下的人族后代,尽管雅戈泰人都对生命的时间线充满敬畏,而在瞬的心里,看一眼地上世界夜空中的繁星,以及那个潜意识中似曾相识的人,已是他在临死前最后的愿望。而当这种情绪达到最强烈时,歌薇丝感应到了另一个世界中的心灵,从而带瞬来到了这个世界,在临死前对明日菜进行了生命的祝福,故事也就此展开。令人感到奇怪的是,尽管瞬坦然接受了死亡结局,但依然在命运中破除了雅戈泰人的世代约定:即永不允许地上人进入这个世界,而是选择追求自由——这也是人类无止境地追逐繁星的真正意识。这恐怕是新海诚对生命从另一个角度的诠释。

至于片头提及的地上人的堕落,故事并没有在此展开讨论,恐怕是脚本原始设定上的一个小失误。然而《追逐星星的孩子们》给人以强烈的宫崎骏式的感官,同时又夹带了《EVA》的世界观(威达之水 vs LCL?),这让许多对新海诚充满期待的资深动漫迷们感到无法接受。但是无论如何,观影的过程是让人感到无比舒适的。

附惊艳片尾曲歌词《Hello Goodbye & Hello》:

Hello Goodbye & Hello

相遇 分别与重逢

词曲:熊木杏里

编曲:清水俊也

歌:熊木杏里

君(きみ)に会(あ)って

今(いま) 君(きみ)とさよなら

Hello goodbye and hello

そして君(きみ)のいない

この世界(せかい)にHello

本当(ほんとう)のさよならを

知(し)らなかったあの时(とき)

壊(こわ)れゆく心(こころ)はずっと

君(きみ)を探(さが)してた

もしも届(とど)くのならば

伝(つた)えたかったことがたくさんある

すべての気持(きも)ちで

君(きみ)の笑(え)み颜(かを)を

绝(た)やさずそばにいたいと誓(ちか)うよ

Hello goodbye and hello

君(きみ)に会(あ)って

今(いま) 君(きみ)にさよなら

Hello goodbye and hello

そして君(きみ)のいない

この世界(せかい)にHello

思(おも)い出(で)が温(ぬく)もりは

君(きみ)へと続(つづ)く糸(いと)

たとえても见(み)つからない

それだけを见(み)つけた

失(な)くしたくない愿(ねが)い

一番(いちばん)

远(とお)い星(ほし)だと思(おも)ったよ

空(そら)は広(ひろ)がる

明日(あす)のように

果(は)てないけれど手(て)を伸(の)ばしたいよ

Hello goodbye and hello

君(きみ)の事(こと)を

いつも忘(わす)れないよ

Hello goodbye and hello

そしてこの道(みち)を

歩(ある)いてゆくなあ

君(きみ)を好(す)きになった时(とき)から

始(はじ)まていたこの旅(たび)…

Hello goodbye and hello

君(きみ)に会(あ)って

今(いま) 君(きみ)とさよなら

Hello goodbye and hello

そして君(きみ)のいない

この世界(せかい)にHello

Hello goodbye and hello

君(きみ)に会(あ)って

今(いま) 君(きみ)にさよなら

Hello goodbye and hello

そして君(きみ)のいない

この世界(せかい)にHello

Comments

有关Beta 2和Kinect for Windows商用前瞻

在本月初Kinect正式发布一周年之际,微软公司副总裁Frank X. Shaw在公司官方博客上发表纪念文章“Feeling the Kinect Effect”,并透露Kinect的商用计划“Kinect for Windows commercial program”,该项目将于2012年初正式公布。文章称专门负责商用计划的团队已获得来自超过25个国家的知名公司共超过200项商业应用申请,这些应用覆盖了20多个不同领域,这恐怕会令即将到来的2012年成为名副其实的“Kinect年”。

而在上个月27号,微软注册了kinectforwindows.org域名并将其作为Kinect for Windows项目新的官方网站,紧接着Kinect for Windows SDK 1.0 Beta 2在本月5号正式发布。相较于8月份后就再没更新过的Beta 1,新版本SDK在以下功能上进行了持续改进:

1、骨骼跟踪功能得到显著增强,在跟踪精度、计算和传输性能上有了明显提升。此外骨骼跟踪现在能够正确支持多核处理器,在同时使用2个Kinect时,开发人员也可以指定专门用于骨骼跟踪的设备了;

2、API现在能够对设备的状态进行有效检测和管理了,例如device unplugged, device plugged in, power unplugged等,这样应用程序就能在系统从待机状态恢复时自动重新连接设备了。一个很好的程序示例被写进了新版本的Shape Game Demo里;

3、在WPF程序中使用语音功能的开发人员不需要从额外的线程访问DMO了,现在可以直接从UI线程创建KinectAudioSource,从而能够简化现有工程的代码。

4、新的驱动程序、运行时系统和SDK现在能够在Windows 8 Developer Preview中使用了。

5、现在能直接创建64位应用程序;

6、NuiImageBuffer被新的INuiFrameTexture代替,新定义在MSR_NuiImageCamera.h中,现有项目不再需要引用NuiImageBuffer.h了;

7、安装目录的结构进行了调整,现在的安装路径使用环境变量%KINECTSDK_DIR%定义,默认值为C:\Program Files\Microsoft SDKs\Kinect\v1.0 Beta2;

8、示例代码的更改包括:

一个新的C#程序示例:KinectAudioDemo;

示例程序现在被默认安装在C:\Program Files\Microsoft SDKs\Kinect\v1.0 Beta2\Samples,你需要Unzip以便查看源代码,而这里建议将源码Unzip到Program Files以外的目录去;

9、驱动程序和运行时系统的稳定性和性能进一步提升,尤其是在托管API层

总的来看,Beta 2并未提供关键功能上的改进,更多是对现有问题的修正。此外,备受瞩目的Kinect for Windows杀手级应用仍未出现,社区反馈是目前很多未公开的商业项目在尝试OpenNI,对MS SDK反倒比较谨慎。不过从长远角度考虑,MS SDK在开发社区、系统平台和资源支撑方面拥有众多优势,明年商业化后必然会率先占据有利位置。由此联想到近期在4S上被热炒的Siri,看来自然交互的春天真的离我们不远了。

Comments

从SIGGRAPH’11看《Rango》

一年前,我们曾介绍并讨论了展示在siggraph’10 Talks上、作为Disney’s 50th Feature Animation的《Tangled》。在今年8月7日至11日的温哥华siggraph’11大会上,工业光魔携首部动画长篇《Rango》成为了“Let there be light”(加点儿灯光?)单元当之无愧的主角(尽管去年的Tangled和今年的Cars 2同时均有入选)。

《Rango》中文译名“兰戈”,由执导了前三部加勒比海盗系列的Gore Verbinski担任导演,该片作为工业光魔在Feature Animation(FA)领域的处女之作,使得后者在首次试水FA后即登上了巅峰。影片主要讲述了一只不慎被遗失在西部荒漠中的蜥蜴,历经艰难、最终找回自我的故事。影片无论在情节构思、画面、配乐上的精细程度都堪称前所未有。本文依旧从Siggraph’11上的三篇文章出发,试图探索堪称计算机图形学史上迄今最先进的工业级CG技术。

使用面向FX工具制作动画角色和光照特效

在拍摄初期,工作人员在虚拟转台上测试了整个ILM的材质库,其意在测试材质的环境光遮蔽和阴影效果。然而在影片中,除了60名主要角色以外,还需要大约1000个道具。为了简化这部分工作,这里还使用了部分置换贴图以丰富材质信息。同时,再将这些材质用于不同环境的转台程序下,以便迅速发现问题并制作新的Shader;

过去通常使用光板或参考集设置光线,然而《Rango》则例外,这部分影片中引入了新的方法。每一组镜头中的光照设置非常简单,即包括关键光、环境光、反射光三部分,该方法被用于全部的室外光和一些室内光。技术人员使用Digital Matte部门开发的虚拟集渲染器创建环境光和反射光映射,而非直接进行360度捕获。上述映射被用于非静止的、处于快速移动物体中的反射/折射光精确表示。设置灯光时,关键光通过一个受可切变天空顶约束的远程光Shader定义,并通过复制角色的远程关键光,达到较好的交互和阴影效果。同时,用户还可以通过旋转整个装置以达到尽可能广泛的变化,或只旋转关键光以改变复制光,或通过特定的扭曲修改角色局部的复制光。

除个别场景外,影片几乎所有的室外场景都使用了前文所述的格式化远程关键光、环境光和反射光装置。该装置包含两个开关:一是激活阳光反射卡片(模拟光晕效果),另一个用于开启基于距离的阴影模糊。

假设你在一个阳光明媚的室外场所,挥动手臂并在一张白纸上映上阴影效果,你会发现当你升起手臂时,阴影边界的模糊度随之逐级递增,这种边界阴影模糊在物理学中被称为“半影”现象。物理学中已经证明,半影宽度除以障碍物至阴影面的距离值约为常数1/112,它同时也是太阳以弧度为单位角直径值。工作人员实现了基于距离的关键光阴影边界模糊并对其进行严格控制,力求在符合真实世界效果的基础上尽可能满足导演对夸张手法的要求。

简易的关键光/环境光设置方法是设置全局光照参数,并将其作为一组镜头的初始光照。整部影片也可以通过该方法初始化并检测通用关键光的特效和镜头效果。每当TD(Technical Directors)布置新任务时,他们就可以通过添加特定的光照效果以丰富镜头。出于对主角显著区别于背景的绘制需要,工作人员对其进行了逐帧细化和调整。

角色合成方面起初的构想十分简单,然而随后愈加复杂,这种复杂程度甚至超过了真实的角色电影。导演对每一个场景均有特定的灯光、编排和镜头要求,还包括变化的气候、照片级真实感绘制(光畸变,正确的燃烧扭曲,热涟波和相机抖动等)。额外还包括了沙漠、指纹、水、尘土等各种细节效果。为此制作团队特组织了一批强大的计算机开发团队,通过创建自定义通用脚本制作了多个工具辅助影片拍摄。

动物皮毛的穿透避免和动力学

在《Tango》中需要对多个鸟类角色建立羽毛模型,而这种羽毛模型通常需要手动放置主要的羽毛茎秆曲线,再在不允许插值的条件下实例化整个皮毛几何体。此外,影片对动物角色的要求还包括了日常姿态、呼吸动作、受风、动量、惯性影响的效果等。这里制作团队开发了一种尽可能保持原设计形态的皮毛动力学模拟和自由碰撞技术。

鸟类的羽毛是通过分层有序叠加的,开发人员应允许设计师能够任意设计皮毛的基本外形、层次结构,且不必处心积虑地避免皮毛穿透问题。设计师通过在角色皮肤上放置引导曲线,以构建基本的皮毛外观,同时在其径向上实例化一个矩形几何框,用户可据此设置宽度、扭曲度、与起始点法线相似度等参数。该四边形面片同时还被用于在绘制阶段实现多种纹理效果。

制作团队共使用了两个实例化的皮毛集合,一是目标集,包括了许多皮毛间的相互穿透效果。二是特征皮毛根集,这部分使用狭长的面片实现,由于其更接近法线方向,故存在较少的互穿透。后者用于对某些动物的皮毛进行初始化和带穿透避免的布料模拟。与[Weber and Gornowicz 2009]提出的复杂方法不同,下一步是使用非身体力设置布料模拟的皮毛。每一个布片的基被限制在一个曲面片上,据此检测面片间的相互碰撞。目标集则是通过布料解析器限制下点接点的受力建立。在模拟过程中,布料面片将面向目标集方向生长、然后由碰撞检测部分避免穿透。碰撞避免的方法可以使用基于三角形或是基于边的排斥方法。在第一步完成后,仍需要进一步对角色动作过程中的皮毛穿透现象进行检测, 同时还要保证对原设计形态的维持。

插值毛发的碰撞精度

毛发的动力学常常是通过引导毛发和成员插值构成的,因此这部分也被称为插值毛发。碰撞精度是毛发模拟技术中最费时的阶段之一,因此通过限制毛发的碰撞精度从而提升动力学性能是非常重要的。在许多情况下,只需要视觉感官上可被接受即可不需增加碰撞精度,遗憾的是,我们的运气往往没有这么好:)

影片中许多动物都穿有衣服,那么即使是一根发丝从衣服布料中伸出来都是不可接受的。然而对整个已生成的毛发集合进行穿透检测和避免也是不现实的:首先,这种技术非常耗时,插值后的毛发往往是引导毛发的成百上千倍;其次,这种方法并不能用于目前的管线设置,因为在模拟阶段插值头发尚不存在;最后,基于物理的碰撞检测方法通常是使用多边形面片,而非Catmull-Clark细分曲面表示,即使是极小的曲面差异也很难保证碰撞检测的正确性。

这里制作团队提出了一个新的穿透修正方法,该方法主要解决的问题包括精度、效率和时间相关性,其主要贡献是对平滑曲面表示进行碰撞检测,沿着毛发生长方向进行连续碰撞检测,并在每一帧进行碰撞检测。该方法最终在影片多处被用到,它既保证了高效率,同时精度也达到了无需进行后期修正的程度。

文中工作人员使用了[Verma et al. 2009]将CC曲面转换为Bezier表示,这种显式曲面允许通过精确交叉查询解决碰撞检测的问题。其次,使用层次数据结构对毛发和Bezier面片进行候选碰撞检测。由于当前配对可能发生了穿透,将毛发的生长方向再移动至其参数空间中的上层部分。通过沿参数化的曲线空间搜索连续毛发-曲面交叉,其中使用Newton法计算毛发和曲面交叉部分。

在穿透避免时很容易造成无法保持原始形态的问题,这里使用了一种简便方法以保持形态,即在穿透避免后使用[Goldenthal et al. 2007]提出的快速投影法修正其差异长度,然后在碰撞精度和应用不可延展间进行迭代,直到满足两方面需求即停止。实际应用中只需要很少的迭代次数即可完成计算。

插值头发绘制时逐步生成的,同时还要同步进行穿透避免计算。因此需要在每一帧进行独立的穿透避免计算(并行处理),这条限制有一定隐患,即可能导致发生时间无干性:毛发可能在连续帧中发生不平滑。这里通过尽量使其朝向生长方向以降低不平滑的程度,尽管尚不完美,但已经足够达到目的了。

总结

《Rango》无疑是siggraph’11大会上一颗耀眼的明珠。与去年的《Tangled》相比,该片的制作成本要少一亿三千万美元(估计成本一亿三千五百万),前者更是花费了Disney Animation Studio长达六年时间。不过,这次ILM的口碑和舆评显然超过了Disney,正如片尾Rango骑着白鸡,发表了如下慷慨激昂的讲话:

My fellow comrades.

There will be times when you doubt yourself.

When you feel pummeled by the cataclysms of life,

Remember this moment. Remember me.

Know that I will be there watching you,

Sometimes at inappropriate moments.

That’s part of the deal.

And remember, within all of us resides

The true spirit of the…

Comments

KINECT来了——解析SDK(MS SDK 2)

NUI图像数据流概述

NUI的流数据是通过连续静态图像序列传递的。在上下文初始化阶段,应用程序将识别需要读取的流数据,并对其进行附加的流相关设置,包括数据解析度、图像类型、用于存储输入帧的缓冲区数量等内容。在应用程序检索并释放相关帧之前,如果运行时数据占满了缓冲区,那么系统将自动丢弃最旧的帧并重用缓冲区,也就是说,帧数据是可被丢弃的。同时系统最多允许请求四个缓冲区,而在大多数应用情形下通常只需要其中的两个。应用程序可通过API获取如下类型的图像信息:彩色图像数据、深度图像数据、用户分割数据等。下面将分别对上述三种类型的数据进行一些说明。

彩色图像数据:系统提供两种格式的彩色图像数据,包括32位X8R8G8B8格式的sRGB位图数据和16位的UYVY格式的YUV位图数据。由于两者实际来自同一图像数据,因此两种格式的最终图像实际上没有任何差别。不过后者要求图像保持640x480的分辨率和15FPS的帧率,同时内存需求更小。应注意,由于系统采用USB连接,传感器层会首先将1280x1024分辨率的Bayer彩色滤波马赛克图像压缩并转换为RGB格式传输,运行时系统再对该数据进行解压缩操作。上述特性可以保证数据帧率可达30FPS,但解码操作会损失一定的图像精度。

深度图像数据:深度图像帧中的每一个像素点都表示从摄像头所在平面到视野内最近物体的笛卡尔坐标系距离,单位为毫米。系统目前支持630x480、320x240、80x60三种规格的深度图像帧。应用程序可根据深度图像数据跟踪人物动作、识别并忽略背景物体。深度图像数据含有两种格式,其一是唯一表示深度值:那么像素的低12位表示一个深度值,高4位未使用;其二是既表示深度值又含有人物序号,则低三位保存人物序号,其余数据位表示深度值。应注意如果获取的深度值为0,则说明物体距离摄像头过近或过远以致超出了设备规格。

用户分割数据:SDK beta目前支持读取两个用户的分割映射数据,其数据帧的相关像素分别记录了用户的序号。尽管用户分割数据是独立生成的数据流,在实际应用中仍可以将深度数据和用户分割数据整合成一个帧,其中像素值的高13位保存了深度值,低三位保存用户序号,其中序号为0则表示无用户,1和2分别表示两个不同的用户。在实际应用中,应用程序往往利用用户分割数据在深度图像和原始彩色图像中获取ROI感兴趣信息。

基本编程模型

基于NUI API的编程模型本质上就是获取传感器图像数据的过程。应用程序往往通过相关代码首先将图像的最后一帧读入至缓冲区中,如果该帧已预备好,那么其将进入缓冲区,如果帧数据尚未就绪,代码仍可选择是否继续挂起等待或暂时释放并稍后重试。NUI摄像头API绝对不会多次传递相同的图像数据。框架包含的基本编程模型如下:

1、POLLing模型,该模型较为基础易用。首先应开启图像数据流,然后请求并设置等待下一帧的时间,范围允许从0到无穷大,单位为毫秒;如果帧数据尚未就绪,则系统将等待刚才指定的时间然后返回。如果帧数据成功返回,则应用程序可请求下一帧数据并在同一线程执行其它操作。通常一个C++应用程序应调用NuiImageStreamOpen函数首先启动一个彩色或深度数据流,并忽略可选事件。托管代码则需调用ImageStream.Open方法。请求彩色或深度图像帧的C++函数为NuiImageStreamGetNextFrame,C#为ImageStream.GetNextFrame方法。

2、事件模型,事件模型允许将获取骨骼帧的功能精确、灵活地集成入应用程序引擎。在该模型中,C++程序首先调用NuiImageStreamOpen函数并传入一个事件句柄。每当一个新的图像帧数据可用时,事件信号将被触发。任何相关的等待线程将被唤醒并通过调用NuiImageGetNextFrame函数获取骨骼信息,与此同时事件将被系统重置。托管代码应绑定Runtime.DepthFrameReady和Runtime.ImageFrameReady事件到相关的处理函数,当新数据可用时,处理函数可调用ImageStream.GetNextFrame获取该数据。

NUI骨骼跟踪应用

NUI还包括一个Skeleton骨骼跟踪模块,该部分提供最多两名用户的详细位置和朝向信息。骨骼跟踪的输出是一个点集,称作Skeleton Positions,该点集表示了一个完整的人体骨骼信息,如下图所示。

[singlepic id=44 w=320 h=240 mode=watermark float=center]

骨骼位置信息表示了用户当前的位置和姿态,如果要使用骨骼跟踪功能,应用程序应在NUI初始化阶段设置相关内容。NUI骨骼数据获取的方式与NUI Image部分基本一致,其基本编程模型也包括Polling和Event两种。前者的C++函数为NuiSkeletonGetNextFrame,托管函数为SkeletonEngine.GetNextFrame;后者的C++句柄绑定操作由NuiSkeletonTrackingEnable完成,并在处理线程内调用NuiSkeletonGetNextFrame;C#则使用Runtime.SkeletonFrameReady绑定事件,然后调用SkeletonEngine.GetNextFrame获取相关信息。

骨骼跟踪模块通过深度数据计算地板裁切面,其基本方法将在后文进行介绍。如果应用程序在NUI初始化时开启了骨骼跟踪功能,则其每处理完一套深度数据则就放出相应的骨骼数据信号,而无论该深度数据中是否真的包含骨骼信息。应用程序使用地板裁切面数据获取骨骼框架,返回的骨架信息将携带一个时间戳以和相关的深度信息进行匹配。

NUI骨骼跟踪分主动和被动两种模式,提供最多两副完整的骨骼跟踪数据。主动模式下需要调用相关帧读取函数获得用户骨骼数据,而被动模式下还支持额外最多四人的骨骼跟踪,但是在该模式下仅包含了用户的位置信息。对于所有获取的骨骼数据,其至少包含以下信息:

1、相关骨骼的跟踪状态,被动模式时仅包括位置数据,主动模式包括完整的骨骼数据。

2、唯一的骨骼跟踪ID,用于分配给视野中的每个用户。

3、用户质心位置,该值仅在被动模式下可用。

4、对于主动模式下的骨骼跟踪数据,还包括用户完整的骨骼数据。

5、对于被动模式下的骨骼跟踪数据,仅包括用户位置信息,不包括详细的骨骼数据。

NUI坐标变换原理

深度图像空间:这是一个仅包含物体到传感器法平面的深度数据的投影空间,其z值是唯一有效的,而x、y值仅仅是进行了插值计算的结果,其数据实际并无任何物理意义;

骨骼空间:用户骨骼位置使用x、y、z三维坐标表示,与深度图像空间坐标系不同的是,该空间的单位为米,且是一个传感器朝向为z轴正向的右手系。应注意,骨骼空间坐标系与Kinect位置息息相关,如果传感器被放置在一个非水平面上,那么计算得到的坐标系可能并非是标准形式,最终的用户数据也有可能是倾斜的。

地板裁剪面的确定:骨骼数据均需要包含一个地板裁剪面向量,该向量保存了与地板平面方程有关的系数coefficients,骨骼跟踪模块通过地板裁剪平面除去背景,并将用户图像分割出来。对于平面的一般式方程Ax+By+Cz+D=0,该方程经过规范化即D值实际是指传感器到地板平面的高度值。如果地板不可见,那么地板裁剪平面向量实际为0。地板裁剪面向量值可在NUI_SKELETON_FRAME结构的vFloorClipPlane成员中获取。托管代码则保存在SkeletonFrame.FloorClipPlane域中。

骨骼镜像:默认的用户图像实际上是一个镜像数据,也就是说该数据表示了用户当前面朝屏幕内部。然而有时确实需要图像面向用户本人一侧,那么需要确定一个镜像变换矩阵以达到此类要求。

Comments

KINECT来了——解析SDK(MS SDK 1)

在8月初的文章里,我们曾对Microsoft推出的官方Kinect SDK beta进行了初步介绍,本文将在此基础上对其做出进一步说明。值得注意的是对托管代码和非托管代码的选择,从社区反馈看来似乎前者占据了绝对上风,coding4fun推荐的项目也基本都是以WPF编程为主。不过考虑到平台的潜在可扩展,这里还是推荐使用标准C++构建非托管程序。下面先给出两种编程方式在VS2010中的配置方法:

对于托管C#程序,添加Add Reference中.Net标签页的Microsoft.Research.Kinect.dll,使用using Microsoft.Research.Kinect.Nui引用NUI API的声明文件,如果还要引用音频API,还要加上using Microsoft.Research.Kinect.Audio。

对于标准C++程序,代码中必须加入<windows.h>头文件,其中NUI API需要包含MSR_NuiApi.h头文件、音频API需要包含MSRKinectAudio.h。另外需要添加相应的静态链接库,同时确保安装的DLL文件存放在PATH路径中。这里给出SDK所包含的头文件说明:

MSR_NuiApi.h,该文件包含所有关于NUI API声明,包括初始化调用和访问函数,如NuiInitialize、NuiShutdown、MSR_NuiXxx以及INuiInstance,其主要功能是枚举设备并对其进行访问调用。MSR_NuiImageCamera.h,该文件包含对NUI图像和摄像头功能API的声明,其一般形式为NuiCameraXxx和NuiImageXxx:此类API的功能为调整摄像头倾角和仰角,并启动数据流并读入图像帧。MSR_NuiProps.h,该文件包含对NUI属性枚举API函数的声明。MSR_NuiSkeleton.h,该文件包括NUI骨架API函数的声明,其一般形式为NuiSkeletonXxx and NuiTransformXxx:功能为打开/关闭骨架跟踪、获取骨架数据、将骨架数据进行变换以实现平滑绘制。MSRKinectAudio.h,该文件包括对音频API函数的声明,其中ISoundSourceLocalizer接口可返回波束方向和音源位置。NuiImageBuffer.h,该文件定义了一个帧缓冲器,其作用类似DirectX9的纹理缓冲。

Kinect for Windows应用程序架构

[singlepic id=43 w=320 h=240 mode=watermark float=center]

上图给出了beta SDK的整体组件架构,硬件层我们已经在上月进行了详细介绍。驱动的内核模式包含了设备驱动程序,上层的数据交互统一使用WinUSB数据栈,其中设备栈主要用于设备的配置和访问,摄像头栈用于视频数据流控制,USBAudio栈用于音频数据流控制;用户模式为API提供了访问和控制接口。应用层API上包括了三部分组件,其中MS SDK beta直接提供了NUI API即基本API集和KinectAudio DMO,后者的功能主要是提供波束成形和音源定位功能。此外,如果要使用Kinect的所有功能,还需要自己准备Windows 7 SDK中的音频、语音、媒体API集以及微软语音识别SDK,上述组件并未包含在SDK中。近两篇文章会主要介绍NUI API部分的设计原理和编程说明。

NUI API概述

NUI API是Kinect SDK的核心组成部分,其主要功能包括:提供连接至PC的Kinect传感器元件的访问接口、提供对由Kinect成像传感器生成的图像和深度数据流访问接口、通过经处理的图像和深度数据实现骨骼跟踪。下面我们分别使用托管和非托管代码介绍整个Kinect API上下文环境的创建和销毁。

与OpenNI不同的是,Kinect SDK允许方便地同时使用多台Kinect设备,但是每台设备(或传感器)同一时间只能被一个程序实例使用。下面是使用C++代码实现传感器枚举和访问的整个过程:

情形一:应用程序同一时间仅使用一台Kinect设备:

1、调用NuiInitialize,该函数首先会初始化一个Kinect传感器设备实例;

2、调用NuiXxx,该函数集的功能是传输图像和骨骼数据流,并管理并配置相关摄像头;

3、调用NuiShutdown结束。

情形二:应用程序同一时间使用多台Kinect设备:

1、调用MSR_NuiDeviceCount,查看可用Kinect设备的数量;

2、调用MSR_NuiCreateInstanceByIndex创建指定设备索引的实例,该函数将返回该实例的INuiInstance接口指针;

3、调用INuiInstance::NuiInitialize,该函数用于初始化针对该实例的NUI API上下文;

4、调用针对INuiInstance接口的其它方法,用于传输图像和骨骼数据流并管理相关摄像头;

5、调用INuiInstance::NuiShutdown,销毁某个设备实例的NUI API上下文;

6、调用MSR_NuiDestroyInstance函数销毁该实例;

接下来是使用C#代码实现传感器枚举和访问的整个过程:

情形一:应用程序同一时间仅使用一台Kinect设备:

1、创建一个新的运行时对象,将其参数列表留空,例如nui = new Runtime(),调用该构造函数表示在系统中创建了一个Kinect传感器设备实例;

2、调用Runtime.Initialize函数初始化NUI API上下文;

3、调用其它托管接口,用于传输图像和骨骼数据流,并管理和配置相关摄像头;

4、调用Runtime.Shutdown销毁实例。

情形二:应用程序同一时间使用多台Kinect设备:

1、调用MSR_NuiDeviceCount函数获取可用设备数量;

2、创建一个新的运行时对象,参数为设备索引号,如nui = new Runtime(index),调用该构造函数表示创建了针对某个Kinect传感器的系统实例;

3、调用Runtime.Initialize函数初始化NUI API上下文;

4、调用其它托管接口方法,用于传输图像和深度数据、并管理和配置相关摄像头;

5、调用Runtime.Shutdown函数销毁实例。

NUI API的数据处理是通过一个多级管线实现的,在初始化阶段,应用程序需要指定相应级别的子系统,这样运行时系统才能系统所需的部分管线。在初始化时系统通常允许进行以下配置:

彩色:应用程序指定从设备中获取彩色图像数据流;

深度:应用程序指定从设备中获取深度图像数据流;

深度和人物索引:应用程序指定从设备中获取深度数据流,并请求骨骼跟踪引擎当前生成的人物索引;

骨骼:获取骨骼位置数据;

上述设置指定了有效数据流类型和解析度,例如当一个应用程序没有在NUI API初始化阶段指定深度数据时,它随后也无法开启一个深度数据流。

Comments