ARCore初探

4,330 阅读13分钟
原文链接: mp.weixin.qq.com

前言

Google近几年在VR/AR领域动作频频,先是推出Cardboard作为VR体验的敲门砖,随后发布Project Tango作为AR体验的基石,紧接着移动端的VR平台Daydream应运而生,今年在Google I/O大会上推出了升级版Daydream2.0,近期发布了基于Android平台的AR SDK — ARCore,这摆明了就是要怼早一步公布的iOS平台的AR SDK — ARKit,让无数Android开发者兴奋不已,两家公司的竞争态势也蔓延到组内移动端两股开发势力,前几个月隔壁iOS组的同事可都是鼻子朝天走路的。

秉着对VR/AR的好奇,自己对VR and AR at Google (Google I/O ‘17)进行相关学习,也对ARCore进行实践操作和分析,结合各种专业人士的真知灼见,本文难免有所纰漏,欢迎大家指导交流。

VR和AR区别

比较正式的解释:

  • 虚拟现实(Virtual Reality):利用计算机创造一个虚拟空间,利用虚拟现实眼镜能够使用户完全沉浸在一个虚拟的合成环境中,利用双目视觉原理,虚拟世界在眼镜中是3D立体的,无法看到真实环境。

  • 增强现实(Augmented Reality):能够把虚拟信息(物体、图片、视频、声音等等)融合在现实环境中,将现实世界丰富起来,构建一个更加全面的虚幻世界。

而对于小白用户来说,最直观最接地气的解释是

  • VR不需要开摄像头,只有虚拟场景,没有眼前的真实场景

  • AR需要打开摄像头,既有虚拟场景,也有所处的真实场景。

Google双管齐下,在这两方面都投入了很多的资源

  • VR方面,攻城锤是Cardboard和Daydream,前者是体验级VR解决方案,属于入门级VR设备的首选,物美价廉;后者是消费级VR解决方案,提供了手持遥控设备Controller,提高渲染效率,优化延迟。很多应用开发者都在Daydream平台上产出琳琅满目的作品,大量的影视作品、演唱直播都制作成VR格式。最近推出的Daydream 2.0版本提出了Instant Preview,在Unity平台上开发可以让手机与电脑一起联动,提高开发效率。

    这次更新也提供了投射功能,将你所能看见的展现给在场的其他朋友一起观看

  • AR方面,主力军是Project Tango和ARCore,前者是利用高配置的软硬件结合方案,提供环境感知,位置跟踪等服务,应用于室内定位、三维建模、机器人等领域,应用于移动设备上的产品很有限;

后者是最近推出的针对移动设备上的单目+IMU(Inertial measurement unit惯性测量单元)的增强现实方案,试图打造用户量最大的AR平台,目前还处在preview阶段,主要对标苹果推出的ARKit。

ARCore工作原理浅谈

ARCore 在移动设备上运行主要有三大关键技术:

  1. Motion tracking(运动追踪)可以让手机了解并追踪其在现实世界中的位置。使用手机的摄像头观察房间里的特征点和IMU传感器数据,判断设备所在的位置和方向,对虚拟物体进行精准放置,同时使用vps(visual positioning service室内导航)定位周围的物体位置。

  2. Environmental understanding(环境感知)可以让手机检测到类似地板或桌面平面大小和位置。虚拟物体一般是放在平面上,ARCore可以利用动作追踪中使用的数据点判断水平表面,保证物体可以正常放置,增加现实感。

  3. Light estimation(光线感知)可以让手机感知真实世界环境中的光照条件,让开发者照亮虚拟物体的方式与周围环境匹配,虚拟阴影在光照条件下会自动调整,以便让虚拟物体看起来更真实。

ARCore上手

官方运行设备

ARCore被设计用来支持数量广大的Android设备,但是目前对设备要求比较严格,要求系统不低于Android 7.0 Nougat(API  24),支持下列设备:

  • Google Pixel 和 Pixel XL

  • Samsung Galaxy S8 (SM-G950U, SM-G950N, SM-G950F, SM-G950FD, SM-G950W, SM-G950U1)

但是实际上可运行的设备并不限于以上手机类型,个人臆测其实Google应该是提前研发了ARCore,为了增加使用范围,所以在适配其他手机类型上花费了较多的时间,没想到苹果利用iPhone适配款式少、系统唯一等优势提前发布了ARKit,并直接宣称是世界上最大的AR平台,别说Google,就我们这些Android开发者也是不服的。出于各种因素,Google应该是提前发布了ARCore,并限定了可运行的手机设备,这些设备是满足各项严格测试的,还有其他部分设备只支持部分功能,存在未知隐患,所以还没有公布。但是可以通过修改代码的方式来去除设备限制,这个会在后文描述。

开发环境

根据目前的Google AR文档描述,支持的开发环境有Android Studio、Unity、Unreal、Web四种。下面以Android Studio为例进行开发。

首先搭建开发环境:

  • 安装Android Studio 2.3 或更高版本,运行环境Android 7.0 Nougat(API  24)或更高版本。

  • 需要使用上面提到的能支持 ARCore 的 Android 设备。

  • 需要为 Android Studio 提供 ARCore SDK,可以下载ARCore SDK preview for Android Studio并解压或直接下载ARCore在github上的项目

ARCore 不支持 Android Emulator 等虚拟设备,满足要求的设备除了要开启大家所熟知的开发者模式之外,还需要提前安装arcore-preview.apk,提供基础的ARCore Service,安装成功之后会在系统应用里面显示出Tango Core的提示,表示安装成功。

同时利用Android Studio可以反编译查看arcore-preview.apk的结构

根据对so包文件名称猜测,这个apk才是ARCore的核心,供应用中的jni接口调用。在 Android Studio 中,找到 /samples/java_arcore_hello_ar,并打开 HelloAR 示例项目,主要依赖文件有arcore_client.aar和obj-0.2.1.jar

编译项目并在设备上运行,打开相机权限,移动拍摄位置,会出现很多星点,经过计算之后会识别出平面位置,点击平面会放置绿色的安卓logo,效果图如下。

其他可以使用ARCore的设备

在普通手机上运行该项目,会直接弹出“This device does not support AR”的提示,然后就闪退了,连app里面什么样子都看不见,支持ARCore的官方推荐手机都是5000元以上的高端机,像我这种手持低端机的开发者也想看看app运行的样子,感谢github上大神提出的arcore-for-all这种简单易用的方法修改依赖文件,虽然不能从根本上解决问题,但还是可以绕过手机类型判断这一步。

解析过程

  1. 解压文件:arcore-android-sdk-master中libraries文件夹下有arcore_client.aar文件,也是项目中的依赖文件,对其进行解压,再对其中的classes.jar文件进行解压得到核心class文件集,对com/google/atap/tangoservice/SupportedDevices.class文件进行修改。

  2. 反编译文件:需要将.class文件转换为.java文件,我采用的是cfr工具进行反编译,在命令行中执行java -jar /xxxxxx/cfr.jar SupportedDevices.class > SupportedDevices.java

  3. 修改文件:文件名很直观的告诉我们这个文件主要执行对可运行设备的判断,里面的方法也很简洁:主要在isSupported()中判断,而其中的一个判断条件deviceCalibrationAvailable()主要是对Build.FINGERPRINT(由设备的各种信息拼接而成)的内容进行匹配,所以可以直接一刀切,在isSupported()中最后一个判断分支里面注释掉return false的语句,如下所示:

  4. public static boolean isSupported(Context context) {
        try {
            ApplicationInfo applicationInfo = context.getPackageManager().getApplicationInfo(context.getPackageName(), 128);
            int n = applicationInfo.metaData.getInt("com.google.ar.version.major");
            int n2 = applicationInfo.metaData.getInt("com.google.ar.version.minor");
            int n3 = 0;
            int n4 = 0;
            if (n > n3) {
                Log.e((String)TAG, (String)"Major version of AR Core is too low.");
                return false;
            }
    
            if (n == n3 && n2 > n4) {
                Log.e((String)TAG, (String)"Minor version of AR Core is too low.");
                return false;
            }
        }
        catch (PackageManager.NameNotFoundException nameNotFoundException) {
            Log.e((String)TAG, (String)"Unexpected error: Packagename of app doing isSupported check should exist.");
        }
        if (!SupportedDevices.deviceCalibrationAvailable()) {
            Log.e((String)TAG, (String)"Device calibration unavailable. ");
            return false;
        }
        return true;
    }
    
    private static boolean deviceCalibrationAvailable() {
        return Build.FINGERPRINT.contains("sailfish:7") || Build.FINGERPRINT.contains("sailfish:O") || Build.FINGERPRINT.contains("sailfish:8") || Build.FINGERPRINT.contains("marlin:7") || Build.FINGERPRINT.contains("marlin:O") || Build.FINGERPRINT.contains("marlin:8") || Build.FINGERPRINT.contains("walleye:O") || Build.FINGERPRINT.contains("walleye:8") || Build.FINGERPRINT.contains("taimen:O") || Build.FINGERPRINT.contains("taimen:8") || Build.FINGERPRINT.contains("SC-02J/SC-02J:7") || Build.FINGERPRINT.contains("SCV36_jp_kdi/SCV36:7") || Build.FINGERPRINT.contains("dreamqlteue/dreamqlteue:7") || Build.FINGERPRINT.contains("dreamqltesq/dreamqltesq:7") || Build.FINGERPRINT.contains("dreamqlteldusq/dreamqltesq:7") || Build.FINGERPRINT.contains("dreamqltezm/dreamqltecmcc:7") || Build.FINGERPRINT.contains("dreamqltevl/dreamqltecan:7") || SupportedDevices.isSupportedExynosDevice();
    }
    
    public static boolean isSupportedExynosDevice() {
        return Build.FINGERPRINT.contains("dreamlteldu/dreamlte:7") || Build.FINGERPRINT.contains("dreamlteks/dreamlteks:7") || Build.FINGERPRINT.contains("dreamltexx/dreamlte:7");
    }
  5. 编译文件:利用Android SDK中的android.jar文件对java文件进行编译,在当前的SupportedDevices.java文件目录下执行javac -cp /xxxxx/android.jar -source 1.8 -target 1.8 SupportedDevices.java,这里1.8是对应我本地的java 8 版本,因人而异。

  6. 打包文件:将得到的SupportedDevices.class文件重新压缩进jar文件中,在classes.jar所在目录下执行jar cvf classes.jar -C classes .,接着在arcore_client.aar所在目录下执行 jar cvf arcore_client.aar -C aar_client.

  7. 生成apk:在Android Studio中build->clean project(新改的依赖包可能会不生效),然后运行安装在其他设备上,经过部分手机的测试,Nexus 6p也可以出现上文展示的效果,logcat中也会展示出09-10 19:59:50.478 866-866/? E/SupportedDevices: Device calibration unavailable.,进入了刚才修改的判断分支中,不过相比较于Pixel和S8,识别速度等会慢一些。而大部分手机虽然可以进入应用,但是只是在底部提示“Searching for surfaces…”,主要的显示区域也是黑屏,并不能使用ARCore的主要功能。上述的github项目中也展示了支持ARCore的手机测试清单,除了官方推荐,其余支持的手机目前只有Nexus 6p和OnePlus 5。

ARCore VS Tango

上文中ARCore的三个核心技术在Tango中都有涉及,而且ARCore SDK和so包里面的文件命名都出现了Tango的字眼,由此不难猜测出ARCore其实是在Tango的研发基础上进行的功能改造,Tango一定要达到特定的软硬件标准才能够实现,比如下图是一台Tango手机需要的部分组件

Tango有专用的红外深度感应摄像头,可以创建丰富的3D纹理,直接测量距离。ARCore可以简单理解为检测平坦的表面,然后在上面放置虚拟物体,它并只是对相机反馈数据进行估计。但是苛刻的设备要求、大量OEM产商不合作和用户需求不够强烈等因素使得Tango一直不温不火,于是将Tango的关键部分分离出来,移除了深度相机部分功能,让它适用于普通手机,ARCore就是为了解决这些痛点而存在,不需要严格的特殊硬件,主要从软件方面解决问题。但是毕竟现在还是预览版,能否真正实现Tango未实现的目标还不得而知。

ARCore VS ARKit

首先了解下ARKit的基础知识。ARKit是一种为iOS构建增强现实的框架,意在实现将虚拟内容精确且真实地浸入真实世界场景上。ARKit框架提供了两种AR技术,一种是基于3D场景(SceneKit)实现的增强现实,一种是基于2D场景(SpriktKit)实现的增强现实。ARKit的核心是为一些基本的关键功能提供支持,包括运动跟踪,水平面检测,以及环境光预测。

  • 运动跟踪:移动设备提供了专用的运动协处理器。该功能采用VIO(Visual Inertial Odometry 视像惯性测程),基于镜头捕捉的数据估计设备的三维定位及移动情况。

  • 水平面检测:可以识别出水平面,将虚拟物体精确地置于真实物理场景中。

  • 环境光预测:对虚拟物体产生真实阴影和光照效果相适配。

下图是针对两种框架下的官方demo实例对比,左侧是是iPhone 7,右侧是三星S8,分别识别出平面并添加物体,旋转一周,特征点发生明显的变化之后,再次重新定位

异同点

  • 光线感知:ARKit和ARCore都可以对环境光进行简单的估计,ARKit为开发者提供了强度和色温选项,而ARCore提供了单像素强度值(Android Studio API)和Shader(Unity API)。

  • 建图定位:ARCore和ARKit都使用了离散点云图,跟踪器会提前去判断是否有预加载的图,没有的话就自定义新的模型,会获取到相机视角下的一个3D范围。当你移动设备时,摄像头会捕捉到新的一图像,并加载到之前新建的3D模型中,不断增加内容。ARKit在建图的时候使用了“sliding window”,只会在图中保存最近的时间和距离数据,旧的数据会被自动忽视,而ARCore会管理维护更大的数据和地图,保存的内容会更加持久稳定。

  • 市场布局:ARKit只支持A9及以上处理器的设备,对应着就是iPhone 6s及以后的机型,手机系统的高度统一性也奠定了苹果庞大的设备基础,目前ARCore预览版只针对少量机型和系统,再加上OEM产商各自为营,因此在普及度上短期内还是处于落后地位

  • 产品开发:ARKit提前几个月发布,目前已经有多款实用的app,展现了开发者无限的想象力  而近期才发布的ARCore还需要开发者脑洞大开,不过Tango在过去的2-3年里面已经积攒了开发工具和技术支持,这些应该可以为长期致力于AR的开发者提供良好的过渡和帮助。

比较看来,ARCore和ARKit核心功能点类似,demo中ARCore 在已经支持的设备上追踪性能与ARKit的识别能力十分接近,ARCore在建图和重定位方面具有一些优势,ARKit在集成和跟踪方面具有一定的技术优势,各自都有市场地位,在选择方面主要看开发者的个人偏好。

总结

Google和苹果两大巨头终于在AR领域部署基于系统层面的解决方案,推出了实际的可落实到移动设备上的框架产品,两者强势的竞争势头是众多AR领域开发者的福音,而对于第三方独立AR公司来说可能就是沉重一击,毕竟这两大巨头配套OEM产商垄断了移动端的硬件设备和软件系统,在夹缝中生存的压力可想而知。ARCore和ARKit相爱相杀,不仅提高了AR应用的体验效果,又降低了开发门槛,是不是AR的春天真的来了,让我们拭目以待……

参考资料

  1. mp.weixin.qq.com/s/BwjyJwUJK…

  2. https://github.com/tomthecarrot/arcore-for-all

  3. https://www.leiphone.com/news/201708/2WE6jIhArekIryfl.html

  4. http://www.infoq.com/cn/news/2017/09/ARCore-moblie-AR

  5. https://www.leiphone.com/news/201709/hioiZlgdXIj9fFex.html

  6. http://www.infoq.com/cn/news/2017/06/ios-augmented-reality-arkit