如何从具有位图或字节数组的内存中加载图像以在ML.net中进行图像处理

问题描述

我想从位图或byte []中加载图像。大多数样本正在使用文件

我们想对视频流进行预测。我们可以将帧输出为位图或字节数组。

public class MagsData2
{
    public Image ImageData;
}

public class MagsData
{
    public byte[] ImageData;
}   

Image btmap = Bitmap.FromFile("assets/images/img.jpg");
var images = new List<MagsData2>() { new MagsData2() { ImageData = btmap } };
var images = new List<MagsData>() { new MagsData() { ImageData = ImagetoByte(btmap) } };

使用第一个会出现异常:

System.ArgumentOutOfRangeException:'无法确定IDataView 类型和成员图像数据的注册自定义类型(参数 'rawType')'

在线

IDataView imageDataView = mlContext.Data.LoadFromEnumerable(images);

第二个例外:

System.ArgumentOutOfRangeException: 'Schema mismatch for input column 'ImageData': 
expected String,got VarVector<Byte> (Parameter 'inputSchema')'

在线

var model = pipeline.Fit(data);

相关代码

var data = mlContext.Data.LoadFromEnumerable(new List<MagsData>());
            var pipeline = mlContext.Transforms.LoadImages(outputColumnName: "image",imageFolder: "",inputColumnName: nameof(MagsData.ImageData))
                .Append(mlContext.Transforms.ResizeImages(outputColumnName: "image",imageWidth: ImageNetSettings.imageWidth,imageHeight: ImageNetSettings.imageHeight,inputColumnName: "image"))
                .Append(mlContext.Transforms.ExtractPixels(outputColumnName: "image"))
                .Append(mlContext.Transforms.ApplyOnnxModel(modelFile: modelLocation,outputColumnNames: new[] { TinyYoloModelSettings.ModelOutput },inputColumnNames: new[] { TinyYoloModelSettings.ModelInput }));
            var model = pipeline.Fit(data);

解决方法

有一些动人的作品,但我会尽力掩盖它们(并希望我能把它们全部拿走!)。

我假设您使用的是预训练模型?如果您是您,则在加载上下文时不需要传递您的ml上下文任何图像。我知道这有点时髦,但在经过预训练的模型中,将LoadFromEnumeable传递给空列表是可以的。另外请注意,由于处理图像不再是管道的工作,因此您无需将要处理的任何图像的位置传递给管道。

我们希望使用可用于获取我们的预测的预测引擎,而不是在管道中加载图像(请参见https://docs.microsoft.com/en-us/dotnet/api/microsoft.ml.predictionengine-2?view=ml-dotnet)。这是一个泛型,需要输入和输出类型,因此在我们的情况下,我认为您会想要做的。

var PredictionEngine<MagsData,MagsPrediction> predictionEngine;

MagsPrediction是您定义的与模型输出匹配的类。对于TinyYolo2,它看起来像

public class MagsPreidction
    {
        [ColumnName("grid")]
        public float[] PredictedLabels { get; set; }
    }

将所有预测代码放在一起,如下所示。

var emptyData = new List<MagsData2>();
var imageDataView = context.Data.LoadFromEnumerable(emptyData);

var pipeline = context.Transforms.ResizeImages(resizing: ImageResizingEstimator.ResizingKind.Fill,outputColumnName: "image",imageWidth: ImageSettings.imageWidth,imageHeight: ImageSettings.imageHeight,inputColumnName: nameof(MagsData2.Image))
Append(context.Transforms.ExtractPixels(outputColumnName: "image")).Append(context.Transforms.ApplyOnnxModel(modelFile: "LOCATION OF YOUR MODEL",outputColumnName: "grid",inputColumnName: "image"));

var model = pipeline.Fit(data);
var predictionEngine = context.Model.CreatePredictionEngine<MagsInput,MagsPrediction>(model);

var prediction = predictionEngine.Predict(new MagsData2{ Image = YOURIMAGE});

然后,您可以为每张图像反复使用预测引擎,而更多的则遵循其余的Microsoft文档来获取边界框等。

我在ML.Net上找到的最好的资源之一是乔恩·伍德(Jon Wood)的YouTube频道https://www.youtube.com/channel/UCrDke-1ToEZOAPDfrPGNdQw-一些非常棒的东西,我不能推荐他的频道。

,

您需要按照以下方式使用ImageType标志,并使用Bitmap代替Image

public class MagsData2
{
    [ColumnName("image")]
    [ImageType(512,512)]
    public Bitmap ImageData;
}

您需要用调整大小后的图像的实际大小(ImageNetSettings.imageWidth,ImageNetSettings.imageHeight)替换(512,512)。

然后通过以下方式加载图像:

Image btmap = Bitmap.FromFile("assets/images/img.jpg");
var images = new List<MagsData2>() { new MagsData2() { ImageData = new Bitmap(btmap) } };

然后您的管道变为:

var data = mlContext.Data.LoadFromEnumerable(new List<MagsData2>());

var pipeline = mlContext.Transforms.ResizeImages(outputColumnName: "image",imageWidth: ImageNetSettings.imageWidth,imageHeight: ImageNetSettings.imageHeight,inputColumnName: "image")
    .Append(mlContext.Transforms.ExtractPixels(outputColumnName: "image"))
    .Append(mlContext.Transforms.ApplyOnnxModel(modelFile: modelLocation,outputColumnNames: new[] { TinyYoloModelSettings.ModelOutput },inputColumnNames: new[] { TinyYoloModelSettings.ModelInput }));

var model = pipeline.Fit(data);