HarmonyOS鸿蒙Next中想从摄像头里面拿出yuv图像用于面部点位识别,我看到官网说api23才支持,请问下低于23我只能用jpeg格式转吗?这个也太慢了?

HarmonyOS鸿蒙Next中想从摄像头里面拿出yuv图像用于面部点位识别,我看到官网说api23才支持,请问下低于23我只能用jpeg格式转吗?这个也太慢了? 【问题描述】:想从鸿蒙摄像头里面拿出yuv 图像用于面部点位识别,我看到官网说api23才支持,请问下低于23我只能用jpeg 格式转吗?这个也太慢了?

【问题现象】:想从鸿蒙摄像头里面拿出yuv 图像用于面部点位识别,我看到官网说api23才支持,请问下低于23我只能用jpeg 格式转吗?但hpeg转太慢了,很影响用户体验,api23以下还有其他方案吗?能不能请给的简单的demo 双路预览从ImageReceiver 可直接拿到 YUV byteBuffer

【版本信息】:开发工具版本6.0.1、Api语言版本:22

【复现代码】:未涉及

【尝试解决方案】:未涉及


更多关于HarmonyOS鸿蒙Next中想从摄像头里面拿出yuv图像用于面部点位识别,我看到官网说api23才支持,请问下低于23我只能用jpeg格式转吗?这个也太慢了?的实战教程也可以访问 https://www.itying.com/category-93-b0.html

6 回复

从目前 HarmonyOS NEXT 的能力来看,你的理解基本是对的:

API 23 之前,应用层确实拿不到 Camera 输出的 YUV 原始数据流;API 23 开始才正式开放了 YUV 数据流能力。

API 23 之前的情况

在 API 22 及更早版本中,Camera Framework 对应用开放的主要是:

  • PreviewOutput(预览)
  • PhotoOutput(拍照)
  • VideoOutput(录像)

如果通过:

ImageReceiver

获取图像数据,通常拿到的是:

JPEG

或者编码后的图像格式。

因此很多视觉算法场景会变成:

Camera
↓
JPEG
↓
解码Bitmap/PixelMap
↓
转YUV/RGB
↓
AI推理

这条链路确实比较重。

尤其是:

30fps实时人脸检测
关键点检测
活体检测

场景下性能压力会比较明显。


API 23 为什么新增 YUV

实际上就是为了解决:

CV
AI视觉
AR
OCR
人脸识别

这些场景。

API 23 开始支持:

ImageReceiver

直接输出:

YUV_420_888

开发者可以直接获取:

ArrayBuffer
ByteBuffer

避免:

JPEG编码
JPEG解码

带来的性能损耗。


API 22 有没有其他办法?

目前公开能力里基本没有真正意义上的:

Camera → 原始YUV

方案。

一般能考虑的只有下面几种。

方案1:升级到 API23

这是最推荐的方案。

因为官方已经提供:

YUV数据流

能力。

对于:

人脸关键点
人体关键点
OCR
目标检测

都是最佳方案。


方案2:降低 JPEG 分辨率

如果必须兼容 API22:

例如:

640×480
720P

而不是:

1920×1080
4K

然后:

JPEG
↓
PixelMap
↓
RGB

送入模型。

虽然还是有损耗,但延迟会下降很多。


方案3:降低推理频率

不要:

每帧推理

改为:

30fps预览
5fps推理
10fps推理

很多人脸识别场景其实够用了。


方案4:使用系统视觉服务

如果你的需求只是:

人脸检测
人脸框
关键点

而不是自己训练模型。

可以看看:

Core Vision Kit

或者相关视觉能力。

系统内部本身拿到的是底层图像流,不需要你自己处理 JPEG。

不过能力范围受系统提供的接口限制。


关于双路输出

你提到:

双路预览
Preview + ImageReceiver

这种模式在 API23 以后是支持的。

典型流程:

PreviewOutput
↓
页面显示

ImageReceiver(YUV)
↓
AI推理

但 API22 下没有开放 YUV 输出的话,即使配置双路,通常也拿不到真正的:

YUV ByteBuffer

因此不存在一个官方 Demo 能在 API22 直接通过:

ImageReceiver

拿到:

YUV_420_888

原始数据。


我的建议

如果你的业务核心是:

  • 人脸关键点识别
  • 活体检测
  • 姿态识别
  • AI视觉分析

那么:

API22 + JPEG方案

只能作为兼容方案。

真正想达到流畅体验,建议直接以:

HarmonyOS 6.1
API23

作为目标版本,使用 Camera 新增的 YUV 数据流能力。

因为 JPEG → RGB → 模型 的额外开销,不仅影响性能,还会增加功耗和发热,在实时视觉场景下体验差异会非常明显。

更多关于HarmonyOS鸿蒙Next中想从摄像头里面拿出yuv图像用于面部点位识别,我看到官网说api23才支持,请问下低于23我只能用jpeg格式转吗?这个也太慢了?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


是的,从API version 23开始,相机框架提供YUV格式图片拍照能力。

https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/camera-yuv-shooting

如果目标是实时面部点位识别,不建议把“拍照 JPEG 再转 YUV”作为主方案。JPEG 像把视频流先压成一张照片再拆开,压缩、解码、色彩转换都会吃时间,实时性会明显受影响。

从公开能力看,直接拿相机预览 YUV/原始帧这类能力和 API 版本强相关。如果官方文档标注 API23 才支持对应图像格式或帧回调,那么低于 API23 的公开接口里就不要假设可以稳定拿到同等 YUV 数据。低版本可选路线一般是:1. 降低分辨率和帧率,用 JPEG/PixelMap 转换做兜底;2. 使用系统提供的人脸/视觉能力,避免自己处理原始帧;3. 如果业务必须实时识别,优先把最低支持版本提到 API23,并在运行时做版本判断。

建议代码里按版本分支:API23 走原始帧能力,低版本走降级方案,并提示性能差异。参考来源:Camera Kit 图像输出能力、ImageKit/PixelMap、API 版本差异说明。

如果目标是 API 22,建议先按当前公开能力保守处理:官方 FAQ 里的双路预览方案是 XComponent 预览一路,再用 ImageReceiver 另一路接收图像;但 FAQ 也明确说明当前 ImageReceiver 不支持直接获取 YUV 数据,只能通过 JPEG 数据通道拿到图像数据再处理,这条链路确实会有编码/解码开销。

所以 API 23 以下如果没有设备厂商扩展能力,通常不建议把“每帧 JPEG 转 YUV”作为高帧率人脸点位识别主路径。可以考虑:

  1. 降低送算法的分辨率和帧率,例如预览保持高清,算法只取低分辨率/抽帧数据;
  2. 把 JPEG 解码、缩放、格式转换放到 worker/native 侧,避免阻塞 UI 线程;
  3. 如果算法 SDK 支持 RGB/NV21 以外的输入,尽量减少格式来回转换;
  4. 对 API 23+ 设备走直接 YUV/byteBuffer 能力,API 22 及以下走降级路径。

也就是说,API 22 下并不是你代码写法的问题,而是公开预览数据通道本身受限;如果业务强依赖实时 YUV,建议把 API 23 作为高性能路径的最低版本。

鸿蒙Next中,若API级别低于23,Camera设备默认不提供YUV输出。此时无法直接使用JPEG转换满足实时面部识别性能需求。可尝试通过ImageReader配置ImageFormat.YUV_420_888,部分设备低版本可能通过厂商扩展仍支持;若系统限制严格,则需考虑升级目标设备的API版本或使用支持NV21的旧版Camera API。

HarmonyOS NEXT(API 10+)已经支持通过 ImageReceiver 直接输出 YUV 格式图像,不需要等 API 23,也完全不必走 JPEG 解码。
只需要创建一个 YUV 格式的 ImageReceiver 作为额外的 CaptureOutput,和预览流同时使用,就能实时拿到 YUV ByteBuffer 用于面部点位识别,延迟远低于 JPEG 转换。

import camera from '@ohos.multimedia.camera';
import image from '@ohos.multimedia.image';

// 创建 YUV ImageReceiver
let receiver = image.createImageReceiver(640, 480, image.ImageFormat.YUV_420_888, 8);
receiver.on('imageArrival', () => {
  receiver.readNextImage((err, img) => {
    if (err || !img) return;
    let y = img.getComponent(image.ComponentType.YUV_Y);
    // y.byteBuffer 就是 Y 分量数据,可直接送入识别算法
    img.release();
  });
});

// 将 ImageReceiver 的 Surface 加入 CameraSession
let surfaceId = await receiver.getReceivingSurfaceId();
let yuvOutput = camera.createCaptureOutput(camera.OutputType.IMAGE, { surfaceId });
// 再添加正常的 PreviewOutput 用于画面显示
// 启动会话后即可双路输出

当前 NEXT 版本(API 10–12)对 ImageReceiver 的 YUV 支持已经稳定,不需要在 JPEG 上浪费性能。

回到顶部