【HarmonyOS 7新能力|028】Core Vision Kit工程封装:把接入逻辑放进可维护的分层结构

【HarmonyOS 7新能力|028】Core Vision Kit工程封装:把接入逻辑放进可维护的分层结构

端侧视觉 AI 的演示通常只需要"取一张图并显示识别结果",工程实现却必须处理实时帧、方向旋转、坐标换算、页面生命周期、推理背压和隐私留存。任意一环失控,都可能出现框选错位、页面退出后仍计算、内存持续增长等问题。

本文构建"受控取帧---图像归一化---端侧推理---结构化校验---坐标映射---页面渲染---及时释放"的分层链路。文中的类型、接口和阈值均为应用侧教学封装,不代表 HarmonyOS 7 Core Vision Kit 的官方 API 或模型指标;实际能力、输入格式与支持设备必须以当前 SDK 和华为官方文档为准。封面检测数值属于视觉示意,不是实测准确率。

一、先定义视觉任务与失败边界

"识别画面中的东西"过于宽泛。第一版应固定输入来源、任务类型、输出结构和用户动作,例如"在相机预览中识别有限类别,结果只用于本地叠加,不保存原始图像"。

验收目标包括:没有相机权限时不启动;只保留最新待处理帧;旋转后框选位置正确;低置信结果不展示;页面退出后迟到结果丢弃;异常路径释放图像与推理会话;原始帧默认不落盘。

二、业务层只接收稳定结果模型

页面不应直接解析平台原始对象。视觉适配器把结果映射为归一化矩形和有限标签。

ts 复制代码
interface NormalizedRect {
  left: number
  top: number
  right: number
  bottom: number
}

interface VisionDetection {
  id: string
  label: string
  confidence: number
  box: NormalizedRect
  frameId: number
}

归一化坐标统一限定在 0 到 1,页面再按预览区域换算像素。这样推理输入尺寸变化不会渗透到 UI。

三、图像帧必须拥有明确所有权

相机回调提供的帧可能绑定原生缓冲区,其生命周期不一定覆盖异步推理。会话层要明确是立即复制必要数据,还是由平台支持的引用机制延长所有权。

ts 复制代码
interface FrameLease {
  frameId: number
  width: number
  height: number
  rotation: 0 | 90 | 180 | 270
  timestamp: number
  close(): void
}

无论推理成功、失败还是取消,close() 都要执行且可安全重复。不要把帧对象存进全局状态。

四、用会话状态机管理生命周期

页面出现不等于相机已就绪,页面消失也不等于异步任务立即停止。显式状态机能阻止关闭后的新帧进入。

ts 复制代码
type VisionSessionState =
  | 'idle'
  | 'requesting-permission'
  | 'starting'
  | 'running'
  | 'stopping'
  | 'stopped'
  | 'failed'

interface VisionSession {
  id: string
  revision: number
  state: VisionSessionState
  latestFrameId: number
}

启动、权限返回、旋转和停止都增加 revision。异步结果提交前检查会话版本与状态。

五、预处理要记录完整几何变换

推理输入可能经过旋转、裁剪、缩放和补边。若只保存最终尺寸,结果无法准确映射回预览。应把每一步变换参数组织成可逆链路。

ts 复制代码
interface ImageTransform {
  sourceWidth: number
  sourceHeight: number
  rotation: 0 | 90 | 180 | 270
  scale: number
  padX: number
  padY: number
  cropLeft: number
  cropTop: number
}

方向信息应只应用一次,避免相机层和模型层重复旋转。裁剪区域也必须在源图边界内。

六、通过背压保持实时链路稳定

相机帧率高于推理速度时,不能无限排队。实时预览通常采用"最多一个正在处理、最多一个最新待处理帧"的策略,中间旧帧直接释放。

ts 复制代码
class LatestFrameQueue {
  private pending: FrameLease | null = null

  replace(frame: FrameLease): void {
    this.pending?.close()
    this.pending = frame
  }

  take(): FrameLease | null {
    const frame = this.pending
    this.pending = null
    return frame
  }
}

这不是丢失业务数据,而是用新鲜度换取实时性。离线批处理则应采用不同队列和进度策略。

七、平台能力收口在视觉适配器

图像格式转换、Core Vision 能力调用和原始错误解析都属于适配层。上层只依赖窄接口。

ts 复制代码
interface VisionInput {
  frameId: number
  bytes: Uint8Array
  width: number
  height: number
}

interface VisionPort {
  infer(input: VisionInput, signal: AbortSignal): Promise<ReadonlyArray<VisionDetection>>
  close(): Promise<void>
}

测试时可注入假实现,稳定复现空结果、慢结果、越界结果和异常,而不依赖真实模型。

八、所有推理结果都按不可信数据校验

即使推理运行在本地,返回值也可能因模型、输入或适配错误而异常。展示前检查有限数值、置信区间、标签白名单和矩形边界。

ts 复制代码
function validDetection(item: VisionDetection, allowed: ReadonlySet<string>): boolean {
  const b = item.box
  return allowed.has(item.label) && Number.isFinite(item.confidence) &&
    item.confidence >= 0 && item.confidence <= 1 &&
    [b.left, b.top, b.right, b.bottom].every((v) => Number.isFinite(v) && v >= 0 && v <= 1) &&
    b.left < b.right && b.top < b.bottom
}

阈值是产品策略,不应散落在页面组件中。

九、坐标映射必须覆盖裁剪模式

预览常用等比填充,部分图像会超出视口并被裁剪。简单地把归一化坐标乘以视图宽高会产生偏移。需要结合源宽高、旋转、缩放和裁剪量做反变换。

ts 复制代码
interface Viewport {
  width: number
  height: number
  contentScale: number
  offsetX: number
  offsetY: number
}

function toViewX(normalizedX: number, viewport: Viewport): number {
  return normalizedX * viewport.width * viewport.contentScale + viewport.offsetX
}

完整实现还要处理 Y 轴、旋转和镜像。使用四角测试图比肉眼拖框更可靠。

十、迟到结果不能覆盖新画面

实时推理可能乱序完成。页面只接受当前会话、当前 revision 且不早于已展示帧号的结果。

ts 复制代码
function canCommit(session: VisionSession, resultFrameId: number, resultRevision: number): boolean {
  return session.state === 'running' && resultRevision === session.revision &&
    resultFrameId >= session.latestFrameId
}

页面停止或切换镜头后,旧任务即使无法立即取消,也只能完成清理,不能更新 UI 或持久化。

十一、隐私策略默认不留存原始帧

实时识别不等于需要保存图像。默认只在内存中处理帧,推理后立即释放;日志仅记录帧号、耗时、结果数量和错误码,不记录图像、完整识别文本或可识别个人信息。

ts 复制代码
interface VisionMetric {
  sessionId: string
  frameId: number
  elapsedMs: number
  resultCount: number
  outcome: 'ok' | 'empty' | 'cancelled' | 'failed'
}

若业务确实需要保存,必须单独定义用户目的、授权、保存位置、保留期限和删除入口。

十二、用设备故障场景完成验收

测试覆盖:权限拒绝与撤回、空帧、异常方向、前后摄切换、快速进入退出、连续旋转、推理慢于帧率、低内存、结果含 NaN、矩形越界、模型返回空、取消后迟到结果,以及多轮启动停止后的资源基线。

还要分别检查适配填充和裁剪填充下的框选坐标,并确认深浅色模式中覆盖层可读。性能结论只能来自目标设备的可复现实测,不能由示意图或单次调试推断。

端侧视觉 AI 的可靠性来自完整链路,而不只是模型调用。把帧所有权、状态机、背压、几何变换、结果校验、迟到保护和隐私最小化放进分层结构,Core Vision Kit 才能成为可持续演进的应用能力。

相关推荐
Zentceh2 小时前
0.001Lux是什么概念
图像处理·人工智能·科技·计算机视觉·车载系统·无人机·智能硬件
马剑威(威哥爱编程)3 小时前
【共创稿事节】HarmonyOS 7 互动卡片实战:摇一摇触发静态转动态,前景元素出框
华为·harmonyos
贾伟康3 小时前
【HarmonyOS 7新能力|029】3DGS工程封装:把接入逻辑放进可维护的分层结构
harmonyos·arkts·三维重建·3dgs·harmonyos 7
马剑威(威哥爱编程)3 小时前
【共创稿事节】HarmonyOS 7 闪控窗实战:标准悬浮窗、侧边栏暂存与闪控球一键切换
华为·harmonyos
这张生成的图像能检测吗3 小时前
(论文速读)SphereFormer:用径向窗口解决 LiDAR 远距离稀疏点的信息断连
计算机视觉·点云·3d技术·三维感知
贾伟康4 小时前
【HarmonyOS 7新能力|019】平行视界入门实战:从能力边界到最小可运行链路
harmonyos·arkts·arkui·harmonyos 7·平行视界
技术任我行XTing5 小时前
【DFX系列】Flutter 鸿蒙应用外接纹理介绍及问题定位
flutter·harmonyos
三翼鸟数字化技术团队5 小时前
WiFi-DensePose × OpenHarmony 智慧家居融合
harmonyos
HarmonyOS_SDK5 小时前
AI 赋能 Push Kit 场景化消息开发,高效完成鸿蒙应用推送能力接入
harmonyos