bgrMatToSignedFloat32 function

  1. @visibleForTesting
Float32List bgrMatToSignedFloat32(
  1. Mat mat, {
  2. required int totalPixels,
  3. Float32List? buffer,
})

Converts a continuous BGR CV_8UC3 cv.Mat to a [-1, 1]-normalized RGB float tensor using OpenCV SIMD kernels (BGR→RGB swap + scaled float conversion) and a single memcpy into buffer.

Falls back to the scalar Dart loop (bgrBytesToSignedFloat32) for non-CV_8UC3 or non-continuous inputs.

Implementation

@visibleForTesting
Float32List bgrMatToSignedFloat32(
  cv.Mat mat, {
  required int totalPixels,
  Float32List? buffer,
}) {
  // BGRA (4ch) and grayscale (1ch) inputs must be color-converted to 3-channel
  // BGR first: both the SIMD path below and the byte fallback assume 3
  // bytes/pixel, so a non-BGR stride overruns the buffer (BGRA) or under-reads
  // it (grayscale) and corrupts the tensor.
  cv.Mat? owned;
  cv.Mat src = mat;
  if (mat.type == cv.MatType.CV_8UC4) {
    src = owned = cv.cvtColor(mat, cv.COLOR_BGRA2BGR);
  } else if (mat.type == cv.MatType.CV_8UC1) {
    src = owned = cv.cvtColor(mat, cv.COLOR_GRAY2BGR);
  }
  try {
    if (src.type != cv.MatType.CV_8UC3 || !src.isContinuous) {
      return bgrBytesToSignedFloat32(
        bytes: src.data,
        totalPixels: totalPixels,
        buffer: buffer,
      );
    }
    final cv.Mat rgb = cv.cvtColor(src, cv.COLOR_BGR2RGB);
    final cv.Mat f32 = rgb.convertTo(
      cv.MatType.CV_32FC3,
      alpha: 1.0 / 127.5,
      beta: -1.0,
    );
    rgb.dispose();
    final Uint8List raw = f32.data;
    final Float32List view = Float32List.view(
      raw.buffer,
      raw.offsetInBytes,
      totalPixels * 3,
    );
    final Float32List tensor = buffer ?? Float32List(totalPixels * 3);
    tensor.setAll(0, view);
    f32.dispose();
    return tensor;
  } finally {
    owned?.dispose();
  }
}