Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //------------------------------------------------------------------------------
- // <copyright file="MainWindow.xaml.cs" company="Microsoft">
- // Copyright (c) Microsoft Corporation. All rights reserved.
- // </copyright>
- //------------------------------------------------------------------------------
- namespace Microsoft.Samples.Kinect.DepthBasics
- {
- using System;
- using System.ComponentModel;
- using System.Diagnostics;
- using System.Globalization;
- using System.IO;
- using System.Windows;
- using System.Windows.Media;
- using System.Windows.Media.Imaging;
- using Microsoft.Kinect;
- /// <summary>
- /// Interaction logic for MainWindow
- /// </summary>
- public partial class MainWindow : Window, INotifyPropertyChanged
- {
- /// <summary>
- /// Map depth range to byte range
- /// </summary>
- private const int MapDepthToByte = 8000 / 256;
- /// <summary>
- /// Active Kinect sensor
- /// </summary>
- private KinectSensor kinectSensor = null;
- /// <summary>
- /// Reader for depth frames
- /// </summary>
- private DepthFrameReader depthFrameReader = null;
- /// <summary>
- /// Description of the data contained in the depth frame
- /// </summary>
- private FrameDescription depthFrameDescription = null;
- /// <summary>
- /// Bitmap to display
- /// </summary>
- private WriteableBitmap depthBitmap = null;
- /// <summary>
- /// Intermediate storage for frame data converted to color
- /// </summary>
- private byte[] depthPixels = null;
- /// <summary>
- /// Current status text to display
- /// </summary>
- private string statusText = null;
- private ushort[] raw = null;
- private WriteableBitmap rawPNG = null;
- /// <summary>
- /// Initializes a new instance of the MainWindow class.
- /// </summary>
- public MainWindow()
- {
- // get the kinectSensor object
- this.kinectSensor = KinectSensor.GetDefault();
- // open the reader for the depth frames
- this.depthFrameReader = this.kinectSensor.DepthFrameSource.OpenReader();
- // wire handler for frame arrival
- this.depthFrameReader.FrameArrived += this.Reader_FrameArrived;
- // get FrameDescription from DepthFrameSource
- this.depthFrameDescription = this.kinectSensor.DepthFrameSource.FrameDescription;
- // allocate space to put the pixels being received and converted
- this.depthPixels = new byte[this.depthFrameDescription.Width * this.depthFrameDescription.Height];
- this.raw = new ushort[this.depthFrameDescription.Width * this.depthFrameDescription.Height];
- // create the bitmap to display
- this.depthBitmap = new WriteableBitmap(this.depthFrameDescription.Width, this.depthFrameDescription.Height, 96.0, 96.0, PixelFormats.Gray8, null);
- this.rawPNG= new WriteableBitmap( this.depthFrameDescription.Width, this.depthFrameDescription.Height, 96.0, 96.0, PixelFormats.Gray16, null );
- // set IsAvailableChanged event notifier
- this.kinectSensor.IsAvailableChanged += this.Sensor_IsAvailableChanged;
- // open the sensor
- this.kinectSensor.Open();
- // set the status text
- this.StatusText = this.kinectSensor.IsAvailable ? Properties.Resources.RunningStatusText
- : Properties.Resources.NoSensorStatusText;
- // use the window object as the view model in this simple example
- this.DataContext = this;
- // initialize the components (controls) of the window
- 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.depthBitmap;
- }
- }
- /// <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;
- // notify any bound elements that the text has changed
- 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)
- {
- if (this.depthFrameReader != null)
- {
- // DepthFrameReader is IDisposable
- this.depthFrameReader.Dispose();
- this.depthFrameReader = null;
- }
- if (this.kinectSensor != null)
- {
- this.kinectSensor.Close();
- this.kinectSensor = null;
- }
- }
- /// <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)
- {
- if (this.depthBitmap != null)
- {
- // create a png bitmap encoder which knows how to save a .png file
- BitmapEncoder encoder = new PngBitmapEncoder();
- // create frame from the writable bitmap and add to encoder
- // TO SAVE THE DISPLAYED 8-BIT PNG
- //encoder.Frames.Add( BitmapFrame.Create( this.depthBitmap) );
- // TO SAVE THE RAW 16-BIT PNG
- encoder.Frames.Add( BitmapFrame.Create( this.rawPNG ) );
- string time = System.DateTime.UtcNow.ToString("hh'-'mm'-'ss", CultureInfo.CurrentUICulture.DateTimeFormat);
- string myPhotos = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
- string path = Path.Combine(myPhotos, "KinectScreenshot-Depth-" + time + ".png");
- // write the new file to disk
- try
- {
- // FileStream is IDisposable
- using (FileStream fs = new FileStream(path, FileMode.Create))
- {
- encoder.Save(fs);
- }
- this.StatusText = string.Format(CultureInfo.CurrentCulture, Properties.Resources.SavedScreenshotStatusTextFormat, path);
- }
- catch (IOException)
- {
- this.StatusText = string.Format(CultureInfo.CurrentCulture, Properties.Resources.FailedScreenshotStatusTextFormat, path);
- }
- }
- }
- /// <summary>
- /// Handles the depth frame data arriving from the sensor
- /// </summary>
- /// <param name="sender">object sending the event</param>
- /// <param name="e">event arguments</param>
- private void Reader_FrameArrived(object sender, DepthFrameArrivedEventArgs e)
- {
- bool depthFrameProcessed = false;
- using (DepthFrame depthFrame = e.FrameReference.AcquireFrame())
- {
- if (depthFrame != null)
- {
- // the fastest way to process the body index data is to directly access
- // the underlying buffer
- using (Microsoft.Kinect.KinectBuffer depthBuffer = depthFrame.LockImageBuffer())
- {
- // verify data and write the color data to the display bitmap
- if (((this.depthFrameDescription.Width * this.depthFrameDescription.Height) == (depthBuffer.Size / this.depthFrameDescription.BytesPerPixel)) &&
- (this.depthFrameDescription.Width == this.depthBitmap.PixelWidth) && (this.depthFrameDescription.Height == this.depthBitmap.PixelHeight))
- {
- // Note: In order to see the full range of depth (including the less reliable far field depth)
- // we are setting maxDepth to the extreme potential depth threshold
- ushort maxDepth = ushort.MaxValue;
- // If you wish to filter by reliable depth distance, uncomment the following line:
- //// maxDepth = depthFrame.DepthMaxReliableDistance
- this.ProcessDepthFrameData(depthBuffer.UnderlyingBuffer, depthBuffer.Size, depthFrame.DepthMinReliableDistance, maxDepth);
- depthFrameProcessed = true;
- }
- }
- }
- }
- if (depthFrameProcessed)
- {
- this.RenderDepthPixels();
- }
- }
- /// <summary>
- /// Directly accesses the underlying image buffer of the DepthFrame to
- /// create a displayable bitmap.
- /// This function requires the /unsafe compiler option as we make use of direct
- /// access to the native memory pointed to by the depthFrameData pointer.
- /// </summary>
- /// <param name="depthFrameData">Pointer to the DepthFrame image data</param>
- /// <param name="depthFrameDataSize">Size of the DepthFrame image data</param>
- /// <param name="minDepth">The minimum reliable depth value for the frame</param>
- /// <param name="maxDepth">The maximum reliable depth value for the frame</param>
- private unsafe void ProcessDepthFrameData(IntPtr depthFrameData, uint depthFrameDataSize, ushort minDepth, ushort maxDepth)
- {
- // depth frame data is a 16 bit value
- ushort* frameData = (ushort*)depthFrameData;
- // convert depth to a visual representation
- for (int i = 0; i < (int)(depthFrameDataSize / this.depthFrameDescription.BytesPerPixel); ++i)
- {
- // Get the depth for this pixel
- ushort depth = frameData[i];
- // FOR DISPLAYING ON SCREEN:
- // To convert to a byte, we're mapping the depth value to the byte range.
- // Values outside the reliable depth range are mapped to 0 (black).
- this.depthPixels[i] = (byte)(depth >= minDepth && depth <= maxDepth ? (depth / MapDepthToByte) : 0);
- // FOR SAVING RAW PNG 16-BIT DATA
- // Keeping the raw depth values after clipping them to the max depth. The data is converted to ushort which is 16bit data
- raw[i] = (ushort)(depth >= minDepth && depth <= maxDepth ? (depth) : 0);
- }
- }
- /// <summary>
- /// Renders color pixels into the writeableBitmap.
- /// </summary>
- private void RenderDepthPixels()
- {
- // Rendering frame for displaying on the screen, in 8-Bit grayscale format
- depthBitmap.WritePixels(
- new Int32Rect( 0, 0, depthBitmap.PixelWidth, depthBitmap.PixelHeight ),
- depthPixels,
- depthBitmap.PixelWidth,
- 0 );
- // Rendering frame for saving as raw-16-bit PNG file
- rawPNG.WritePixels(
- new Int32Rect( 0, 0, depthBitmap.PixelWidth, depthBitmap.PixelHeight ),
- raw,
- depthBitmap.PixelWidth * 2,
- 0 );
- }
- /// <summary>
- /// Handles the event which the sensor becomes unavailable (E.g. paused, closed, unplugged).
- /// </summary>
- /// <param name="sender">object sending the event</param>
- /// <param name="e">event arguments</param>
- private void Sensor_IsAvailableChanged(object sender, IsAvailableChangedEventArgs e)
- {
- // on failure, set the status text
- this.StatusText = this.kinectSensor.IsAvailable ? Properties.Resources.RunningStatusText
- : Properties.Resources.SensorNotAvailableStatusText;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement