HarmonyOS 7 3DGS 端侧重建实战:从拍视频到生成 3D 模型的全流程拆解
以前搞3D建模得用专业软件或者云端跑几小时,现在拿着HarmonyOS 7手机,拍一圈就能在端侧生成3D模型,今天就带大家亲手把这个流程跑通。
聊聊这玩意儿到底多香
兄弟们,不知道你们有没有这种经历:想给自家猫主子建个3D模型,结果不是要啃Blender几个月,就是得把照片传到云端等半天。说实话,门槛真不是一般的高。
但HarmonyOS 7(API 26)搞了个大事情——把3DGS(3D Gaussian Splatting,三维高斯溅射)端侧重建做成了系统级API。啥概念?就是你拿着手机拍一圈,本地就能生成3D模型,数据都不用上传,隐私安全拉满。
这玩意儿跟之前的NeRF比,最大的区别就是快。NeRF训练一次几小时,渲染一帧好几秒;3DGS训练几分钟,渲染直接跑到30FPS以上。鸿蒙这套还专门用了NPU加速,中端手机几十秒就能出活。
不废话了,咱们直接上手干。
第一步:先把环境支棱起来
权限配置
打开你的module.json5,把该申请的都申请了:
"requestPermissions": [
{
"name": "ohos.permission.CAMERA",
"reason": "拍物体照片做3D重建",
"usedScene": {"abilities": ["EntryAbility"]}
},
{
"name": "ohos.permission.READ_MEDIA_IMAGES",
"reason": "读取图片用于重建"
},
{
"name": "ohos.permission.WRITE_MEDIA_FILES",
"reason": "保存生成的3D模型"
}
]
重点来了:系统能力声明不能少,不然API调了直接报错:
"SystemCapability.Graphics.SpatialRecon",
"SystemCapability.Graphics.SpatialRender"
引入依赖
import { spatialRecon, spatialRender, spatialImage } from '@kit.ArkGraphics3D';
import { camera } from '@kit.CameraKit';
import { fileIo } from '@kit.CoreFileKit';
第二步:判断设备能不能跑
不是所有鸿蒙设备都支持3DGS重建,得先做个检测:
import { spatialImage } from '@kit.ArkGraphics3D';
function checkDeviceSupport(): boolean {
const status = spatialImage.SpatialImageGenerator.isSupport();
switch(status) {
case spatialImage.SpatialImageStatus.STATUS_SUCCESS:
console.log('✅ 设备支持,模型已就绪');
return true;
case spatialImage.SpatialImageStatus.STATUS_AIMODEL_NOT_EXIST:
console.log('⚠️ 设备支持,但需要下载AI模型');
downloadModel(); // 调用 prepareEnv 下载
return true;
case spatialImage.SpatialImageStatus.STATUS_NOT_SUPPORT:
console.log('❌ 设备不支持3DGS重建');
return false;
default:
return false;
}
}
第三步:核心——图像采集 + 重建
配置重建参数
const reconConfig: spatialRecon.ReconstructionConfig = {
mode: spatialRecon.ReconstructionMode.HIGH_QUALITY, // 高质量模式
maxFrames: 120, // 最多采集120帧
enableDensification: true,// 开启稠密化,细节更丰富
gaussianCount: 500000 // 高斯球数量上限,低端机调低到20万
};
创建会话并开始重建
这段代码是核心中的核心,建议直接抄走:
import { spatialRecon } from '@kit.ArkGraphics3D';
async function startReconstruction(
imagePixelMaps: Array<image.PixelMap>,
onProgress: (stage: string, percent: number) => void
): Promise<string> {
// 1. 创建重建会话
const session = await spatialRecon.createSession(reconConfig);
// 2. 订阅进度回调
session.on('progress', (stage: string, percent: number) => {
console.log(`阶段: ${stage}, 进度: ${(percent * 100).toFixed(0)}%`);
onProgress(stage, percent);
});
// 3. 逐帧喂入图像
for (let img of imagePixelMaps) {
await session.addFrame(img);
}
// 4. 执行重建,输出PLY模型文件
const outputPath = '/data/storage/el2/base/haps/entry/files/model.ply';
const result = await session.reconstruct(outputPath);
console.log('🎉 重建完成!模型保存在:', outputPath);
return outputPath;
}
注意:
on('progress')的回调里,percent是0到1之间的小数,显示百分比记得乘100。
第四步:渲染——把模型秀出来
用XComponent搭画布
import { sceneKit } from '@kit.SceneKit';
@Entry
@Component
struct ModelViewerPage {
private sceneController: sceneKit.SceneController = new sceneKit.SceneController();
private gaussianNode: sceneKit.GaussianSplattingNode | null = null;
@State isLoading: boolean = true;
build() {
Stack() {
XComponent({
id: 'scene3d',
type: XComponentType.SURFACE,
controller: this.sceneController.getXComponentController()
})
.width('100%')
.height('100%')
.onLoad(() => {
this.loadModel();
})
if (this.isLoading) {
Column() {
LoadingProgress()
.width(60)
.height(60)
Text('模型加载中...')
.fontSize(16)
.fontColor('#FFFFFF')
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
.backgroundColor('rgba(0,0,0,0.5)')
}
}
}
async loadModel() {
const scene = this.sceneController.getScene();
const rootNode = scene.getRootNode();
// 加载3DGS模型
this.gaussianNode = scene.createGaussianSplattingNode({
uri: 'file:///data/storage/el2/base/haps/entry/files/model.ply'
});
if (this.gaussianNode) {
rootNode.addChild(this.gaussianNode);
this.isLoading = false;
}
}
}
第五步:进阶——模型编辑(能删能改)
鸿蒙7的Spatial Recon Kit还支持对生成的高斯球模型做编辑,比如框选删除多余物体:
import { spatialRecon } from '@kit.SpatialReconKit';
async function editGaussianModel(modelPath: string) {
const gsModel = await spatialRecon.loadModel(modelPath);
// 框选不想要的区域(比如桌面上多扫进去的茶杯)
const boundingBox = {
min: { x: -1.0, y: -0.5, z: -1.0 },
max: { x: 1.0, y: 0.5, z: 1.0 }
};
// 删除框内的高斯球
gsModel.deleteGaussiansInBox(boundingBox);
// 导出编辑后的模型
await gsModel.export('/data/storage/el2/base/haps/entry/files/model_edited.ply');
}
踩坑指南(血泪教训)
1. 拍视频有讲究
- 别怼脸拍:物体占画面比例别超过70%
- 转圈要平滑:最好间隔15度左右拍一张,一共拍20-30张
- 光线要均匀:别半边亮半边暗,重建出来会崩
2. 模型下载失败
如果isSupport()返回STATUS_AIMODEL_NOT_EXIST,记得调用prepareEnv()下载模型文件,需要联网权限:
await generator.prepareEnv((progress: number) => {
console.log(`模型下载进度: ${progress}%`);
});
3. 内存溢出
3DGS重建很吃内存,如果App闪退,可以降低gaussianCount或减少输入的图片数量。同一时间只能跑一个重建任务,别并发搞。
4. 渲染黑屏
检查两个地方:一是确认loadPlugin有没有调用,二是检查场景里有没有加光源。3DGS模型本身不带光照信息,场景环境光得配好。
能拿来干啥?
这套能力落地场景真不少,我列几个方向供参考:
- 商品3D展示:电商App让用户拍一圈商品,直接生成3D预览,比图片直观多了
- 文旅展陈:博物馆文物数字化,游客手机扫码就能看3D文物
- 文化遗产保护:给古建筑建数字档案,数据不出设备,安全可控
- 个人创作:普通人也能做3D建模师,门槛大幅降低
最后我要说
从拍视频到生成3D模型,HarmonyOS 7这套3DGS端侧重建API把流程压缩到了几分钟之内,而且全程在设备本地跑,数据不用上传。这在以前想都不敢想。
建议动手试一下,拿着手机拍个手办或者家里的盆栽,看看重建出来的效果有多惊艳。代码在真机上跑通了,欢迎来评论区交作业!
如果这篇文章帮到了你,点赞收藏不迷路,遇到问题评论区见,看到就回。(抖音: 黑马程序员就业指南)
更多推荐



所有评论(0)