Несколько дней назад я переключился с tensorflow на fastai для своего проекта С#. Но теперь я столкнулся с проблемой с моей нормализацией. Для обоих я использую конвейер onnx для загрузки модели и данных.
var onnxPipeline = mLContext.Transforms.ResizeImages(resizing: ImageResizingEstimator.ResizingKind.Fill, outputColumnName: inputName,
imageWidth: ImageSettings.imageWidth, imageHeight: ImageSettings.imageHeight,
inputColumnName: nameof(ImageInputData.Image))
.Append(mLContext.Transforms.ExtractPixels(outputColumnName: inputName, interleavePixelColors: true, scaleImage: 1 / 255f))
.Append(mLContext.Transforms.ApplyOnnxModel(outputColumnName: outputName, inputColumnName: inputName, modelFile: onnxModelPath));
var emptyData = mLContext.Data.LoadFromEnumerable(new List<ImageInputData>());
var onnxModel = onnxPipeline.Fit(emptyData);
с
class ImageInputData
{
[ImageType(ImageSettings.imageHeight, ImageSettings.imageWidth)]
public Bitmap Image { get; set; }
public ImageInputData(byte[] image)
{
using (var ms = new MemoryStream(image))
{
Image = new Bitmap(ms);
}
}
public ImageInputData(Bitmap image)
{
Image = image;
}
}
После использования fastai я узнал, что модели получают лучшую точность, если данные нормализованы с определенным средним значением и стандартным отклонением (поскольку я использовал модель resnet34, это должно быть среднее значение {0,485, 0,456, 0,406} stds = {0,229, 0,224, 0,225). } соответственно). Таким образом, значения пикселей (для каждого цвета c.) должны быть преобразованы с этими значениями, чтобы соответствовать тренировочным изображениям. Но как я могу добиться этого на С#? Что я пробовал до сих пор:
int imageSize = 256;
double[] means = new double[] { 0.485, 0.456, 0.406 }; // used in fastai model
double[] stds = new double[] { 0.229, 0.224, 0.225 };
Bitmap bitmapImage = inputBitmap;
Image image = bitmapImage;
Color[] pixels = new Color[imageSize * imageSize];
for (int x = 0; x < bitmapImage.Width; x++)
{
for (int y = 0; y < bitmapImage.Height; y++)
{
Color pixel = bitmapImage.GetPixel(x, y);
pixels[x + y] = pixel;
double red = (pixel.R - (means[0] * 255)) / (stds[0] * 255); // *255 to scale the mean and std values to the Bitmap
double gre = (pixel.G - (means[1] * 255)) / (stds[1] * 255);
double blu = (pixel.B - (means[2] * 255)) / (stds[2] * 255);
Color pixel_n = Color.FromArgb(pixel.A, (int)red, (int)gre, (int)blu);
bitmapImage.SetPixel(x, y, pixel_n);
}
}
Конечно, это не работает, потому что значения цвета не могут быть отрицательными (что я понял позже). Но как я могу добиться этой нормализации между -1 и 1 для моей модели на С# с моделью onnx?
Есть ли другой способ накормить модель или справиться с нормализацией?
Любая помощь будет оценена по достоинству!