HarmonyOS 7文搜图 + 3DGS:文字描述检索并加载空间资产
文搜图 3DGS文字描述检索并加载空间资产商品库里有 3000 多个 3DGS 资产用户在搜索框敲一句红色运动鞋期望不是看到一张平面缩略图而是直接把对应的高斯点模型加载进空间场景里转着看。这件事拆开看是两段能力拼起来的前半段是 Core Vision Kit 的文搜图Text Search把文字映射到候选图后半段是 Spatial Recon Kit 的 GSNode 加载把候选图背后的 3DGS 资产 ID 拉进渲染场景。两段都不难难的是中间那张图 → 3DGS 资产 ID的映射表怎么维护、检索结果排序怎么对齐用户预期。能力面文搜图 API 与资产映射Core Vision Kit 在 API 26 暴露的 Text Search 接口位于kit.CoreVisionKit目前仍带 Beta 标记。基本用法是建一个检索会话喂入查询文本拿到一组带相似度分数的候选图。// entry/src/main/ets/textsearch/TextSearchSession.etsimport{textSearch}fromkit.CoreVisionKit;exportclassAssetTextSearch{privatesession:textSearch.TextSearchSession|nullnull;asyncinit(imageDbUri:string):Promisevoid{// imageDbUri 指向预先建好的检索库一组带索引的图constopts:textSearch.SessionInitOptions{databaseUri:imageDbUri,// 检索库模式本地嵌入向量库离线可用mode:textSearch.Mode.LOCAL};this.sessionawaittextSearch.createSession(opts);}asyncsearchByText(query:string,topK:number5):PromisetextSearch.SearchResult[]{if(!this.session){thrownewError(session not initialized);}constreq:textSearch.SearchRequest{queryText:query,topK:topK,// 返回字段图片 uri、相似度分数、自定义元数据fields:[uri,score,meta]};constresp:textSearch.SearchResponseawaitthis.session.search(req);returnresp.results;}release():void{this.session?.close();this.sessionnull;}}检索结果给的是图片 uri 和相似度分数不是 3DGS 资产 ID。中间这张映射表得自己维护。我们的做法是在建检索库的时候把每个商品图的meta字段塞进assetId检索回来直接读meta.assetId去查 3DGS 资产表。// 检索结果到 3DGS 资产的映射interfaceAssetMapping{imageUri:string;assetId:string;// 3DGS 资产 IDgsNodeUri:string;// GSNode 加载 uri例如 file:///.../sneaker_red.plycategory:string;businessWeight:number;// 业务权重用于排序调整}asyncfunctionretrieveAndLoad(query:string,searcher:AssetTextSearch,mappingTable:Mapstring,AssetMapping):PromisespatialRender.GSNode|null{constresultsawaitsearcher.searchByText(query,5);if(results.length0){returnnull;}// 取 Top1实际场景里要做排序调整见第 44 篇consttopresults[0];constmappingmappingTable.get(top.uri);if(!mapping){// 检索命中的图没有对应 3DGS 资产这是常见坑后面展开console.warn(hit image${top.uri}has no 3DGS asset);returnnull;}// 加载 3DGS 资产进场景scene/root 需要外部传入returnawaitloadGsAsset(mapping.gsNodeUri);}约束面Beta 标记、召回率、资产库成本文搜图在 API 26 仍是 Beta。Beta 的含义不是不能用是接口签名可能在下一个 API 版本调整。我们这边封装了一层AssetTextSearch把textSearch的所有调用收在内部真要迁移只改这一个文件。这个隔离层在 Beta 阶段必须有否则接口一变全局搜替换很痛。召回率是另一个硬约束。官方在通用数据集上给的召回率数字好看但商品场景不是通用数据集。我们实测 500 个商品图、50 条 query整体 Top5 召回率 62%离宣传的 85% 差一截。差异来源主要是商品描述高度同质化——红色运动鞋和红色跑步鞋在嵌入空间里不一定近红色板鞋可能更近。第 44 篇专门展开这个测法。3DGS 资产库的构建成本是第三道坎。文搜图能召回的前提是检索库里要有图3DGS 能加载的前提是资产表里有对应模型。一个商品要进这个链路得先拍图、再重建 3DGS、再给图建索引。我们团队测下来一个中等复杂度商品一双鞋从采集到 3DGS 重建完成大约 8-12 分钟3000 个商品全量建库是个不小的工程。实际落地建议先挑高频类目建库长尾商品按需补建否则上线节奏会被资产生产拖死。建库流程里有个容易忽略的细节检索库的图和 3DGS 重建用的采集图不一定是同一张。检索库要的是能代表商品外观的封面图通常是棚拍白底图3DGS 重建要的是多角度环绕拍摄的视频帧。两张图来自不同工序但都要挂在同一个assetId下。我们第一版把检索库的图直接拿去重建结果重建质量很差——单张棚拍图视角单一3DGS 重建需要多视角覆盖。后来改成两条独立工序棚拍图进检索库环绕视频进重建管线用assetId做关联键。这个分工理清楚后建库效率高很多。检索库本身的体积也要关注。500 张商品图的嵌入向量库约 12 MB3000 张约 72 MB。这个库要随应用打包或首次启动下载体积太大影响首装体验。我们的做法是库分片按类目切用户进哪个类目才下载哪个分片首装只带高频类目的 8 MB。场景落地电商完整链路把链路画出来是这样是否用户输入红色运动鞋Text Search 检索 Top5命中图有 3DGS 资产?读 meta.assetId 查映射表降级返回平面缩略图加载 GSNode 进场景用户旋转/缩放查看用户点击常规商品页中间那个判断节点C是踩坑踩出来的。第一版我们假设检索命中的图一定有 3DGS 资产结果线上跑起来一堆mapping not found警告。原因是商品库分两批建的第一批 800 个有 3DGS后面补的 2200 个只有平面图。检索库是全量 3000 张图3DGS 资产表只有 800 条必然对不上。降级路径不能省。降级路径的 UI 处理也有讲究。从 3DGS 降级到平面图视觉上有明显跳变——用户期望看到立体模型结果给了张平面图体感是功能坏了。我们的做法是降级时加一句解释“该商品 3D 模型制作中先看平面图”把降级包装成暂时而非不可用。这个文案调整后降级路径的用户投诉降了一半。技术降级要配合文案降级不要默默给个差结果。检索结果的展示顺序也要注意。Top5 结果如果全展示用户可能不点 Top1 而点 Top3。我们的数据显示 Top1 点击率 61%Top2 18%Top3 11%Top4-5 加起来 10%。如果只展示 Top1 自动加载 3DGS省了用户选择步骤但用户失去比较机会。折中做法是 Top1 自动加载右侧缩略图列 Top2-5用户想换点缩略图。这个交互比5 个都让用户选更顺滑。完整可运行的页面组件这个页面有几个工程要点值得展开。第一是检索库初始化放在aboutToAppear里首次启动时如果库文件不存在要从远端拉。拉取过程要显示进度不能让用户对着空白页等。我们的做法是首次启动拉检索库时显示正在准备商品搜索能力约 X 秒拉完缓存到沙箱后续启动直接读本地。库版本要校验远端更新后本地旧库要重新拉否则检索结果用的是旧嵌入向量。第二是 3DGS 加载完要把status切到ready触发 UI 刷新显示 Component3D。这个状态切换不能忘否则场景加载了但 UI 不显示用户以为卡住了。ArkUI 的声明式 UI 靠State驱动刷新状态不切 UI 不动。第三是搜索按钮的防重入。用户连点搜索按钮会触发多次检索和加载浪费资源且可能因为并发加载 GSNode 出错。按钮 onClick 里要加 loading 状态判断搜索中禁用按钮。这个细节小但不能漏。// entry/src/main/ets/pages/AssetViewerPage.etsimport{Scene,RenderContext,Node,Component3D}fromkit.ArkGraphics3D;import{spatialRender}fromkit.SpatialReconKit;import{AssetTextSearch}from../textsearch/TextSearchSession;EntryComponentstruct AssetViewerPage{privatescene:Scene|nullnull;privatesearcher:AssetTextSearchnewAssetTextSearch();StatequeryText:string;Statestatus:stringidle;StatehasGsAsset:booleanfalse;StatefallbackImageUri:string;asyncaboutToAppear():Promisevoid{// 检索库放在应用沙箱首次启动从远端拉取awaitthis.searcher.init(file:///data/storage/el2/base/files/asset_index.db);awaitthis.initScene();}privateasyncinitScene():Promisevoid{constctxScene.getDefaultRenderContext();if(!ctx)return;ctx.loadPlugin(spatialRender.GSPlugin.PLUGIN_ID);this.sceneawaitScene.load();}asynconSearch():Promisevoid{if(!this.queryText||!this.scene)return;this.statussearching;constt0Date.now();constresultsawaitthis.searcher.searchByText(this.queryText,5);constsearchMsDate.now()-t0;console.info(text search cost:${searchMs}ms, hits:${results.length});if(results.length0){this.statusno_result;return;}consttopresults[0];constmappingawaitthis.lookupMapping(top.uri);if(!mapping){// 降级到平面图this.hasGsAssetfalse;this.fallbackImageUritop.uri;this.statusfallback_image;return;}this.statusloading_gs;constt1Date.now();constgsNodeawaitthis.loadGs(mapping.gsNodeUri);console.info(gs load cost:${Date.now()-t1}ms);this.hasGsAssettrue;this.statusready;}privateasynclookupMapping(imageUri:string):PromiseAssetMapping|null{// 实际从本地 KV 表查这里省略returnnull;}privateasyncloadGs(uri:string):PromisespatialRender.GSNode{constrootthis.scene!.rootasNode;returnawaitspatialRender.GSPlugin.loadGSNode(this.scene!,{uri,offset:0},root);}build(){Column(){TextInput({placeholder:描述你想看的商品}).onChange((v:string){this.queryTextv;})Button(搜索).onClick((){voidthis.onSearch();})if(this.statussearching||this.statusloading_gs){LoadingProgress()}if(this.hasGsAssetthis.scene){Component3D({scene:this.scene}).width(100%).height(70%)}if(!this.hasGsAssetthis.fallbackImageUri){Image(this.fallbackImageUri).width(100%).height(50%)Text(该商品暂无 3D 模型展示平面图).fontSize(14)}}.width(100%).height(100%)}}真机数据测试设备麒麟 9030 旗舰机一台、麒麟 9020 一台、中端机非 9020/9030 系列一台。检索库 500 张商品图50 条人工编写 query。指标9030 旗舰9020 旗舰中端机检索耗时Top5180-240 ms220-300 ms450-680 msTop5 召回率62%61%58%3DGS 加载耗时单资产 ~12MB320-410 ms380-520 ms不保证端到端输入到模型可见580-740 ms690-880 ms降级路径几个值得说的点。检索耗时中端机比旗舰机慢一倍多但都能在 1 秒内出结果这部分体验不是瓶颈。瓶颈在 3DGS 加载——12MB 的资产 9030 上也要 300 ms资产越大越明显。端到端 600-900 ms 用户体感是有一下延迟但能接受超过 1.5 秒就会有人开始重 tap。召回率 62% 这个数字我们内部吵了一架。产品同学坚持说官方宣传 85%是不是我们库建得不对。后来排查发现官方 85% 是在公开通用数据集上测的商品图高度同质化、query 又偏口语召回率掉到 60% 出头是正常的。这个差距在第 44 篇有完整测法。中端机那一列写不保证是有原因的。Spatial Recon Kit 仅保证麒麟 9020/9030S/9030/9030 Pro 及后续旗舰芯片的体验中端机查询 API 返回支持但实际加载 3DGS 帧率只有 18-22 fps转着看会卡。我们的策略是中端机直接走降级路径给平面图不强行上 3DGS。设备分档的判断逻辑放在应用启动时跑一次结果缓存。判断依据不是机型型号而是芯片型号——同一机型不同批次可能换芯片。deviceInfo.getChipSeries()拿到芯片系列匹配 9020/9030 系列才走 3DGS 路径。这个判断要留升级口子后续新芯片出了支持列表要更新别写死成if (chip 9030)这种。检索耗时在不同 query 长度下也有差异。短 query2-4 字比长 query8 字快 30-50 ms原因是短 query 的嵌入计算量小。这个差异对用户体验影响不大但做耗时基准测试时要覆盖各种 query 长度别只测中等长度 query 拿个平均数就交差。踩坑与取舍坑一检索命中的图对应 3DGS 资产没建。 前面提过检索库和资产表两批建的对不上。修复办法是建库流程改成原子操作一个商品要么图和 3DGS 都进要么都不进不允许只进图不进模型。已经入库的脏数据写个对账脚本扫一遍把没资产的图从检索库剔除否则用户搜到了却加载不了比搜不到还糟。坑二检索结果排序和用户预期不一致。 用户搜红色运动鞋Top1 召回一张红色高跟鞋因为视觉上确实红、确实像鞋。相似度分数上高跟鞋就是比运动鞋高一点。纯靠相似度排序在商品场景里不行得叠业务权重。简单做法是给每个类目一个 boostquery 命中运动鞋关键词时把运动鞋类目的分数乘 1.3。这个排序优化的完整实现放第 44 篇。坑三Beta 接口在 minor version 升级后签名变了。 我们在 API 26 minor 2 升到 minor 3 的时候SearchRequest的fields字段从可选变成必填没改的话编译过不去。Beta 阶段每次升级都要扫一遍 changelog别指望接口稳定。坑四检索库更新和在线检索冲突。 商品库会增量上新货检索库要跟着更新。但更新检索库时如果有用户正在检索会出现检索结果引用了已被替换的图 uri加载 3DGS 时 404。我们的做法是检索库用版本号管理更新时新版本写另一个文件原子切换指针旧版本等当前所有检索会话结束后才清理。这个读写分离在并发场景不能省。被放弃的方案 一开始想用云端多模态大模型做检索效果确实好召回率能到 78%。但电商场景要求离线可用地铁里、弱网环境且云端调用有成本和延迟单次 800-1200 ms 网络往返。最后还是用端侧文搜图召回率低一点但离线可用、延迟低。这个取舍在弱网场景占比高的用户群体里是对的如果目标用户全是 WiFi 环境云端方案可能更合适。另一个被放弃的方案是先分类目录再文搜图。做法是 query 先过一层类目分类器确定类目后在类目内做文搜图。理论上类目内检索召回率更高同质化干扰小。实测确实有效鞋类类目内召回率从 71% 到 79%。但类目分类器本身有 12% 的误分类率误分类的 query 直接掉到错误类目里搜召回率反而更差。综合下来整体召回率没提升工程复杂度倒是上去了。放弃留作后续分类器精度上来再试。小注意哦文搜图接口带 Beta 标记封装隔离层禁止业务代码直接调textSearch检索库与 3DGS 资产表必须同进同出建库流程原子化必须有降级路径无结果、命中图无 3DGS 资产、设备不支持 3DGS三段都要兜中端机非麒麟 9020/9030 系列旗舰默认走平面图降级不强行加载 3DGS排序不能纯靠相似度叠业务权重具体做法见第 44 篇

相关新闻

Delphi数据库组件源码跨版本编译与实战指南

Delphi数据库组件源码跨版本编译与实战指南

简介:Absolute Database v7.93 源代码包面向 Delphi 开发者,尤其是需要在 Delphi 4 至 11(含 Delphi 11 Alexandria)环境中集成嵌入式关系型数据库的工程师。它提供完整的数据库引擎实现,涵盖事务处理、内存与缓存优化…

2026/10/15 15:43:46 阅读更多 →
HarmonyOS 7重建结果缓存策略:LRU 与按场景分组

HarmonyOS 7重建结果缓存策略:LRU 与按场景分组

重建结果缓存策略:LRU 与按场景分组 商品列表有 50 个 3DGS 场景,用户翻来翻去看。第一次进商品详情要重建(或下载预重建结果),耗时 600-1200 ms。第二次进同一个商品如果还要重建,用户会觉得"我都看过…

2026/10/15 15:43:46 阅读更多 →
老鼠走迷宫课设:用栈与队列吃透DFS和BFS

老鼠走迷宫课设:用栈与队列吃透DFS和BFS

简介:一份面向数据结构课程设计场景的C迷宫求解项目,适合计算机相关专业学生完成课设或练习图、栈、DFS/BFS等算法时参考;项目把迷宫抽象为二维数组表示的图,用0/1标记通路与墙体,以老鼠走迷宫为线索,完整演…

2026/10/15 15:43:46 阅读更多 →

最新新闻

AP-0316语音处理模组实战:回声消除与波束成形调试指南

AP-0316语音处理模组实战:回声消除与波束成形调试指南

1. 这块模组到底解决了什么问题语音交互这件事,看起来简单,做起来处处是坑。你对着设备喊一句话,设备听到的可能是:你自己的声音、隔壁房间的电视声、空调出风口的呼呼声、桌面共振的低频嗡嗡声,以及电路本身产生的底噪…

2026/10/15 16:27:40 阅读更多 →
高光谱数据加载:PyTorch自定义Dataset与DataLoader全链路解析

高光谱数据加载:PyTorch自定义Dataset与DataLoader全链路解析

简介:面向PyTorch深度学习中需要处理高光谱图像的开发者,这份资源提供了一套完整的高光谱数据加载方案。方案基于DataLoader组件,详细说明了自定义Dataset类的编写方法、光谱通道的归一化处理、批大小的合理设置、多线程加载加速、随机打乱数…

2026/10/15 16:27:40 阅读更多 →
Texture2D.ReadPixels截屏原理与实战:从帧缓冲到图片文件

Texture2D.ReadPixels截屏原理与实战:从帧缓冲到图片文件

1. 截屏这件事,为什么值得单独拎出来聊做游戏开发或者图形工具开发的朋友,迟早会碰到一个需求:把当前画面截下来。可能是给玩家做个拍照模式,可能是自动化测试里要对比渲染结果,也可能是编辑器工具里要生成一张缩略图。…

2026/10/15 16:27:40 阅读更多 →
msvcp120.dll与msvcp140.dll缺失别重装:DLL运行库修复

msvcp120.dll与msvcp140.dll缺失别重装:DLL运行库修复

1. 别急着重装系统:先搞懂DLL报错到底是怎么回事 经常有朋友拿着截图来问我:某软件启动弹出“缺少msvcp120.dll,无法继续执行代码”,或者“无法定位程序输入点……于动态链接库msvcp140.dll上”,是不是得重装系统&…

2026/10/15 16:27:40 阅读更多 →
FFmpeg 多路 RTMP 推流实战:118 克盒子跑稳 5 路

FFmpeg 多路 RTMP 推流实战:118 克盒子跑稳 5 路

音视频处理这个领域,很多人第一次接触 FFmpeg 都是被命令行劝退的——参数多如牛毛,文档又散又杂,一个-map用错了就死活不出声。但只要你熬过最初那段"盲人摸象"的阶段,就会发现这东西确实是名副其实的瑞士军刀&#xf…

2026/10/15 16:27:40 阅读更多 →
C语言银行系统实战:消息队列实现进程间通信与并发控制

C语言银行系统实战:消息队列实现进程间通信与并发控制

前段时间我动手写了一个C语言的银行系统练手项目,功能清单看着很常规:开户、销户、存钱、取钱、转账、查询、保存用户信息。但标题里真正藏关键的是最后那句——使用消息队列达到两个不同进程之间的相互通信。这句话直接把项目的难度从“文件读写练习”拉…

2026/10/15 16:26:30 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →