HarmonyOS 7/API 26 图像超分实战:4439×2959 的原图,为什么生成了 6400×4264?
测试环境:ALN-AL80 真机,OpenHarmony 7.0.0.32,API 26;输入为一张 4439×2959 的 CC0 湖边照片。
为什么要做“清晰修复”
照片被裁切、压缩或放到大屏上展示时,普通缩放只能增加像素数量,边缘和纹理不会随之恢复。HarmonyOS 7/API 26 在 Core Vision Kit 中新增图像超分能力,应用可以把 PixelMap 交给系统进行超分辨率重建。
华为官方版本说明将图像超分描述为“对低分辨率图像进行超分辨率重建,使图像更加清晰”。对应的图像超分开发指南和API 参考给出了 ImageSRAnalyzer 的调用方式;API 26 变更清单将该能力列入 Core Vision Kit 的新增 API。本机 SDK 中的 create()、process() 和 destroy() 均标注为 @since 26.0.0。
双镜记忆相机接入这项能力时确定了两个产品要求:处理结果保存成新文件,原图继续保留;页面同时展示处理前后的真实尺寸和同区域画面,避免只用“处理成功”代替效果判断。
处理前:原始文件是 4439×2959
测试图来自应用沙箱。详情页通过 ImageSource.getImageInfo() 读取 JPEG 的实际宽高,得到 4439×2959。

图 1:处理前,详情页读取到原始 JPEG 尺寸为 4439×2959。
如果把这组尺寸直接和最终文件比较,很容易得出“系统把 4439×2959 放大到 6400×4264”的结论。实际处理链路中还有一次解码缩放,模型没有直接接收完整原图。
API 26 的最小调用
图像超分的系统调用集中在三步:创建分析器、传入 PixelMap、取得输出 PixelMap。
const analyzer = await imageSuperResolution.ImageSRAnalyzer.create();
const response = await analyzer.process({
inputData: { pixelMap: sourcePixelMap }
});
const outputPixelMap = response.pixelMap;
接口返回的是像素对象,不会替应用保存 JPEG,也不会创建相册记录。文件解码、输入尺寸控制、结果编码、异常清理和原图保护都由应用完成。
点击“清晰修复”后,页面进入忙碌状态,禁止同一张照片重复启动任务:

图 2:真机正在执行图像超分,处理期间按钮不可重复触发。
4439×2959 → 1600×1066 → 6400×4264
项目把模型输入长边限制为 1600。解码比例按原图长边计算:
const maxInputSide = 1600;
const decodeScale = Math.min(
1,
maxInputSide / Math.max(sourceWidth, sourceHeight)
);
const desiredWidth = Math.floor(sourceWidth * decodeScale);
const desiredHeight = Math.floor(sourceHeight * decodeScale);
代入本次原图尺寸:
floor(4439 × 1600 / 4439) = 1600
floor(2959 × 1600 / 4439) = 1066
ImageSRAnalyzer 在这台真机上返回 6400×4264:
1600 × 4 = 6400
1066 × 4 = 4264
完整链路为:
4439×2959 原始 JPEG
↓ 按长边 1600 解码
1600×1066 输入 PixelMap
↓ ImageSRAnalyzer.process()
6400×4264 输出 PixelMap
↓ JPEG,quality 94
6400×4264 新文件
本次观察到的 4 倍倍率属于 ALN-AL80、OpenHarmony 7.0.0.32 和当前输入条件下的返回结果。输出宽高直接读取 response.pixelMap,设备、系统服务或输入条件变化后,页面会显示新的实际尺寸。
处理后:生成新文件,原图继续保留
超分完成后,应用将输出 PixelMap 以 JPEG quality 94 写入新路径,再从新文件重新读取尺寸,页面显示 6400×4264。

图 3:处理后,新文件的实际尺寸为 6400×4264。
相册中新增一条“由清晰修复生成”的记录,原始记录和原始文件没有写操作:

图 4:原图与超分结果同时保存在相册中。
| 检查项 | 处理前 | 处理后 |
|---|---|---|
| 文件尺寸 | 4439×2959 | 6400×4264 |
| 模型实际输入 | — | 1600×1066 |
| 相册记录 | 原始照片 | 新增“清晰修复”记录 |
| 原文件 | 存在 | 继续保留 |
为什么限制模型输入为 1600
RGBA_8888 每个像素至少占 4 字节。1600×1066 的输入像素数据约为 6.51 MiB,6400×4264 的输出约为 104.10 MiB;两块 PixelMap 同时存在时,像素缓冲已经超过 110 MiB。
进程峰值还包括原始 JPEG 字节、ImageSource、分析器内部数据、编码缓冲和目标文件。完整的 4439×2959 RGBA 输入本身约为 50 MiB,如果系统继续返回数倍尺寸结果,内存和处理时间都会明显增加。
长边 1600 是双镜记忆相机当前单图预览场景的资源边界,不是 Core Vision Kit 的固定倍率或最佳输入值。更换输入限制后,需要重新测量输出尺寸、峰值内存、处理时间和失败率。
应用在 createPixelMap() 后还会读取一次实际解码尺寸。若得到的长边仍超过 1600,再对 PixelMap 执行缩放,保证交给分析器的真实对象符合产品限制。
输出文件怎样避免留下半成品
系统接口返回 PixelMap 后,应用才创建独立输出路径。编码失败时先关闭文件句柄,再删除未完成的目标文件;分析器、输入输出 PixelMap、ImageSource 和 ImagePacker 全部在 finally 中释放。
let targetPath = '';
try {
imageSource = image.createImageSource(readFile(sourcePath));
sourcePixelMap = await decodeForSuperResolution(imageSource, 1600);
analyzer = await imageSuperResolution.ImageSRAnalyzer.create();
outputPixelMap = (await analyzer.process({
inputData: { pixelMap: sourcePixelMap }
})).pixelMap;
targetPath = createIndependentTargetPath();
targetFile = fs.openSync(
targetPath,
fs.OpenMode.CREATE | fs.OpenMode.WRITE_ONLY | fs.OpenMode.TRUNC
);
packer = image.createImagePacker();
await packer.packToFile(outputPixelMap, targetFile.fd, {
format: 'image/jpeg',
quality: 94
});
return targetPath;
} catch (error) {
closeFileQuietly(targetFile);
deletePartialTargetQuietly(targetPath);
throw error;
} finally {
closeFileQuietly(targetFile);
await releaseQuietly(packer);
await destroyQuietly(analyzer);
await releaseQuietly(outputPixelMap);
await releaseQuietly(sourcePixelMap);
await releaseQuietly(imageSource);
}
相册记录在文件成功返回后创建。这样可以避免“页面已经出现新照片,磁盘上却只有空文件”的不一致状态。
同一区域比较:像素增加后画面发生了什么
尺寸链路页同时展示源文件尺寸、模型输入约束和最终输出:

图 5:真机页面记录原始文件、模型输入和最终输出三组尺寸。
画质比较使用相同的中心区域和相同的 3.2 倍显示比例:

图 6:左侧为原始照片,右侧为超分输出,两侧使用相同取样中心和显示倍率。
本次结果中,建筑檐口、栏杆和明暗边缘更突出;山脊和树林的细碎纹理更平整,局部带有人工增强感。最终文件经过 JPEG quality 94 编码,图 6 展示的是“系统超分 + JPEG 编码”的组合效果。
这组素材没有计算 PSNR 或 SSIM。两项指标需要可信的高分辨率真值,而本次模型输入由原图降采样得到,输出尺寸也与原图不同。直接把 4439×2959 原图插值到 6400×4264 再比较,会把插值和对齐误差混入指标。
什么照片值得做一次超分
本次链路把 4439×2959 的 JPEG 解码为 1600×1066,再由 ImageSRAnalyzer 生成 6400×4264 的输出。像素数量明显增加,同区域比较也能看到建筑边缘变得突出;与此同时,树林和山脊的细碎纹理出现了平整化。超分改变了画面的表现,但不会把降采样过程中丢失的信息重新变成真实记录。
裁切后的照片、聊天软件压缩图、旧照片预览以及大屏展示前的临时增强,更容易获得可见收益。原图已经足够大、最终只在手机上查看时,生成一份百兆像素缓冲和新的 JPEG 副本未必划算。产品可以根据原图尺寸和展示终端决定是否推荐“清晰修复”,把选择权留给用户。
落地时建议坚持三条规则:限制模型输入,避免大图推高内存峰值;从 response.pixelMap 读取真实输出尺寸,不预设固定倍率;使用独立路径保存结果,编码失败时删除半成品并保留原图。这样既能使用系统超分带来的视觉增强,也能让用户随时比较和撤销。
证件、医疗、取证和测量场景要求像素忠实反映原始信息,超分生成的纹理不应作为事实依据。这类图片可以放大查看原图,不应使用“清晰修复”结果替代原始材料。
更多推荐


所有评论(0)