如何在ML.NET中使用CenterFace?模型期望形状 (10, 3, 32, 32)

问题描述 投票:0回答:1

我尝试在 ML.NET 中使用 CenterFace ONNX,但不断收到各种错误,主要与输入大小有关。

CenterFace 元数据指出它应该有一个

10, 3, 32, 32
的输入,这对于图像检测来说已经没有任何意义 - 为算法提供 10 批(每批 32x32 像素)有什么意义?

这是我的主要代码:

        string modelPath = "centerface.onnx";
        var mlContext = new MLContext();

        string imagePath = "photo1.jpg";

        var img = Image.FromFile(imagePath);
        var DH = (int)(Math.Ceiling((float)img.Height / 32) * 32);
        var DW = (int)(Math.Ceiling((float)img.Width / 32) * 32);

        var inputData = new[] { new ModelInput { ImagePath = imagePath } };
        IDataView imageData = mlContext.Data.LoadFromEnumerable(inputData);

        var pipeline = mlContext.Transforms.LoadImages(outputColumnName: "input.1", imageFolder: "", inputColumnName: nameof(ModelInput.ImagePath))
            .Append(mlContext.Transforms.ResizeImages(outputColumnName: "input.1", imageWidth: DW, imageHeight: DH))
            .Append(mlContext.Transforms.ExtractPixels(outputColumnName: "input.1"))
            .Append(mlContext.Transforms.ApplyOnnxModel(
                outputColumnNames: ["537", "538", "539", "540"],
                inputColumnNames: ["input.1"],
                modelFile: modelPath
            ));

        var model = pipeline.Fit(imageData);
        var predictionEngine = mlContext.Model.CreatePredictionEngine<ModelInput, ModelOutput>(model);
        var prediction = predictionEngine.Predict(new ModelInput { ImagePath = imagePath });

我的 2 个模型类:

    public class ModelInput
    {
        public string ImagePath { get; set; }
    }

    public class ModelOutput
    {
        [ColumnName("537")] 
        public float[] HeatMap { get; set; }

        [ColumnName("538")]
        public float[] Scale { get; set; }

        [ColumnName("539")]
        public float[] Offset { get; set; }

        [ColumnName("540")]
        public float[] Landmarks { get; set; }
    }

但我确实不断收到有关输入大小的错误:

System.ArgumentException:“内存长度 (3686400) 必须与维度的乘积 (30720) 匹配。”

30720 显然是 10x3x32x32。但话又说回来,这有什么意义呢? 我认为我的 ONNX 坏了,但我确实有一个使用 OpenCVSharp 的有效实现:

// Here is computer DW and DH same way as in ML.NET example
CenterFaceParams p = new(image, resizedSize.Width, resizedSize.Height, scoreThreshold, nmsThreshold);
Size size = new(p.DW, p.DH);

using Mat input = new();
Cv2.Resize(image, input, size);

using Mat blobInput = CvDnn.BlobFromImage(input, 1.0, size, new Scalar(0, 0, 0), true, false);
_net.SetInput(blobInput, "input.1");

using (Mat heatMap = new())
using (Mat scale = new())
using (Mat offset = new())
using (Mat landmarks = new())
{
    _net.Forward([heatMap, scale, offset, landmarks], ["537", "538", "539", "540"]);

    CenterFaceDecoder decoder = new(heatMap, scale, offset, landmarks, p);
    return decoder.GetOutput();
}

这个实现给了我所有 4 层,建模后我得到了我想要的值。

c# .net machine-learning neural-network ml.net
1个回答
0
投票

您看到的错误“内存长度 (3686400) 必须与尺寸乘积 (30720) 匹配”是因为您的 ONNX 模型需要输入形状为 (10, 3, 32, 32),这表示一批10 张图像,具有 3 个颜色通道,每个尺寸为 32x32 像素。 以下是在 ML.NET 中使用此形状的步骤:

准备一批 10 张图像:CenterFace 需要一批 10 张图像,因此您需要:

  • 复制您的图像以填充一批 10 个。
  • 使用循环加载一系列图像并将它们添加到批次中。

代码:

var inputData = Enumerable.Repeat(new ModelInput { ImagePath = imagePath }, 10).ToArray();

调整为 32x32 像素:虽然 32x32 对于人脸检测来说可能看起来很小,但该模型很可能使用完全卷积网络结构来处理跨网格的特征。确保每个图像的大小调整为 32x32,如管道中所示:

.Append(mlContext.Transforms.ResizeImages(outputColumnName: "input.1", imageWidth: 32, imageHeight: 32))

使用浮点像素提取:ML.NET 处理像素提取的方式可能与 OpenCV 不同。如果您的模型需要的话,以标准化浮点格式提取像素。

调整管道:确保管道符合模型的要求并提供所有四个预期输出(537、538、539、540)。

© www.soinside.com 2019 - 2024. All rights reserved.