当前位置: 首页 > news >正文

鸿蒙开发-想测量物体距离?AR Engine深度估计详解

想测量物体距离AR Engine 深度估计详解你有没有想过AR 应用是怎么知道你面前的桌子有多远的或者怎么判断虚拟物体应该被真实物体挡住的比如说你在玩一个 AR 游戏一个小精灵躲在沙发后面只露出半个脑袋。这个被挡住的效果靠的就是深度估计。简单说深度估计就是让手机知道画面中每个像素点离摄像头有多远。有了这个信息你就能做很多有意思的事情测量两点之间的距离、让虚拟物体和真实物体正确遮挡、在真实物体表面做投影效果等等。深度估计整体流程下面是深度估计的完整工作流程是否创建ARViewContext配置depthMode为AUTOMATIC初始化AR会话后台计算深度信息onFrameUpdate回调获取ARFrameacquireDepthImage16Bits获取深度图acquireDepthConfidenceImage获取置信度图读取像素深度值检查置信度等级置信度是否足够?使用深度值进行计算丢弃该深度值释放资源release怎么开启深度估计开启深度估计非常简单只需要在ARConfig里把depthMode设成AUTOMATICimport{arEngine,arViewController}fromkit.AREngine;letcontext:arViewController.ARViewContextnewarViewController.ARViewContext();context.config{type:arEngine.ARType.WORLD,poseMode:arEngine.ARPoseMode.GRAVITY_AND_HEADING,powerMode:arEngine.ARPowerMode.POWER_SAVING,depthMode:arEngine.ARDepthMode.AUTOMATIC};depthMode: arEngine.ARDepthMode.AUTOMATIC这一行就是关键。它告诉 AR Engine“帮我自动获取场景的深度信息”。ARDepthMode枚举有两个值DISABLED0关闭深度模式。这是默认值如果你不主动设置深度估计是关着的。AUTOMATIC1开启深度模式。AR Engine 会自动尝试从多种深度源获取深度信息。注意深度模式默认是DISABLED的。如果你不显式设成AUTOMATIC那后面所有的深度相关 API 都用不了。另外深度估计通常有两种数据来源运动深度算法通过分析摄像头连续画面的视差来推算深度。这种方式不需要特殊硬件但精度相对低一些。硬件深度传感器ToF通过发射红外光并计算反射时间来测量距离。精度更高但需要设备有 ToF 传感器。目前 AR Engine 仅支持使用主 RGB 相机所获取的运动深度数据也就是第一种方式。配置好之后初始化 AR 会话awaitcontext.init();初始化完成后AR Engine 就开始在后台默默计算深度信息了。怎么获取深度图深度图是深度估计的核心产出。它是一张跟摄像头画面一样大的图片但每个像素存的不是颜色而是距离——这个点离摄像头有多远。通过ARFrame.acquireDepthImage16Bits()方法来获取深度图import{arEngine}fromkit.AREngine;// arSession创建参考ARSession.getFrame接口示例代码letframe:arEngine.ARFramearSession.getFrame();frame.acquireDepthImage16Bits();这行代码从当前帧中获取深度图像对象。返回的是一个ARImage对象。深度图有几个重要的特性格式深度图是索引 0 处的单个 16 位平面。每个像素用 16 位无符号整数来存储深度值。单位每个像素的值代表到相机平面的距离单位是毫米mm。范围可表示的深度范围是 0mm ~ 65535mm也就是大约 0 到 65 米。对于室内 AR 应用来说这个范围完全够用了。打个比方如果深度图上某个像素的值是 1500那就表示这个点离摄像头 1500 毫米也就是 1.5 米。深度图的置信度深度图的深度值是算法估算出来的不是百分百准确的。AR Engine 提供了一个置信度图像告诉你每个像素的深度值有多可信import{arEngine}fromkit.AREngine;// arSession创建参考ARSession.getFrame接口示例代码letframe:arEngine.ARFramearSession.getFrame();frame.acquireDepthConfidenceImage();acquireDepthConfidenceImage()返回的也是一个ARImage对象它的宽高跟深度图像一致。置信度值有三个等级0估计深度值的置信度最低。这个点的深度值可能完全不准别太当真。1估计深度值置信度中等。可以参考但不要拿来做精确测量。2估计深度值置信度最高。这个点的深度值比较可靠。在实际使用中你应该先检查置信度再决定是否使用对应的深度值。打个比方如果你想测量两个点之间的距离但其中一个点的置信度是 0那测量结果可能差了十万八千里。怎么读取深度值拿到深度图之后你需要读取具体像素的深度值。ARImage对象包含以下属性format图像数据格式width图像宽度像素height图像高度像素imageTimestamp图像的时间戳纳秒planes图像组件的基本结构参数列表深度图是 16 位的所以每个像素占 2 个字节。你可以通过planes获取底层的二进制数据然后按像素坐标来读取深度值。假设你想获取屏幕中央那个点的深度值大致的思路是获取深度图的宽高计算中央像素的坐标(width/2, height/2)从planes的数据缓冲区中按偏移量读取对应像素的 16 位深度值这个深度值就是该像素点到摄像头的距离单位是毫米。用完记得释放资源深度图和置信度图都是ARImage对象用完之后记得调用release()释放内存import{arEngine}fromkit.AREngine;// arSession创建参考ARSession.getFrame接口示例代码letframe:arEngine.ARFramearSession.getFrame();letimage:arEngine.ARImageframe.acquireDepthImage16Bits();awaitimage.release();如果不释放每帧都会产生一个新的ARImage对象内存会一直涨最终导致应用卡顿甚至崩溃。同样ARFrame用完也要释放awaitframe.release();这在 AR 应用里是个好习惯——任何从acquire开头的方法获取的对象用完都要release。命中检测流程命中检测是深度估计的重要应用之一下面是其工作流程是否用户点击屏幕获取点击像素坐标x,y调用hitTest方法从摄像头发射射线检测射线与平面交点是否有交点?返回ARHitResult数组提示未命中获取交点位姿getHitPose在该位置放置虚拟物体命中检测用深度来判断点击位置深度估计还有一个非常实用的场景——命中检测Hit Test。你有没有想过用户在屏幕上点了一下AR 应用怎么知道用户想点的是现实世界的哪个位置这就需要命中检测。它会从摄像头位置发射一条射线穿过用户点击的屏幕像素然后检测这条射线在现实世界中跟哪些平面或点云相交import{arEngine}fromkit.AREngine;// arSession创建参考ARSession.getFrame接口示例代码letframe:arEngine.ARFramearSession.getFrame();frame.hitTest(0,0);hitTest(x, y)接收两个参数x预览区域中像素的 X 坐标y预览区域中像素的 Y 坐标这两个值是由设备显示分辨率决定的。比如用户点击了屏幕上的某个位置你把那个位置的像素坐标传进去就行了。返回的是一个ARHitResult数组每个元素代表一个交点。ARHitResult包含distance从相机到命中位置的距离单位是米范围 0~65535getHitPose()获取交点的位姿信息位置和朝向打个比方你想做一个点击屏幕放置虚拟物体的功能。用户点击屏幕后你拿到点击的像素坐标调用hitTest()从返回的结果中找到跟平面相交的那个点然后在那个位置放置虚拟物体。这就是 AR 家具摆放 APP 的核心逻辑。场景网格数据除了深度图AR Engine 还提供了更丰富的深度信息——场景网格Scene Mesh。场景网格是 AR Engine 对环境进行三维重建的结果它把现实世界的表面用三角形网格来表示。你可以获取网格的顶点坐标、法线和三角形索引用于更复杂的 AR 效果比如遮挡、物理碰撞等。通过acquireSceneMesh()来获取场景网格import{arEngine}fromkit.AREngine;// arSession创建参考ARSession.getFrame接口示例代码letframe:arEngine.ARFramearSession.getFrame();frame.acquireSceneMesh();返回的是一个ARSceneMesh对象它有两个只读属性verticesSize场景网格中的顶点数量最小为 0无上限triangleIndicesSize场景网格中的三角形索引数量最小为 0无上限然后你可以通过以下方法获取具体的数据import{arEngine}fromkit.AREngine;// arSession创建参考ARSession.getFrame接口示例代码letframe:arEngine.ARFramearSession.getFrame();letsceneMesh:arEngine.ARSceneMeshframe.acquireSceneMesh();sceneMesh.getVertices();getVertices()获取顶点坐标数据。返回的是ArrayBuffer需要转换成float32类型来使用。每 3 个连续的值代表一个顶点的 (x, y, z) 坐标。import{arEngine}fromkit.AREngine;// arSession创建参考ARSession.getFrame接口示例代码letframe:arEngine.ARFramearSession.getFrame();letsceneMesh:arEngine.ARSceneMeshframe.acquireSceneMesh();sceneMesh.getVertexNormals();getVertexNormals()获取顶点法线数据。同样是ArrayBuffer转换成float32。法线数据用于光照计算——知道每个面朝哪个方向才能正确地计算光照效果。import{arEngine}fromkit.AREngine;// arSession创建参考ARSession.getFrame接口示例代码letframe:arEngine.ARFramearSession.getFrame();letsceneMesh:arEngine.ARSceneMeshframe.acquireSceneMesh();sceneMesh.getTriangleIndices();getTriangleIndices()获取三角形索引数据。返回的是ArrayBuffer需要转换成int32类型。每 3 个连续的索引值组成一个三角形指向getVertices()返回的顶点数组中的位置。场景网格用完也要释放awaitsceneMesh.release();深度估计应用场景深度估计可以应用于多种AR场景深度估计数据AR测量工具遮挡效果AR导航3D重建物理碰撞点击两点计算距离判断物体前后关系识别地面位置结合场景网格重建检测真实墙壁边界深度估计的实际应用场景说了这么多 API来看看深度估计能做什么AR 测量工具用户在屏幕上点击两个点通过深度图获取这两个点的 3D 坐标然后计算两点之间的距离。这就是 AR 尺子的原理。遮挡效果虚拟物体应该被真实物体挡住。比如虚拟小人站在桌子后面只露出上半身。深度图能告诉你哪些区域离摄像头近哪些区域远从而正确地处理遮挡关系。AR 导航在地面上画箭头指引用户行走。深度图能帮你识别地面的位置让箭头正确地贴在地面上。3D 重建结合场景网格数据可以把现实环境重建为 3D 模型。这在室内设计、建筑测绘等领域很有用。物理碰撞虚拟物体碰到真实墙壁应该停下来。场景网格提供了真实环境的几何信息你可以用它来做物理模拟。注意事项深度估计是 AR Engine 的基础能力之一但它也有一些限制精度有限运动深度算法的精度不如 ToF 传感器特别在远处比如 5 米以外误差会更大。边缘模糊物体边缘的深度值往往不太准确因为算法很难精确判断物体的边界在哪。动态场景如果场景中有快速移动的物体深度估计可能会出现拖影现象。默认关闭深度模式默认是DISABLED的你必须显式设成AUTOMATIC才能用。最后提醒一下深度图和置信度图都是每帧更新的所以在onFrameUpdate回调里每帧都要重新获取。用完记得释放这是 AR 开发的基本功。
http://www.gsyq.cn/news/1408267.html

相关文章:

  • AI预约聊天机器人实战:从自然语言理解到GDPR合规部署
  • Java JVM技术周刊 2026年第17周
  • 4款降AI软件实测红黑榜:2026年5月哪个能真的去AI痕迹
  • 无锡专业短视频服务机构口碑排行 实测维度解析 - 奔跑123
  • LangChain工程实践:构建生产级智能体系统的架构与避坑指南
  • 为什么你的ChatGPT文档总被PM打回?揭秘技术传播链中缺失的3层语义对齐机制
  • 利用多模型聚合能力为ai绘画提示词生成器提供文本支持
  • AI安全专项:AI边缘计算的安全风险与防护
  • 终极指南:如何快速将QQ音乐QMC加密文件转换为MP3/FLAC格式
  • OceanBase 单机也能玩,安装中会遇到些什么?
  • 通宵改论文怕延毕?2026年4款降AI软件实测,AI痕迹一键去
  • 3步构建高性能Vue虚拟滚动列表:解决万级数据渲染难题
  • UOS软件安装翻车实录:那些年我遇到的‘依赖地狱’和‘启动器失踪案’及解决办法
  • 手机和电脑怎么传文件?从 TCP 到 UDP,手写一个 Android Socket 聊天 App(附完整代码)
  • 别再手动导数据了!用Kettle Spoon 9.0零代码搞定MySQL到PostgreSQL的定时同步
  • TestNG 常用断言(Assert)
  • C语言程序设计作业题
  • 烟台商户获客适配出租车媒体广告机构排行一览 - 奔跑123
  • CLAD:基于OpenCL的并行自动微分库,加速大规模光束法平差
  • STM32+ESP8266 MQTT实战:从传感器到OneNet物联网平台的数据上云之旅
  • 从点击理由看《痛快活一回》的推荐路径
  • Labview 机器视觉(1)之环境搭建与模块选型
  • 2026 国内 GEO 优化服务排行榜:TOP5 权威评测
  • 告别原生Socket:用Netty 4.1.72重构你的Modbus-RTU服务端(附心跳与设备管理实战)
  • 清单来了:盘点2026年最受欢迎的的AI智能降重工具 - 降AI小能手
  • Mac小白必看:用Easy App Locker给微信、相册加把锁,再也不怕别人借电脑了
  • 温州沙发翻新换皮换布哪家好?匠阁 / 御匠 / 锦修三大品牌联系方式、服务内容及区域全解析 - 卓信营销
  • 从搜索入口看《我想我爱到失眠了》的传播价值
  • STM32MP157实战:手把手教你搞定USB OTG驱动,让开发板变身U盘和声卡
  • 避坑指南:STM32MP157 USB Host驱动配置与Type-C芯片(FUSB302)移植详解