Используя Службу 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);
}