news 2026/8/27 12:17:56

HarmonyOS 真机实战:一张普通照片怎样自动抠出人物并生成旅行海报

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
HarmonyOS 真机实战:一张普通照片怎样自动抠出人物并生成旅行海报

HarmonyOS 真机实战:一张普通照片怎样自动抠出人物并生成旅行海报

真机环境:ALN-AL80,OpenHarmony 7.0.0.32(Beta2),API 26;人物素材为专门生成的虚构成年旅行者测试图,不包含真实用户和私人相册内容。

为什么旅行合成最难的是第一步

把人物放到海岸、雪山或古镇模板上,看起来像一次普通的图片叠加。真正影响结果的却是人物边缘:头发、背包带、衣服轮廓只要带着原背景,换景后就会出现明显灰边;让用户用手指一点点涂抹,又很难成为相册里的高频功能。

双镜记忆相机已经有旅行模板和图片编辑页,缺少的是从普通照片直接得到透明前景的入口。本次实践使用 Core Vision Kit 主体分割,从相册详情发起抠图,得到人物前景后进入模板编辑,最后导出一张新的 JPEG,并保留原照片。

验证链路按四个画面连续进行:原始人物照片、主体分割后的默认模板、切换模板并调整大小、导出后回到真实照片详情。

先确认官方能力边界

Core Vision Kit 官方能力页将“主体分割”描述为检测并提取图片中区别于背景的前景物体或区域;Vision Kit 官方能力页也把主体分割用于应用内图片浏览和抠图场景。

本次使用的是@kit.CoreVisionKit中的subjectSegmentation:输入一张PixelMap,配置需要的主体数量和前景图,接口返回主体数量、主体明细以及带透明信息的前景图。旅行模板、人物缩放、位置调整和 JPEG 导出仍由应用完成。

这条边界很重要。主体分割结果是可继续编辑的前景素材,最终画面质量还取决于模板构图、人物比例、边缘融合和输出编码。

准备一张可公开复现的人物图

可复现的抠图测试需要固定、可公开使用的输入素材。本次使用一名虚构成年旅行者:蓝色外套、浅色长裤、橙色背包,人物完整站立在灰色背景前。服装与背景有足够色差,手脚也没有被画面裁断,便于观察主体轮廓。

图 1:从双镜记忆相机的照片详情进入“旅行画境”,输入图仍是带灰色背景的完整照片。

真实产品中,人物照片可能存在逆光、头发与背景同色、肢体被遮挡等情况。入口应允许服务返回“未识别到清晰主体”,不能用原图矩形直接覆盖模板来伪装抠图成功。

从 JPEG 解码到主体前景

主体分割服务接收PixelMap。沙箱中的 JPEG 需要先打开为只读文件,再按RGBA_8888解码:

constsourceFile=awaitfs.open(sourcePath,fs.OpenMode.READ_ONLY);constimageSource=image.createImageSource(sourceFile.fd);constsourcePixelMap=awaitimageSource.createPixelMap({editable:false,desiredPixelFormat:image.PixelMapFormat.RGBA_8888});

随后初始化模型,并明确要求返回一个主体的明细和前景图:

constinitialized=awaitsubjectSegmentation.init();if(!initialized){thrownewError('主体分割服务初始化失败');}constresult=awaitsubjectSegmentation.doSegmentation({pixelMap:sourcePixelMap},{maxCount:1,enableSubjectDetails:true,enableSubjectForegroundImage:true});if(result.subjectCount<=0){thrownewError('没有识别到清晰人物');}constforeground=result.subjectDetails?.[0]?.foregroundImage??result.fullSubject.foregroundImage;

subjectCount是进入编辑器前的硬条件。分割没有返回主体时,页面保留原照片并提示换一张轮廓更清晰的图片,不创建空白成片。

文件、ImageSource、源PixelMap和模型都在finally中释放。大尺寸照片连续处理时,如果只关注前景结果而忘记释放输入,几次操作就可能累积明显内存压力。

分割成功后直接进入模板编辑

真机完成主体分割后,灰色背景从人物周围消失,编辑页把透明前景放到默认旅行模板中。截图里人物背包、外套和腿部轮廓已经与新背景分离。

图 2:Core Vision Kit 返回人物前景,编辑页显示默认模板及可移动、缩放的人物图层。

编辑页不再读取原始 JPEG 作为人物层,而是持有分割后的前景PixelMap。模板层负责背景,人物层负责平移、缩放和镜像,两个图层在导出阶段合成。这样切换模板时不需要再次运行主体分割。

人物初始比例通常只是可用起点。横向海岸模板需要人物略小,竖向城市模板则可能需要上移。页面把比例限制在合理范围内,避免缩成一个点或放大到完全超出画布。

切换海岸模板并调整人物比例

第二步选择“海岸珊瑚落日”,把人物比例调到 85%。这次调整只改变编辑模型,透明前景没有重新生成。

图 3:模板已经切换为海岸落日,人物比例为 85%,脚部位置落在前景岩石区域。

模板切换和主体分割分开后,交互会更稳定:分割是耗时的模型任务,只执行一次;拖动、镜像和缩放是本地画布操作,可以实时响应。导出前还要把人物位置限制在成片画布内,避免手势结束后只剩一部分身体。

合成时遵循固定顺序:先绘制模板,再根据编辑参数绘制人物前景,最后生成一张新的PixelMap。原照片不会参与覆盖写入。

导出新照片,不覆盖原图

完成编辑后,应用把合成PixelMap以质量 94 编码为 JPEG,写入独立的travel_compositions目录:

constoutputDirectory=`${context.filesDir}/travel_compositions`;TravelComposeOutputService.ensureDirectory(outputDirectory);constsafeTemplateId=templateId.replace(/[^0-9a-zA-Z_-]/g,'_');constoutputPath=`${outputDirectory}/travel_card_${safeTemplateId}_${Date.now()}.jpg`;constoutputFile=fs.openSync(outputPath,fs.OpenMode.CREATE|fs.OpenMode.WRITE_ONLY|fs.OpenMode.TRUNC);constpacker=image.createImagePacker();awaitpacker.packToFile(composite,outputFile.fd,{format:'image/jpeg',quality:94});

输出成功后,新文件作为一条独立相册记录写入双镜记忆相机,并继承必要的旅行信息;原始人物照片仍保留在相册中。写文件或编码失败时会清理未完成的目标文件,避免图库里出现零字节成片。

图 4:导出的海岸旅行成片已经进入照片详情,页面提示原照片仍保留在相册中。

这张图完成了结果闭环:图 1 的灰底人物经过主体分割,图 2 进入模板,图 3 完成构图调整,图 4 则是实际写出的新 JPEG,而不是编辑页上的临时预览。

实践中最容易踩的几个点

1. 只要蒙版,不请求前景图

旅行合成需要直接绘制透明人物。配置中应打开enableSubjectForegroundImage;只取区域或蒙版还要增加一次像素处理,并承担边缘和透明通道的组合工作。

2. 把模型任务放进手势更新

主体分割应在进入编辑器时完成一次。缩放、移动和切换模板只更新本地编辑参数,不能在每次手势变化时重新调用模型。

3. 导出覆盖输入文件

覆盖原图会让用户失去拍摄记录,也会使相册索引和缓存失效。新成片使用独立路径和记录 ID,成功写入后再刷新相册。

4. 测试素材本身不适合抠图

人物被裁断、主体太小、衣服与背景完全同色时,分割边缘容易失真。公开测试素材保持完整人物和清晰轮廓;真实相册仍需要失败提示与重新选图入口。

最终效果

ALN-AL80 真机已经完成从普通人物照片到旅行成片的完整路径:JPEG 解码为RGBA_8888,Core Vision Kit 返回透明人物前景,编辑页切换海岸模板并把人物调整到 85%,最后输出新的 JPEG 并进入真实照片详情。

这套实现把模型能力放在最适合的位置:主体分割负责提供可编辑前景,画面设计由模板和本地编辑器完成,文件服务负责生成独立成片。四张连续真机图分别对应输入、分割、编辑和输出,最终结果可以在相册中继续查看、分享或制作回忆电影。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/27 12:17:49

100V输入无光耦反激电源设计:原边反馈原理与实操

前段时间做了一块板子&#xff0c;需求方只丢过来一行字&#xff1a;100-V No-Opto Flyback Regulator。翻译成大白话就是&#xff1a;输入直流母线最高到100V&#xff0c;输出一路隔离的稳压电源&#xff0c;拓扑用反激&#xff0c;反馈不能走光耦。样机调了两周&#xff0c;后…

作者头像 李华
网站建设 2026/8/27 12:16:37

LoRaWAN集成方案解析:PSoC 6与SX126x如何加速智能门锁开发

做物联网硬件开发这几年&#xff0c;有一个问题几乎每个产品定义会上都会撞上&#xff1a;无线连接到底选什么&#xff1f;WiFi 功耗太大&#xff0c;蓝牙距离不够&#xff0c;NB-IoT 要插卡还要算资费。剩下的选项里&#xff0c;LoRaWAN 在低功耗和覆盖距离上确实能打&#xf…

作者头像 李华
网站建设 2026/8/27 12:16:13

WPF图标制作,图形设计转换为矢量Path。

前言 在软件开发过程中&#xff0c;图形元素必不可少&#xff0c;而在WPF中如果使用jpg或png等格式&#xff0c;在应用到Button等控件时的样式时&#xff0c;常常需要做MouseEnter,MouseDown鼠标事件提供不同的颜色或特效。一个图标得分别生成三种颜色才行。如下&#xff1a; N…

作者头像 李华
网站建设 2026/8/27 12:12:16

bug分析记录-添加商品列表没有出现商品

问题1&#xff1a;商品管理列表中添加商品后&#xff0c;商品列表没有看到该条商品记录 分析&#xff1a; 第一步&#xff1a;查看数据库表中是否有添加的数据。 情况①&#xff1a;数据库表中有商品记录&#xff0c;则添加成功&#xff0c;分析判断大概率是列表查询问题&#…

作者头像 李华
网站建设 2026/8/27 12:12:16

数学建模实战:AHP-熵权-TOPSIS组合模型在综合评价中的应用

1. 从“影响评价”到“数据驱动决策”&#xff1a;一个建模者的实战复盘去年带队参加电工杯&#xff0c;B题“人工智能对大学生学习影响的评价”一出来&#xff0c;我们团队就意识到&#xff0c;这绝不是一个简单的“好”或“坏”的判断题。它本质上是一个典型的多指标综合评价…

作者头像 李华
网站建设 2026/8/27 12:12:11

第 36 章:电话与 RIL

Android 的电话子系统是平台中最复杂、分层最多的模块之一。它从任意应用都可以调用的公开 SDK API(TelephonyManager、SmsManager),经过拥有特权的系统服务(PhoneInterfaceManager)、内部的 phone 对象层级、向蜂窝调制解调器序列化请求的无线接口层(RIL),最终到由硬件…

作者头像 李华