ML.Net con modelo ONNX
[ML
]
¡Hola! Hoy vengo a presentaros una POC en la que llevo un tiempo trabajando.
Me picaba la curiosidad jugar un poco con Machine Learning y ver que nos podía ofrecer. Después de leer y situarme un poco sobre el tema, coincidió que Microsoft, había implementado un nuevo Framework de integración para machine learning (ML.Net).
Y la verdad, que es más sencillo de lo que parece.
En esta POC hemos jugado con una aplicación UWP (Universal Windows Platform), la idea era picar e integrar la aplicación con Rasperry Pi 3, en ello estamos, pero el hardware es una pasta…
Lo primero de todo, hay que decir que no he entrenado el modelo. Simplemente en el repositorio de ONNX, tenéis modelos entrenados para hacer vuestros primeros pinitos y posteriormente ya veremos como entrenar un modelo, porque para ello, depende como, se necesita máquina, bastante máquina, aunque he encontrado una alternativa que parece viable CustomVision, sigo pensando que entrenar un modelo al 100% para lo que tu quieras no debería ser con alternativas cómo esta.
Primero definimos la vista XAML con una Grid, control:CameraPreview (Nuget Microsoft.Toolkit.Uwp.UI.Controls; ), un textblock y un canvas (para renderizar el resultado de lo que va detectando):
<Grid Background="BlueViolet">
<controls:CameraPreview x:Name="CameraPreview"
Width="500" Height="300"
HorizontalAlignment="Left"
VerticalAlignment="Top"></controls:CameraPreview>
<Canvas Name="YoloCanvas" Width="500" Height="300"
Grid.Row="0" HorizontalAlignment="Left"
VerticalAlignment="Top"/>
<TextBlock Width="500" Height="300"
HorizontalAlignment="Right"
VerticalAlignment="Top"
x:Name="TextBlockInformation" ></TextBlock>
</Grid>
En la clase MainPage definimos el evento para capturar las imágenes de la cámara:
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
_model = await LearningModelYolo.CreateFromStreamAsync();
_cameraModel = new CameraModel().GetCameraSize(CameraPreview);
await CameraPreview.StartAsync();
CameraPreview.CameraHelper.FrameArrived += CameraHelper_FrameArrived;
}
Y a partir de aquí, ya podemos empezar a procesar los frames de la cámara para su análisis:
private async void CameraHelper_FrameArrived(object sender, Microsoft.Toolkit.Uwp.Helpers.FrameEventArgs e)
{
if (e?.VideoFrame?.SoftwareBitmap == null) return;
_stopwatch = Stopwatch.StartNew();
ImageFeatureValue _image = ImageFeatureValue.CreateFromVideoFrame(e.VideoFrame);
var input = new Yolov2Input
{
image = _image
};
var output = _model.EvaluateAsync(input).GetAwaiter().GetResult();
_stopwatch.Stop();
IReadOnlyList<float> vectorImage = output.grid.GetAsVectorView();
IList<float> imageList = vectorImage.ToList();
_boxes = _parser.ParseOutputs(vectorImage.ToArray());
var maxIndex = imageList.IndexOf(imageList.Max());
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
TextBlockInformation.Text = $"{1000f / _stopwatch.ElapsedMilliseconds,4:f1} fps on Width {_cameraModel.Width} x Height {_cameraModel}";
DrawOverlays(e.VideoFrame);
});
}
Hay que decir que, si instalamos el framework, ML.Net al importar el modelo ONNX, nos genera la clase para poder acceder a él automáticamente.
Por último, lo que más me ha costado ha sido situar el canvas y situarlo más o menos en el punto que reconoce algo en el frame que le pasamos.
De momento, es todo lo que he conseguido. Ahora lo siguiente, es entrenar mi propio modelo para que identifique personas.
Os seguiré contando los avances.
Os dejo el código (Se adminten PR’s)
Un saludo y hasta la próxima.