鸿蒙开发-想识别图片放虚拟物体?AR Engine图像跟踪详解
2026/6/7 15:55:00 网站建设 项目流程

你有没有在商场看到过这样的体验:手机对着一张海报扫一扫,海报上就"跳"出一个 3D 动画角色?或者扫描一张明信片,明信片上就开始播放视频?

这背后靠的就是AR 图像跟踪。简单说,就是让 AR Engine 认识你指定的图片,然后在图片上方叠加 3D 内容。

图像跟踪能做什么?

想象一下这些场景:

  • AR 名片:扫描名片,名片上浮现出 3D 公司 logo 和联系方式
  • AR 教材:扫描课本上的插图,插图变成 3D 模型,学生可以 360 度旋转查看
  • AR 寻宝游戏:在商场里贴几张特定图案,玩家扫描这些图案就能触发不同的 AR 关卡
  • AR 产品展示:扫描产品包装盒,包装盒上方展示产品拆解动画

这些场景的共同点是:先识别一张"已知"的图片,然后在图片上叠加虚拟内容。

AR 图像跟踪整体流程

下面是使用 AR Engine 进行图像跟踪的完整流程:

准备要识别的图片

创建图像数据库

添加图片到数据库

配置 AR 类型为 IMAGE

初始化 AR 会话

摄像头实时扫描

识别到图片?

创建锚点和节点

回调通知应用

在图片上叠加 3D 内容

持续更新位姿

图片质量要求

分辨率 640x480

宽高比 1-1.5

有丰富纹理特征

怎么配置图像跟踪?

要开启图像跟踪能力,你需要在 AR 配置里指定类型为IMAGE

import{arEngine,arViewController}from'@kit.AREngine';letcontext:arViewController.ARViewContext=newarViewController.ARViewContext();context.config={type:arEngine.ARType.IMAGE,// ... 其他配置};

arEngine.ARType.IMAGE告诉 AR Engine “我要做图像识别”。这个类型跟WORLD(环境追踪)、FACE(人脸追踪)、BODY(人体追踪)是并列的,你只能选一个。

配置好之后,调用context.init()初始化 AR 会话。

图像数据库:把要识别的图片喂给 AR Engine

光配置还不够,你还需要告诉 AR Engine “你要识别哪些图片”。这就需要创建一个图像数据库(ARAugmentedImageDatabase)

图像数据库就像一本"图片相册",你把所有要识别的图片都放进去,AR Engine 就会记住它们。当摄像头拍到的画面跟相册里的某张图片匹配时,AR Engine 就会告诉你"我认出来了"。

创建图像数据库的代码:

import{image}from'@kit.ImageKit';import{arEngine}from'@kit.AREngine';letcolor:ArrayBuffer=newArrayBuffer(96);// 96为需要创建的像素buffer大小,取值为:height * width *4letopts:image.InitializationOptions={editable:true,pixelFormat:image.PixelMapFormat.RGBA_8888,size:{height:4,width:6}};letpixelMap:image.PixelMap=image.createPixelMapSync(color,opts);letimageDatabase:arEngine.ARAugmentedImageDatabase=awaitarEngine.createARAugmentedImageDatabase();awaitimageDatabase.addImage('xx',pixelMap,0.3);

这段代码做了三件事:

  1. 创建 PixelMap:把图片数据转成 AR Engine 能处理的格式。这里用image.createPixelMapSync创建了一个像素图。color是像素数据的 ArrayBuffer,opts指定了像素格式(RGBA_8888 是最常见的格式)和图片尺寸。
  2. 创建图像数据库arEngine.createARAugmentedImageDatabase()创建一个空的数据库。
  3. 添加图片imageDatabase.addImage('xx', pixelMap, 0.3)把图片添加到数据库里。

addImage方法有三个参数:

  • 第一个参数'xx':图片的名称,随便取,但不能超过 255 个字符。这个名字会在后续识别到图片时返回给你,让你知道是哪张图被识别到了。
  • 第二个参数pixelMap:图片的像素数据。
  • 第三个参数0.3:图片中对象的实际物理宽度,单位是米。这个参数很重要——AR Engine 需要知道这张图片在现实世界中有多大,才能正确地计算虚拟物体的大小和位置。比如你要扫描一张 A4 纸(宽 21cm),就传0.21。如果你不传这个参数,AR Engine 会用 A4 纸的大小作为默认值。

图片的质量要求

不是随便一张图片就能被 AR Engine 识别的。图片需要满足一些条件:

分辨率:建议以 640×480 为基准。如果图片分辨率太低(比如 160×120),AR Engine 可能识别不了。太高也没太大意义,反而浪费内存。

宽高比:建议在 1 到 1.5 之间(比如 640×480 的宽高比是 1.33)。太窄或太宽的图片(比如长条形)识别效果会差很多。

内容特征:图片需要有足够的视觉特征。纯色图片、纯白背景的图片很难识别。最好是那种有丰富纹理的图片,比如带文字、带图案、带颜色渐变的。

光线条件:图片不能太亮也不能太暗。如果你在黑暗的房间里扫描一张纯黑的图片,AR Engine 肯定认不出来。

如果图片不符合要求,addImage会返回一个失败结果,你可以通过ARAddAugmentedImageReason枚举来查看失败原因:

  • SIZE_NOT_MATCH:图片尺寸不正确
  • LIGHT_ANOMALY:图片太亮或太暗
  • FEATURE_LIMIT:图片颜色太单一
  • OTHER:其他原因,比如反光、光斑、重复性内容

图像数据库管理流程

图像数据库的创建、添加和序列化流程如下:

失败

成功

NORMAL 模式

UPDATE 模式

创建图像数据库

添加图片

添加成功?

检查失败原因

SIZE_NOT_MATCH 尺寸错误

LIGHT_ANOMALY 光线异常

FEATURE_LIMIT 特征不足

需要持久化?

序列化保存

写入文件

下次启动直接加载

直接使用

数据库容量

超过 50 张?

报错

自动删除最旧图片

图像数据库容量限制

图像数据库最多能存多少张图片?默认是50 张

你可以通过getCapacity()方法查看当前数据库的最大容量:

import{arEngine}from'@kit.AREngine';letimageDatabase:arEngine.ARAugmentedImageDatabase=awaitarEngine.createARAugmentedImageDatabase();imageDatabase.getCapacity();

如果你添加的图片数量超过 50 张,会怎样?这取决于你设置的添加模式

  • NORMAL模式(默认):超过 50 张就报错,新图片添加失败。
  • UPDATE模式:超过 50 张时,会自动删除最旧的图片,腾出空间给新图片。

你可以通过setImageAddMode来切换模式:

import{arEngine}from'@kit.AREngine';letimageDatabase:arEngine.ARAugmentedImageDatabase=awaitarEngine.createARAugmentedImageDatabase();imageDatabase.setImageAddMode(arEngine.ARAddAugmentedImageMode.UPDATE);

如果你的 APP 需要识别很多图片(比如扫描百科全书里每一页的插图),用UPDATE模式会更方便,不用手动管理数据库容量。

图像数据库的序列化与反序列化

每次启动 APP 都重新创建图像数据库,这显然很浪费。AR Engine 提供了序列化功能,你可以把数据库保存成一个二进制文件,下次启动时直接加载。

序列化(把数据库保存成二进制数据):

import{arEngine}from'@kit.AREngine';letimageDatabase:arEngine.ARAugmentedImageDatabase=awaitarEngine.createARAugmentedImageDatabase();awaitimageDatabase.serialize();

serialize()返回一个ArrayBuffer,你可以把它写到文件里。

反序列化(从二进制数据恢复数据库):

import{arEngine}from'@kit.AREngine';letbuffer:ArrayBuffer=newArrayBuffer(0);letimageDatabase:arEngine.ARAugmentedImageDatabase=awaitarEngine.createARAugmentedImageDatabase();awaitimageDatabase.deserialize(buffer);

deserialize()是一个耗时操作,建议在后台线程里运行,不要阻塞 UI 线程。

这在实际应用中很有用。比如一个 AR 教育 APP,教材里的图片是固定的,你可以提前把图像数据库序列化好,打包进 APP 里。用户打开 APP 时直接加载,不需要再重新处理图片。

识别到图片后怎么处理?

当 AR Engine 识别到图像数据库里的某张图片时,会通过回调通知你。跟 SLAM 运动跟踪一样,你需要在onAnchorAddonAnchorUpdate回调里处理。

onAnchorAdd:当 AR Engine 识别到一张新图片时,会为这张图片创建一个锚点和对应的场景节点。你可以在回调里拿到锚点的位姿,然后在对应位置放上 3D 模型。

onAnchorUpdate:随着手机的移动,图片在摄像头画面中的位置和角度会变化。AR Engine 会持续更新锚点的位姿,让虚拟物体始终"贴"在图片上。

你还可以通过onFrameUpdate回调获取每一帧的数据,在里面检查当前帧识别到了哪些图片。

图片的实际物理尺寸很重要

前面提到addImage的第三个参数是图片的实际物理尺寸。这个参数为什么这么重要?

想象一下:你扫描一张明信片,AR Engine 识别出这张明信片在现实世界中是 15cm × 10cm 的。然后你在这张明信片上方放一个 3D 模型。AR Engine 需要知道明信片的实际大小,才能正确地计算 3D 模型应该有多大。

如果你把物理尺寸设错了(比如把 15cm 写成了 1.5cm),AR Engine 会认为明信片很小,然后放上去的 3D 模型也会变得很小,看起来就不对了。

如果你不确定图片的实际大小,可以不传这个参数,AR Engine 会用 A4 纸的大小(21cm × 29.7cm)作为默认值。

多张图片同时识别

图像数据库里可以放多张图片,AR Engine 会同时识别所有图片。但有一些限制需要注意:

  • 最多同时识别的图片数量取决于设备性能
  • 如果两张图片长得很像,AR Engine 可能会混淆
  • 图片之间最好不要有太多相似的区域

在实际应用中,建议每张图片都有足够的独特性。比如你要做 AR 产品包装识别,每个产品的包装设计应该有足够的差异,不要用颜色和图案都很相似的设计。

清理资源

图像数据库会占用内存,用完之后记得释放:

import{arEngine}from'@kit.AREngine';letimageDatabase:arEngine.ARAugmentedImageDatabase=awaitarEngine.createARAugmentedImageDatabase();awaitimageDatabase.release();

特别是你创建了很大的图像数据库(比如 50 张高分辨率图片),一定要及时释放,不然内存会一直涨。

一个完整的图像跟踪流程

把上面的内容串起来,一个完整的图像跟踪流程大概是这样的:

  1. 准备要识别的图片,确保图片质量符合要求
  2. 创建图像数据库,把图片添加进去
  3. 配置 AR 类型为IMAGE
  4. 初始化 AR 会话
  5. 在回调里处理识别到的图片,放上 3D 内容
  6. APP 退出时释放资源

如果你的图片是固定的(比如教材插图),可以把图像数据库序列化保存,下次直接加载,省去重新处理图片的时间。

实际应用场景

AR 博物馆导览:游客扫描展品旁的说明牌,说明牌上浮现出展品的 3D 模型和语音讲解。每个说明牌就是一张"已知图片",AR Engine 识别到后就在上面叠加虚拟内容。

AR 营销:品牌在产品包装上印一个特定图案,用户扫描图案就能看到产品的故事动画。比如扫描一瓶酒的标签,标签上跳出葡萄园的 3D 场景。

AR 教育:扫描课本上的解剖图,图上浮现出 3D 人体器官模型。学生可以用手指旋转模型,从不同角度观察。

AR 寻宝游戏:在商场的不同位置贴上不同的图案,玩家扫描这些图案就能触发不同的 AR 任务。每个图案对应图像数据库里的一张图片。

图像跟踪是 AR 应用中最直观、最容易理解的能力之一。用户不需要做任何复杂的操作,只需要对着图片扫一扫,就能看到 AR 效果。这种简单的交互方式让图像跟踪成为 AR 营销和 AR 教育的首选方案。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询