Модель ONNX не возвращает прогнозы на C#C#

Место общения программистов C#
Ответить
Anonymous
 Модель ONNX не возвращает прогнозы на C#

Сообщение Anonymous »

Я обучил более быструю модель RCNN (fpn V2) pytorch resnet50 на Python и экспортировал ее в формат ONNX. Мне нужно использовать C# для загрузки модели и выполнения прогнозов. Для этого я написал тестовый код.
Размер входного изображения модели составляет 576x720, хотя она была обучена с использованием изображений 720x576. Это не серьезная проблема, потому что я могу легко изменить размер изображений, выполнить прогнозы, а затем изменить их размер обратно. Я не знаю, почему это произошло во время обучения, возможно, это как-то связано с моей проблемой.
Результаты, которые я получаю от C#, не очень хорошие. На моих изображениях вообще не обнаруживаются объекты, тогда как в моем коде Python все работает нормально. Я заметил, что в C# большую часть времени я получаю сообщение об ошибке от ONNX, в котором говорится, что он пытался разделить на ноль, но когда я не получаю этой ошибки, объекты, которые он обнаруживает, являются просто мусором.
-resultsArray {Microsoft.ML.OnnxRuntime.DisposableNamedOnnxValue[3]} Microsoft.ML.OnnxRuntime.DisposableNamedOnnxValue[]
  • Код: Выделить всё

      [0] {Microsoft.ML.OnnxRuntime.DisposableNamedOnnxValue} Microsoft.ML.OnnxRuntime.DisposableNamedOnnxValue
    
  • Код: Выделить всё

      [1] {Microsoft.ML.OnnxRuntime.DisposableNamedOnnxValue} Microsoft.ML.OnnxRuntime.DisposableNamedOnnxValue
    ElementType Int64   Microsoft.ML.OnnxRuntime.Tensors.TensorElementType
    Name    "2546"  string
    
  • Код: Выделить всё

      Value   {"Attempted to divide by zero."}    object {Microsoft.ML.OnnxRuntime.Tensors.DenseTensor}
    ValueType   ONNX_TYPE_TENSOR    Microsoft.ML.OnnxRuntime.OnnxValueType
    _disposed   false   bool
    _mapHelper  null    Microsoft.ML.OnnxRuntime.MapHelper
    _name   "2546"  string
    
  • Код: Выделить всё

      _ortValueHolder {Microsoft.ML.OnnxRuntime.OrtValueTensor} Microsoft.ML.OnnxRuntime.IOrtValueOwner {Microsoft.ML.OnnxRuntime.OrtValueTensor}
    
  • Код: Выделить всё

      _value  {"Attempted to divide by zero."}    object {Microsoft.ML.OnnxRuntime.Tensors.DenseTensor}
    
  • Код: Выделить всё

      [2] {Microsoft.ML.OnnxRuntime.DisposableNamedOnnxValue} Microsoft.ML.OnnxRuntime.DisposableNamedOnnxValue
    
Вот код C#, который у меня есть на данный момент. Я считаю, что проблема связана с обработкой изображений, настройкой тензоров и т. д., однако я недостаточно разбираюсь в этом, чтобы быть уверенным.
Модель была обучена без любая явная нормализация и т. д., только необработанное изображение RGB. Несмотря на это, мне удалось достичь среднего показателя IoU проверки, приближающегося к 95 %.

Код: Выделить всё

        private void cmdAnalyse_Click(object sender, EventArgs e)
{
// begin analysis
if (this.txtONNXFile.Text == "")
{
MessageBox.Show("Please select an ONNX file");
return;
}

if (this.originalImage == null)
{
MessageBox.Show("Please select an image");
return;
}

// flip the width and height dimensions.  Images are 720x576, but the model expects 576x720
this.rescaledImage = new Bitmap(originalImage.Height, originalImage.Width);

Graphics graphics = Graphics.FromImage(rescaledImage);
graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
graphics.DrawImage(originalImage, 0, 0, rescaledImage.Width, rescaledImage.Height);

Microsoft.ML.OnnxRuntime.Tensors.Tensor input = new Microsoft.ML.OnnxRuntime.Tensors.DenseTensor(new[] { 1, 3, 720, 576 });

BitmapData bitmapData = rescaledImage.LockBits(new System.Drawing.Rectangle(0, 0, rescaledImage.Width, rescaledImage.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);

int stride = bitmapData.Stride;
IntPtr scan0 = bitmapData.Scan0;

unsafe
{
byte* ptr = (byte*)scan0;
for (int y = 0; y < rescaledImage.Height; y++)
{
for (int x = 0; x < rescaledImage.Width; x++)
{
int offset = y * stride + x * 3;
input[0, 0, y, x] = ptr[offset + 2]; // Red channel
input[0, 1, y, x] = ptr[offset + 1]; // Green channel
input[0, 2, y, x] = ptr[offset];     // Blue channel
}
}
}

rescaledImage.UnlockBits(bitmapData);

var inputs = new List
{
Microsoft.ML.OnnxRuntime.NamedOnnxValue.CreateFromTensor("images", input)
};

// run inference

var session = new Microsoft.ML.OnnxRuntime.InferenceSession(this.txtONNXFile.Text);
Microsoft.ML.OnnxRuntime.IDisposableReadOnlyCollection results = session.Run(inputs);

// process results
var resultsArray = results.ToArray();

float[] boxes = resultsArray[0].AsEnumerable().ToArray();
long[] labels = resultsArray[1].AsEnumerable().ToArray();
float[] confidences = resultsArray[2].AsEnumerable().ToArray();
var predictions = new List
();
var minConfidence = 0.0f;
for (int i = 0; i < boxes.Length; i += 4)
{
var index = i / 4;
if (confidences[index] >= minConfidence)
{
predictions.Add(new Prediction
{
Box = new Box(boxes[i], boxes[i + 1], boxes[i + 2], boxes[i + 3]),
Label = LabelMap.Labels[labels[index]],
Confidence = confidences[index]
});
}
}

System.Drawing.Graphics graph = System.Drawing.Graphics.FromImage(this.rescaledImage);

// Put boxes, labels and confidence on image and save for viewing

foreach (var p in predictions)
{

System.Drawing.Pen pen = new System.Drawing.Pen(System.Drawing.Color.Red, 2);

graph.DrawRectangle(pen, p.Box.Xmin, p.Box.Ymin, p.Box.Xmax - p.Box.Xmin, p.Box.Ymax - p.Box.Ymin);

}

graph.Flush();
graph.Dispose();

// rescale image back
System.Drawing.Bitmap bmpResult = new Bitmap(this.originalImage.Width, this.originalImage.Height);

graphics = Graphics.FromImage(bmpResult);
graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
graphics.DrawImage(rescaledImage, 0, 0, originalImage.Width, originalImage.Height);

graphics.Flush();
graphics.Dispose();

//graph.ScaleTransform(720, 576);
this.pbRibeye.Width = bmpResult.Width;
this.pbRibeye.Height = bmpResult.Height;

this.pbRibeye.Image = bmpResult;

//bmpResult.Dispose();
rescaledImage.Dispose();
}

и работающий код Python:

Код: Выделить всё

ort_session = onnxruntime.InferenceSession(ONNXFile)

# Preprocess the input image

image = Image.open(image_path)  # Load the image using PIL
resized_image = image.resize((576, 720))  # If this is omitted then I receive an error regarding the expected input dimensions

transform = torchvision.transforms.Compose([
torchvision.transforms.ToTensor(),  # Convert PIL image to tensor
])

input_tensor = transform(resized_image)
input_tensor = input_tensor.unsqueeze(0)  # Add a batch dimension

# Run the model
outputs = ort_session.run(None, {'images': input_tensor.numpy()})
Код Python способен выдавать действительный результат, соответствующий результатам, которых я достиг во время проверки.

Подробнее здесь: https://stackoverflow.com/questions/765 ... in-c-sharp
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»