babalae/better-genshin-impact · error · ArgumentException

图像通道数必须为3,当前为{channels}

Error message

图像通道数必须为3,当前为{channels}

What it means

OcrUtils.NormalizeToTensorDnn preprocesses a Mat for the PaddleOCR detection model, which expects a 3-channel BGR image. If src.Channels() != 3 (e.g. a 4-channel BGRA capture, a 1-channel grayscale, or an empty Mat) it throws ArgumentException before splitting, which would otherwise index mean/std arrays incorrectly or crash.

Source

Thrown at BetterGenshinImpact/Core/Recognition/OCR/Engine/OcrUtils.cs:72

    ///     <br />
    ///     标准化:
    ///     Z-Score Normalization
    /// </summary>
    public static Tensor<float> NormalizeToTensorDnn(Mat src,
        float? scale, // scale float32
        float[]? mean, //mean
        float[]? std, //std
        out IMemoryOwner<float> tensorMemoryOwner, bool swapRb = false, bool crop = false, Size size = default)

    {
        scale ??= 0.00392156862745f;
        mean ??= [0.485f, 0.456f, 0.406f];
        std ??= [0.229f, 0.224f, 0.225f];
        using var rt = new ResourcesTracker();
        // 获取图像参数
        var channels = src.Channels();
        if (channels != 3)
            throw new ArgumentException($"图像通道数必须为3,当前为{channels}");
        // var data = rt.T(OcrOperationImpl.NormalizeImageOperation(src, scale, mean, std));
        var stdMat = rt.NewMat();
        Mat[] bgr = [];
        try
        {
            bgr = src.Split();
            for (var i = 0; i < bgr.Length; ++i)
                bgr[i].ConvertTo(bgr[i], MatType.CV_32FC1, 1 / std[i],
                    (0.0 - mean[i]) / std[i] / (float)scale);
            Cv2.Merge(bgr, stdMat);
        }
        finally
        {
            foreach (var channel in bgr) channel.Dispose();
        }

        //stdMat.GetArray<float>(out var data);
        // 使用DNN模块创建blob

View on GitHub (pinned to a7cb36712d)

Solutions

  1. Convert to 3-channel BGR before calling: Cv2.CvtColor(src, src, ColorConversionCodes.BGRA2BGR).
  2. Load images with Cv2.ImRead(path, ImReadModes.Color).
  3. Guard for empty Mat and invalid channels upstream and skip/correct.

Example fix

// before
var tensor = OcrUtils.NormalizeToTensorDnn(srcMat, ...);

// after
if (srcMat.Channels() == 4)
    Cv2.CvtColor(srcMat, srcMat, ColorConversionCodes.BGRA2BGR);
var tensor = OcrUtils.NormalizeToTensorDnn(srcMat, ...);
Defensive patterns

Strategy: validation

Validate before calling

if (srcMat.Channels() == 4)
    Cv2.CvtColor(srcMat, srcMat, ColorConversionCodes.BGRA2BGR);
else if (srcMat.Channels() == 1)
    Cv2.CvtColor(srcMat, srcMat, ColorConversionCodes.GRAY2BGR);
var tensor = OcrUtils.NormalizeToTensorDnn(srcMat, scale, mean, std, out var owner);

Type guard

static bool IsThreeChannel(OpenCvSharp.Mat m) => !m.Empty() && m.Channels() == 3;

Prevention

When it happens

Trigger: Feeding a screenshot Mat with alpha (4 channels); a grayscale Mat; an empty/uninitialized Mat (channels 0); a Mat loaded from a PNG with transparency.

Common situations: Capture pipeline producing BGRA instead of BGR; image loaded via ImRead without IMREAD_COLOR; downscaling/conversion step that changed channel count; ROI extraction returning an empty Mat.

Related errors


AI-assisted analysis of babalae/better-genshin-impact@a7cb36712d (2026-08-13). Data as JSON: /api/errors/910c28b6998c0454. Report an issue: GitHub.