Как преобразовать ограничивающие рамки из выходных данных модели для соответствия фактическому размеру входного изображения? - PullRequest
0 голосов
/ 17 марта 2019

Используя Службу Custom Vision, я обучил модель обнаружения объектов и экспортировал ее в ONNX 1.2.

Использование C # У меня проблемы с преобразованием выходных ограничивающих рамок модели обратно, чтобы соответствовать фактическому размеру входного изображения.

Мое преобразование выходных ограничивающих рамок модели всегда становится слишком маленьким и поэтому никогда не соответствует объектам, найденным на входном изображении: - (

Может кто-нибудь объяснить, что я делаю неправильно, и, возможно, как наилучшим образом преобразовать ограничивающие рамки выходных данных модели, чтобы они точно соответствовали размеру каждого входного изображения?

Тестовое изображение, считанное на шаге 1 ниже, имеет ширину 275 и высоту 138

Выходное значение ограничительной рамки из прогноза на тестовом изображении - аргумент aPrediction в шаге 3 ниже - можно увидеть на скриншоте ниже

aPrediction
    BoundingBox
        Height  0.2569904
        Left    0.197679788
        Top     0.3864116
        Width   0.6202485
//step 1: Input image is resized to model spec which is 416 x 416 before prediction is made
using (var stream = new InMemoryRandomAccessStream())
using (var memStream = new InMemoryRandomAccessStream())
{   
    var imageBytes =  await ReadFile(imagePath);
    ImageBuffer = imageBytes;

    await stream.WriteAsync(imageBytes.AsBuffer());
    stream.Seek(0);
    var decoder = await BitmapDecoder.CreateAsync(stream);
    BitmapEncoder encoder = await BitmapEncoder.CreateForTranscodingAsync(memStream, decoder);
    encoder.BitmapTransform.ScaledWidth = 416;
    encoder.BitmapTransform.ScaledHeight = 416;
    await encoder.FlushAsync();
    memStream.Seek(0);
    var decoder2 = await BitmapDecoder.CreateAsync(memStream);
    softwareBitmap = await decoder2.GetSoftwareBitmapAsync(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight);
}
_predictionModels = await _objectDetection.PredictImageAsync(VideoFrame.CreateWithSoftwareBitmap(softwareBitmap));
..
..
// step 2: The width and height of the overlayCanvas is set to match test image size prior to step 1:
//  overlayCanvas.Width = 275 and overlayCanvas.Height = 138
..
..
//step 3:  The predictions bounding boxes are transformed to fit screen and image size as it was prior to step 1 and then rendered as rectangle's
private void DrawBoundingBox(PredictionModel aPrediction, Canvas overlayCanvas)
{
    // process output boxes
    var x = Math.Max(aPrediction.BoundingBox.Left, 0);
    var y = Math.Max(aPrediction.BoundingBox.Top, 0);
    var w = Math.Min(overlayCanvas.Width- x, aPrediction.BoundingBox.Width);
    var h = Math.Min(overlayCanvas.Height - y, aPrediction.BoundingBox.Height);

    // fit to current canvas and image size
    x = (float)overlayCanvas.Width * x / 416;
    y = (float)overlayCanvas.Height * y / 416;
    w = overlayCanvas.Width * w / 416;
    h = overlayCanvas.Height * h / 416;
    var rectStroke = _lineBrushGreen;

    //The too small bounding box size of the object detected in the input image
    var r = new Windows.UI.Xaml.Shapes.Rectangle
    {
        Tag = aPrediction.BoundingBox,
        Width = w,
        Height = h,
        Fill = _fillBrush,
        Stroke = rectStroke,
        StrokeThickness = _lineThickness,
        Margin = new Thickness(x, y, 0, 0)
    };

    //The correct, hardcoded bounding box size of the object detected in the input image
    //var r = new Windows.UI.Xaml.Shapes.Rectangle
    //{
    //    Tag = aPrediction.BoundingBox,
    //    Width = 92,
    //    Height = 24,
    //    Fill = _fillBrush,
    //    Stroke = rectStroke,
    //    StrokeThickness = _lineThickness,
    //    Margin = new Thickness(78, 75, 0, 0)
    //};
    overlayCanvas.Children.Add(r);
}   

...