305 lines
10 KiB
C#
305 lines
10 KiB
C#
//------------------------------------------------------------------------------
|
||
// <copyright file="MainWindow.xaml.cs" company="Microsoft">
|
||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
// </copyright>
|
||
//------------------------------------------------------------------------------
|
||
|
||
namespace Microsoft.Samples.AzureKinectBasics
|
||
{
|
||
using System;
|
||
using System.ComponentModel;
|
||
using System.Diagnostics;
|
||
using System.Globalization;
|
||
using System.IO;
|
||
using System.Threading.Tasks;
|
||
using System.Windows;
|
||
using System.Windows.Media;
|
||
using System.Windows.Media.Imaging;
|
||
using Microsoft.Azure.Kinect.Sensor;
|
||
|
||
using Microsoft.Azure.CognitiveServices.Vision.ComputerVision;
|
||
using Microsoft.Azure.CognitiveServices.Vision.ComputerVision.Models;
|
||
|
||
using System.Collections.Generic;
|
||
|
||
/// <summary>
|
||
/// Interaction logic for MainWindow
|
||
/// </summary>
|
||
public partial class MainWindow : Window, INotifyPropertyChanged
|
||
{
|
||
/// <summary>
|
||
/// Azure Kinect sensor
|
||
/// </summary>
|
||
private readonly Device kinect = null;
|
||
|
||
/// <summary>
|
||
/// Azure Kinect transformation engine
|
||
/// </summary>
|
||
private readonly Transformation transform = null;
|
||
|
||
/// <summary>
|
||
/// Bitmap to display
|
||
/// </summary>
|
||
private readonly WriteableBitmap bitmap = null;
|
||
|
||
/// <summary>
|
||
/// Current status text to display
|
||
/// </summary>
|
||
private string statusText = null;
|
||
|
||
/// <summary>
|
||
/// The width in pixels of the color image from the Azure Kinect DK
|
||
/// </summary>
|
||
private readonly int colorWidth = 0;
|
||
|
||
/// <summary>
|
||
/// The height in pixels of the color image from the Azure Kinect DK
|
||
/// </summary>
|
||
private readonly int colorHeight = 0;
|
||
|
||
/// <summary>
|
||
/// Status of the application
|
||
/// </summary>
|
||
private bool running = true;
|
||
|
||
/// <summary>
|
||
/// Subscription key for Cognitive Services
|
||
/// </summary>
|
||
private const string subscriptionKey = "YOUR SUBSCRIPTION KEY HERE";
|
||
|
||
/// <summary>
|
||
/// Connection to Azure Computer Vision Cognitive Service
|
||
/// </summary>
|
||
private ComputerVisionClient computerVision;
|
||
|
||
/// <summary>
|
||
/// Bounding box of the person
|
||
/// </summary>
|
||
BoundingRect boundingBox;
|
||
|
||
/// <summary>
|
||
/// List of features to find in images
|
||
/// </summary>
|
||
private static readonly List<VisualFeatureTypes> features =
|
||
new List<VisualFeatureTypes>()
|
||
{
|
||
VisualFeatureTypes.Categories, VisualFeatureTypes.Description,
|
||
VisualFeatureTypes.Faces, VisualFeatureTypes.ImageType,
|
||
VisualFeatureTypes.Tags, VisualFeatureTypes.Objects
|
||
};
|
||
|
||
/// <summary>
|
||
/// Initializes a new instance of the MainWindow class.
|
||
/// </summary>
|
||
public MainWindow()
|
||
{
|
||
// Open the default device
|
||
this.kinect = Device.Open();
|
||
|
||
// Configure camera modes
|
||
this.kinect.StartCameras(new DeviceConfiguration
|
||
{
|
||
ColorFormat = ImageFormat.ColorBGRA32,
|
||
ColorResolution = ColorResolution.R1080p,
|
||
DepthMode = DepthMode.NFOV_2x2Binned,
|
||
SynchronizedImagesOnly = true
|
||
});
|
||
|
||
// Initialize the transformation engine
|
||
this.transform = this.kinect.GetCalibration().CreateTransformation();
|
||
|
||
this.colorWidth = this.kinect.GetCalibration().ColorCameraCalibration.ResolutionWidth;
|
||
this.colorHeight = this.kinect.GetCalibration().ColorCameraCalibration.ResolutionHeight;
|
||
|
||
// Create the computer vision client
|
||
computerVision = new ComputerVisionClient(
|
||
new ApiKeyServiceClientCredentials(subscriptionKey),
|
||
new System.Net.Http.DelegatingHandler[] { })
|
||
{
|
||
// You must use the same region as you used to get
|
||
// your subscription keys.
|
||
Endpoint = "https://westus.api.cognitive.microsoft.com/"
|
||
};
|
||
|
||
this.bitmap = new WriteableBitmap(colorWidth, colorHeight, 96.0, 96.0, PixelFormats.Bgra32, null);
|
||
|
||
this.DataContext = this;
|
||
|
||
this.InitializeComponent();
|
||
}
|
||
|
||
/// <summary>
|
||
/// INotifyPropertyChangedPropertyChanged event to allow window controls to bind to changeable data
|
||
/// </summary>
|
||
public event PropertyChangedEventHandler PropertyChanged;
|
||
|
||
/// <summary>
|
||
/// Gets the bitmap to display
|
||
/// </summary>
|
||
public ImageSource ImageSource
|
||
{
|
||
get
|
||
{
|
||
return this.bitmap;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the current status text to display
|
||
/// </summary>
|
||
public string StatusText
|
||
{
|
||
get
|
||
{
|
||
return this.statusText;
|
||
}
|
||
|
||
set
|
||
{
|
||
if (this.statusText != value)
|
||
{
|
||
this.statusText = value;
|
||
|
||
if (this.PropertyChanged != null)
|
||
{
|
||
this.PropertyChanged(this, new PropertyChangedEventArgs("StatusText"));
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Execute shutdown tasks
|
||
/// </summary>
|
||
/// <param name="sender">object sending the event</param>
|
||
/// <param name="e">event arguments</param>
|
||
private void MainWindow_Closing(object sender, CancelEventArgs e)
|
||
{
|
||
running = false;
|
||
|
||
if (this.kinect != null)
|
||
{
|
||
this.kinect.Dispose();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handles the user clicking on the screenshot button
|
||
/// </summary>
|
||
/// <param name="sender">object sending the event</param>
|
||
/// <param name="e">event arguments</param>
|
||
private void ScreenshotButton_Click(object sender, RoutedEventArgs e)
|
||
{
|
||
// Create a render target to which we'll render our composite image
|
||
RenderTargetBitmap renderBitmap = new RenderTargetBitmap((int)CompositeImage.ActualWidth, (int)CompositeImage.ActualHeight, 96.0, 96.0, PixelFormats.Pbgra32);
|
||
|
||
DrawingVisual dv = new DrawingVisual();
|
||
using (DrawingContext dc = dv.RenderOpen())
|
||
{
|
||
VisualBrush brush = new VisualBrush(CompositeImage);
|
||
dc.DrawRectangle(brush, null, new System.Windows.Rect(new Point(), new Size(CompositeImage.ActualWidth, CompositeImage.ActualHeight)));
|
||
}
|
||
|
||
renderBitmap.Render(dv);
|
||
|
||
BitmapEncoder encoder = new PngBitmapEncoder();
|
||
encoder.Frames.Add(BitmapFrame.Create(renderBitmap));
|
||
|
||
string time = System.DateTime.Now.ToString("hh'-'mm'-'ss", CultureInfo.CurrentUICulture.DateTimeFormat);
|
||
|
||
string myPhotos = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
|
||
|
||
string path = Path.Combine(myPhotos, "KinectScreenshot-" + time + ".png");
|
||
|
||
// Write the new file to disk
|
||
try
|
||
{
|
||
using (FileStream fs = new FileStream(path, FileMode.Create))
|
||
{
|
||
encoder.Save(fs);
|
||
}
|
||
|
||
this.StatusText = string.Format(Properties.Resources.SavedScreenshotStatusTextFormat, path);
|
||
}
|
||
catch (IOException)
|
||
{
|
||
this.StatusText = string.Format(Properties.Resources.FailedScreenshotStatusTextFormat, path);
|
||
}
|
||
}
|
||
|
||
private Stream StreamFromBitmapSource(BitmapSource bitmap)
|
||
{
|
||
Stream jpeg = new MemoryStream();
|
||
|
||
BitmapEncoder enc = new JpegBitmapEncoder();
|
||
enc.Frames.Add(BitmapFrame.Create(bitmap));
|
||
enc.Save(jpeg);
|
||
jpeg.Position = 0;
|
||
|
||
return jpeg;
|
||
}
|
||
|
||
private async void Window_Loaded(object sender, RoutedEventArgs e)
|
||
{
|
||
int count = 0;
|
||
|
||
while (running)
|
||
{
|
||
using (Image transformedDepth = new Image(ImageFormat.Depth16, colorWidth, colorHeight, colorWidth * sizeof(UInt16)))
|
||
using (Capture capture = await Task.Run(() => { return this.kinect.GetCapture(); }))
|
||
{
|
||
count++;
|
||
|
||
this.transform.DepthImageToColorCamera(capture, transformedDepth);
|
||
|
||
this.bitmap.Lock();
|
||
|
||
var color = capture.Color;
|
||
var region = new Int32Rect(0, 0, color.WidthPixels, color.HeightPixels);
|
||
|
||
unsafe
|
||
{
|
||
using (var pin = color.Memory.Pin())
|
||
{
|
||
this.bitmap.WritePixels(region, (IntPtr)pin.Pointer, (int)color.Size, color.StrideBytes);
|
||
}
|
||
|
||
if (boundingBox != null)
|
||
{
|
||
int y = (boundingBox.Y + boundingBox.H / 2);
|
||
int x = (boundingBox.X + boundingBox.W / 2);
|
||
|
||
this.StatusText = "The person is:" + transformedDepth.GetPixel<ushort>(y, x) + "mm away";
|
||
}
|
||
}
|
||
|
||
this.bitmap.AddDirtyRect(region);
|
||
this.bitmap.Unlock();
|
||
|
||
if (count % 30 == 0)
|
||
{
|
||
var stream = StreamFromBitmapSource(this.bitmap);
|
||
_ = computerVision.AnalyzeImageInStreamAsync(stream, MainWindow.features).ContinueWith((Task<ImageAnalysis> analysis) =>
|
||
{
|
||
try
|
||
{
|
||
foreach (var item in analysis.Result.Objects)
|
||
{
|
||
if (item.ObjectProperty == "person")
|
||
{
|
||
this.boundingBox = item.Rectangle;
|
||
}
|
||
}
|
||
}
|
||
catch (System.Exception ex)
|
||
{
|
||
this.StatusText = ex.ToString();
|
||
}
|
||
}, TaskScheduler.FromCurrentSynchronizationContext());
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|