Azure Kineck SDK - Hello world (for dummies)
Dopo qualche giorno di attesa sono arrivati in BitForFun i due Azure Kinect DK che abbiamo ordinato.
Per chi non lo conoscesse, l' Azure Kinect SDK è un kit di sviluppo e include diversi sensori come una telecamera di profondità, una camera RGB, giroscopio, accelerometro, un array di microfoni e altro.
Da tecnico, la prima cosa che ho notato è (per via della giovane uscita) la mancanza di documentazione per chi vuole svilupparci con Visual Studio e C#.
Questo Hello world per l'Azure Kinect ha l'obbiettivo primario di evidenziare quanto sia semplice (economicamente e tecnicamente) eseguire il Body Tracking.
L'obiettivo secondario è mostrare dei cerchi colorati in corrispondenza delle mani e seguirne i movimenti :)
In realtà esiste un wrapper C# ma è scarsamente documentato.
Facendo riferimento alll' SDK in C++ però è semplice venirne a capo anche con C#.
Senza dilungarmi, ecco quanto annunciato nell'introduzione.
Creare una nuova applicazione WPF:
Io l'ho nominata "Azure Kinect Hello World".
Aggiungere i pacchetti NuGet relativi al Kinect:
1) Microsoft.Azure.Kinect.Sensor
2) Microsoft.Azure.Kinect.BodyTracking
3) WriteableBitmapEx
Nota: appena aggiunti i pacchetti, VS2019 darà il seguente errore "Azure Kinect only supports the x86/x64 platform ('AnyCPU' not supported)"
Basta andare in configuration manager e creare una nuova configurazione:
L'hello world avrà le seguenzi sezioni:
- Configurazione (e calibrazione)
- Acquisizione
- Visualizzazione
https://github.com/giemma/AzureKinectDkHelloWorld
Ecco il codice C# al completo:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Task.Run(() => Go());
}
private async Task Go()
{
try
{
using (Device device = Device.Open())
{
device.StartCameras(new DeviceConfiguration
{
CameraFPS = FPS.FPS30,
ColorResolution = ColorResolution.R1080p,
ColorFormat = ImageFormat.ColorBGRA32,
DepthMode = DepthMode.NFOV_2x2Binned,
SynchronizedImagesOnly = true
});
var calibration = device.GetCalibration();
Transformation transformation = calibration.CreateTransformation();
Tracker tracker = Tracker.Create(calibration, new TrackerConfiguration()
{
ProcessingMode = TrackerProcessingMode.Gpu,
SensorOrientation = SensorOrientation.Default
});
while (true)
{
Capture capture1 = device.GetCapture();
tracker.EnqueueCapture(capture1);
var frame = tracker.PopResult(TimeSpan.Zero, throwOnTimeout: false);
i f (frame != null)
{
this.Dispatcher.Invoke(() =>
{
for (uint i = 0; i < frame.NumberOfBodies; i++)
{
var bodyId = frame.GetBodyId(i);
var body = frame.GetBody(i);
var handLeft = body.Skeleton.GetJoint(JointId.HandLeft);
var handRight = body.Skeleton.GetJoint(JointId.HandRight);
var pointLeft = calibration.TransformTo2D(handLeft.Position, CalibrationDeviceType.Depth, CalibrationDeviceType.Color);
var pointRight = calibration.TransformTo2D(handRight.Position, CalibrationDeviceType.Depth, CalibrationDeviceType.Color);
try
{
if (pointLeft.HasValue && pointRight.HasValue)
{
Image1.Source = CreateNewBitmap(capture1.Color,
(int)pointLeft.Value.X, (int)pointLeft.Value.Y,
(int)pointRight.Value.X, (int)pointRight.Value.Y);
}
}
catch { }
}
});
}
}
}
}
catch (Exception ex)
{
}
}
private WriteableBitmap CreateNewBitmap(
Microsoft.Azure.Kinect.Sensor.Image image,
int xLeft, int yLeft,
int xRight, int yRight)
{
WriteableBitmap wb = new WriteableBitmap(
image.WidthPixels + 30,
image.HeightPixels + 30,
96,
96,
PixelFormats.Bgra32, null);
var region = new Int32Rect(0, 0, image.WidthPixels, image.HeightPixels);
unsafe
{
using (var pin = image.Memory.Pin())
{
wb.WritePixels(region, (IntPtr)pin.Pointer, (int)image.Size, image.StrideBytes);
}
}
using (wb.GetBitmapContext())
{
wb.FillEllipse(xLeft, yLeft, xLeft + 40, yLeft + 40, Colors.Red);
wb.FillEllipse(xRight, yRight, xRight + 40, yRight + 40, Colors.Blue);
}
return wb;
}
}
<Image x:Name="Image1" Stretch="UniformToFill" />
Termino con il link al sito di Microsoft: