You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中startImageStream返回CameraImage的planes.height为null的问题

解决CameraImage中Plane height为null的问题

问题根源

在camera:^0.10.0版本中,部分设备或特定分辨率预设下,startImageStream返回的CameraImage对象的Plane属性(height/width)可能为null。这是因为底层相机框架未直接传递这些值,或返回的图像格式与预期结构不符。

解决方案

1. 规范相机初始化与流启动逻辑

不要用setState包裹startImageStream调用,相机完全初始化后直接启动流即可,避免UI重建导致的状态混乱,同时指定标准图像格式保证Plane结构稳定:

initCamera() async {
  try {
    cameraController = CameraController(
      cameras[0],
      ResolutionPreset.medium,
      imageFormatGroup: ImageFormatGroup.yuv420, // 强制使用YUV420格式,确保Plane结构可预测
    );
    await cameraController.initialize();
    
    if (!mounted) return;
    
    cameraController.startImageStream((imageFromStream) async {
      if (!isWorking) {
        isWorking = true;
        await preprocessImage(imageFromStream);
        isWorking = false; // 处理完成后重置状态,保证后续帧能被处理
      }
    });
    setState(() {}); // 仅在需要更新UI时调用
  } catch(e) {
    print(e);
  }
}

2. 从相机预览尺寸获取Plane真实尺寸

如果imageFromStream.planes[0].height为null,直接从cameraController.value.previewSize获取宽高——因为相机初始化完成后,预览尺寸是确定存在的:

preprocessImage(CameraImage cameraImage) async {
  final previewSize = cameraController.value.previewSize;
  if (previewSize == null) {
    print("预览尺寸未初始化");
    isWorking = false;
    return null;
  }

  final planes = cameraImage.planes;
  final yPlane = planes[0];
  final uvPlane = planes[1];

  // Y平面尺寸对应完整预览尺寸
  final yHeight = previewSize.height;
  final ySize = yPlane.bytesPerRow * yHeight;
  // UV平面尺寸为预览尺寸的一半(YUV420格式特性)
  final uvHeight = previewSize.height ~/ 2;
  final uvSize = uvPlane.bytesPerRow * uvHeight;

  final bytes = Uint8List(ySize + uvSize);

  // 填充Y平面
  bytes.setRange(0, ySize, yPlane.bytes);

  // 填充UV平面
  final uvOffset = ySize;
  for (var i = 0; i < uvHeight; i++) {
    final srcOffset = i * uvPlane.bytesPerRow;
    final destOffset = uvOffset + i * (previewSize.width ~/ 2) * 2;
    bytes.setRange(destOffset, destOffset + uvPlane.bytesPerRow, uvPlane.bytes, srcOffset);
  }
  return bytes;
}

3. 优化状态管理与异常兜底

  • 确保isWorking在图像处理完成后(无论成功或失败)重置,避免只处理一帧就停止后续流。
  • 在preprocessImage开头添加预览尺寸的null检查,避免意外崩溃。

关键说明

指定imageFormatGroup: ImageFormatGroup.yuv420是核心优化点,它强制相机返回标准YUV420格式,让Plane的结构完全可预测,从根源上减少因设备默认格式差异导致的属性缺失问题。

内容的提问来源于stack exchange,提问作者Parikshit23

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 17:34:57