AR 开发

看到一个不错帖子,整理放这里啦:

背景

前段时间合伙人想做一个早教类的 AR 项目,并且扔给了我一个小册子:

大概的功能是:

  • iPad 扫瞄识别右侧的积木
  • 屏幕上出现主角按照顺序执行操作
  • 最后显示运行结果,闯关是否成功

折腾了一段时间,基本做完了上述功能,可以在这里看到演示的效果。

整个项目从第一次提交代码,到最后出演示效果,花了两天的时间,看了下 git commit 累计花了 25 小时(主要是炒股浪费了不少时间,也浪费了不少钱,此处略过不谈)。

看上去最终的开发时间不多,不过前面还是做了不少功课,在此简单的记录一下。

文章中不会涉及任何工具的具体使用过程,所有的基础操作在官方文档里都有详细的讲解。

了解

正式开发之前,先做了一些准备工作,主要是搜索 AR 相关的功能,看看有哪些工具可供使用。一番调研对比和测试之后整理了以下待选方案:

  • OpenCV:计算机视觉库,主要进行右侧积木的识别。
  • Vuforia:可以方便的在软件中实现 AR 功能,主要用于关卡识别和主角模型展示。
  • Python:主要是围绕 OpenCV 的一系列科学运算工具,用于快速开发图像识别功能的原型。
  • Unity3D:一款 3D 游戏引擎,可以很方便的进行 3D 场景搭建。
  • OpenGL:如果不用 Unity3D 就需要在 iOS 项目里基于 Vuforia 手写 OpenGL 实现 AR 功能。

积木识别测试

在正式开发之前,先使用 OpenCV for Python 开发图像识别原型,看看这个项目好不好搞。

在 Jupyter Notebook 里开发图像识别项目真是一种非常流畅的体验:

加载图像之后,只需要在新的 Cell 里写图像识别相关的算法就可以了,图像数据已经被加载到了内存里,不需要每次运行都执行全部脚本。然后 OpenCV 进行图像处理, numpy 进行像素运算, matplotlib 展示图像,一条龙服务,十分方便。

具体的图像识别算法不再赘述,上一篇《使用 OpenCV 识别 QRCode》里基本都已包含。

iOS App

搞定了积木识别之后,接下来就是做 AR 功能,主要有两个方案可供选择: iOS App 或者 Unity3D 。

先用 iOS App 试一下效果。

Vuforia 官方的 Sample Code 里已经包含了一个可以完整运行的项目,可以下载体验一下。然后用 pod 'OpenCV' 就能装好 OpenCV for C++ ,基本的开发环境就齐全了。折腾了一段时间之后我决定放弃使用 iOS App 的方案,因为实在是太繁琐了。

首先需要一个 ARSession 对象来管理 AR 的相关事务,里面包括了视频的渲染(需要等比拉伸并裁切之后渲染在屏幕上)、资源的回收和处理(比如手机退到后台)、线程切换(绘图需要在主线程)等等;然后需要一个 ARViewController 对象来负责具体页面的显示,里面包括基础资源的加载、识别模型的激活与切换、设备相关的事件监听等等;然后需要一个 ARImageTargetGLView 来渲染 AR 场景,包括 buffer 的维护、model 的加载、shader 的渲染等等。

而最让我崩溃的,是 Swift、Objective-C、C++ 的混写,项目中大量这样的代码:

     
     
[self setFramebuffer];
glVertexAttribPointer(vertexHandle, 3, GL_FLOAT, GL_FALSE, 0, ( const GLvoid*)buildingModel.vertices);
glEnableVertexAttribArray(textureCoordHandle);
if (offTargetTrackingEnabled) {
glBindTexture(GL_TEXTURE_2D, augmentationTexture[ 3].textureID);
} else {
glBindTexture(GL_TEXTURE_2D, augmentationTexture[targetIndex].textureID);
}
glUniformMatrix4fv(mvpMatrixHandle, 1, GL_FALSE, ( const GLfloat*)&modelViewProjection.data[ 0]);
glUniform1i(texSampler2DHandle, 0);
glDisableVertexAttribArray(textureCoordHandle);

最后发现写了上千行代码,几十个文件,才只是搭建好了一个基础的 AR 开发环境,还不包括自定义的 3D 效果和自己的业务代码,细思恐极,赶紧放弃。

Unity3D

接下来就是转投 Unity3D 的怀抱。

遇到的第一个问题是如何集成 OpenCV ,通过买买买这个 OpenCV for Unity 插件解决了,它是基于 OpenCV for Java 的,所以接口和 Python C++ 相比略有些变化,不过基本是相同的。在整合 OpenCV 和 Vuforia 的时候看到了 OpenCV for Unity 开发团队的 Voforia with OpenCV for Unity Sample 这个示例项目,再结合自带的 Samples 文件基本就没问题了。

遇到的第二个问题是 Unity3D 中如何处理项目文件的问题,在 iOS 项目里我的项目目录是这样的:

  • General
    • Macro
    • View
    • Extension
  • Section
  • Vendor

在 Unity3D 里,由于项目里不止是代码文件,还包括 fbx 之类的模型文件、 mat 等材质文件、prefab 等预设文件、unity 等场景文件,如果都放在一起十分混乱,很难检索。

参照 iOS 的项目目录,现在 Unity3D 里的项目里是这样安排的:

  • General:全局通用的文件
    • Scripts:通用的代码文件
      • Class:自定义的通用类
      • Extension:基础模块的扩展,比如 List 的方差运算等等
      • Static:静态工具类
  • Section:业务相关的文件,一个场景一个文件夹
    • Scene1:具体场景的文件夹,包括所有该场景下的资源
      • Scripts:该场景所需的代码
      • Prefabs:该场景内的预设对象
      • Resources:该场景下的其他资源
        • Materials:该场景下的材质

基本上单个场景的目录结构和 General 的目录结构是一致的, General 像是所有场景的『基类』。

遇到的第三个问题是 OpenCV 绘图如何处置的问题。我希望能够将 OpenCV 的一些 Debug 信息绘制在屏幕上,比如找到的 contours 、比如计算出的方差/均值、比如画面里的积木总数等等,可以很方便的了解图像识别的情况,找到出现问题的原因。本来是通过注释掉绘图代码的方式进行状态切换,后来发现实在是太麻烦了,于是在所有的 OpenCV 绘图方法外面套了一层,放在 CVUtil 里:

     
     
public class CVUtil {
public class Draw {
public static void Text(Mat mat, string str, double x, double y,
double fontScale = 1, Scalar color = null,
LogLevel level = LogLevel.Debug) {
if (level >= Global.CurrentLogLevel) {
Imgproc.putText (mat, str, new Point (x,y), Core.FONT_HERSHEY_PLAIN, fontScale, color);
}
}
public static void Rectangle(Mat mat, OpenCVForUnity.Rect rect,
Scalar color = null, int thickness = 1,
LogLevel level = LogLevel.Debug) {
if (level >= Global.CurrentLogLevel) {
Imgproc.rectangle (mat, rect.tl (), rect.br (), color, thickness);
}
}
}
}

然后这样只要切换全局变量 Global.CurrentLogLevel 就能控制 Debug 内容的显示和隐藏了。

整个 Unity3D 项目里,AR 相关的渲染完全不用操心,只需要把 Vuforia 里的 ImageTarget 这个 Prefab 脱拽到场景中就能实现基础的 AR 功能。

小结

就简单的写这么多啦,没什么干货,只是简单回顾一下自己的开发过程。

AR 开发的技术门槛并不是很高,目前现成的 SDK 很多,可以自行选择。而如何通过 AR 做出有趣的产品,这才是核心所在。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值