title: OpenNI Face Detection in .NET Windows Form Application
body: <p>I am developing a windows form application in C#. I have to add face recognition functionality. For that purpose I am using OpenNI Library. The hardware for video capture is <code>Xtion PRO LIVE</code>.
  I have successfully installed it and I was able to run the sample code. This code continuously recording video and nothing else. I have modified it in such a way that after pressing <code>Capture</code> button, It saves the current picture to hard drive (Its fine!).<br/>
  <b>Now what I want to accomplish is to detect face by facial landmarks so that I can verify a person's image with saved images in database. How can I do this with OpenNI?</b>
  <br/><br/>
  Here is my code:</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.ComponentModel;
  using System.Data;
  using System.Drawing;
  using System.Linq;
  using System.Text;
  using System.Windows.Forms;
  using OpenNI;
  using System.Threading;
  using System.Drawing.Imaging;
  
  
  namespace CameraApp
      {
          public partial class MainWindow : Form
  
      {
      public MainWindow()
      {
      InitializeComponent();
  
      this.context = Context.CreateFromXmlFile(SAMPLE_XML_FILE, out scriptNode);
      this.depth = context.FindExistingNode(NodeType.Depth) as DepthGenerator;
      if (this.depth == null)
      {
      throw new Exception("Viewer must have a depth node!");
      }
  
      this.histogram = new int[this.depth.DeviceMaxDepth];
  
      MapOutputMode mapMode = this.depth.MapOutputMode;
  
      this.bitmap = new Bitmap((int)mapMode.XRes, (int)mapMode.YRes, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
      this.shouldRun = true;
      this.readerThread = new Thread(ReaderThread);
      this.readerThread.Start();
      }
  
      protected override void OnPaint(PaintEventArgs e)
      {
      base.OnPaint(e);
  
      lock (this)
      {
      e.Graphics.DrawImage(this.bitmap,
      this.panelView.Location.X,
      this.panelView.Location.Y,
      this.panelView.Size.Width,
      this.panelView.Size.Height);
      }
      }
  
      protected override void OnPaintBackground(PaintEventArgs pevent)
      {
      //Don't allow the background to paint
      }
  
      protected override void OnClosing(CancelEventArgs e)
      {
      this.shouldRun = false;
      this.readerThread.Join();
      base.OnClosing(e);
      }
  
      protected override void OnKeyPress(KeyPressEventArgs e)
      {
      if (e.KeyChar == 27)
      {
      Close();
      }
      base.OnKeyPress(e);
      }
  
      private unsafe void CalcHist(DepthMetaData depthMD)
      {
      // reset
      for (int i = 0; i &lt; this.histogram.Length; ++i)
      this.histogram[i] = 0;
  
      ushort* pDepth = (ushort*)depthMD.DepthMapPtr.ToPointer();
  
      int points = 0;
      for (int y = 0; y &lt; depthMD.YRes; ++y)
      {
      for (int x = 0; x &lt; depthMD.XRes; ++x, ++pDepth)
      {
      ushort depthVal = *pDepth;
      if (depthVal != 0)
      {
      this.histogram[depthVal]++;
      points++;
      }
      }
      }
  
      for (int i = 1; i &lt; this.histogram.Length; i++)
      {
      this.histogram[i] += this.histogram[i - 1];
      }
  
      if (points &gt; 0)
      {
      for (int i = 1; i &lt; this.histogram.Length; i++)
      {
      this.histogram[i] = (int)(256 * (1.0f - (this.histogram[i] / (float)points)));
      }
      }
      }
  
      private unsafe void ReaderThread()
      {
      DepthMetaData depthMD = new DepthMetaData();
  
      while (this.shouldRun)
      {
      try
      {
      this.context.WaitOneUpdateAll(this.depth);
      }
      catch (Exception)
      {
      }
  
      this.depth.GetMetaData(depthMD);
  
      CalcHist(depthMD);
  
      lock (this)
      {
      Rectangle rect = new Rectangle(0, 0, this.bitmap.Width, this.bitmap.Height);
      BitmapData data = this.bitmap.LockBits(rect, ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
  
      //ushort* pDepth = (ushort*)this.depth.DepthMapPtr.ToPointer();
  
      //// set pixels
      //for (int y = 0; y &lt; depthMD.YRes; ++y)
      //{
      // byte* pDest = (byte*)data.Scan0.ToPointer() + y * data.Stride;
      // for (int x = 0; x &lt; depthMD.XRes; ++x, ++pDepth, pDest += 3)
      // {
      // byte pixel = (byte)this.histogram[*pDepth];
      // pDest[0] = 0;
      // pDest[1] = pixel;
      // pDest[2] = pixel;
      // }
      //}
  
      // This will point to the depth image.
      ushort* pDepth = (ushort*)this.depth.DepthMapPtr.ToPointer();
  
      // This will point to the RGB image.
      RGB24Pixel* pRGB =
      (RGB24Pixel*)this.depth.DepthMapPtr.ToPointer();
  
      // Go over the depth and RGB image and set the bitmaps
      // we're copying to based on our depth &amp; RGB values.
      for (int y = 0; y &lt; depthMD.YRes; ++y)
      {
      // Assuming that the size of each data frame is
      // 640x480.
      // Scan line by line (480 lines), each line
      // consists of 640 pointers.
      byte* pDest_Depth =
      (byte*)data.Scan0.ToPointer() + y *
      data.Stride;
      byte* pDest_Rgb = (byte*)data.Scan0.ToPointer()
      + y * data.Stride;
  
      for (int x = 0; x &lt; depthMD.XRes; ++x,
      ++pDepth, pDest_Depth += 3,
      ++pRGB, pDest_Rgb += 3)
      {
      // Change the color of the bitmap
      // based on depth value.
      byte pixel = (byte)this.histogram[*pDepth];
      pDest_Depth[0] = 0;
      pDest_Depth[1] = pixel;
      pDest_Depth[2] = pixel;
  
      // Get the RGB values to generate
      // a whole RGB image.
      byte red = pRGB-&gt;Red;
      byte green = pRGB-&gt;Green;
      byte blue = pRGB-&gt;Blue;
  
      // Get depth information.
      ushort depthVal = *pDepth;
      }
      }
  
      this.bitmap.UnlockBits(data);
      }
  
      this.Invalidate();
      }
      }
  
      private readonly string SAMPLE_XML_FILE = @"C:/Program Files/Microsoft Visual Studio 10.0/Microsoft Visual Studio 2010 Ultimate - ENU/OpenNI/Data/SamplesConfig.xml";
  
      private Context context;
      private ScriptNode scriptNode;
      private DepthGenerator depth;
      private Thread readerThread;
      private bool shouldRun;
      private Bitmap bitmap;
      private int[] histogram;
  
      private void button1_Click(object sender, EventArgs e)
      {
      this.readerThread.Abort();
      this.bitmap.Save("D:\\Screenshot.jpeg", System.Drawing.Imaging.ImageFormat.Jpeg);
      this.readerThread = new Thread(ReaderThread);
      this.readerThread.Start();
      }
      }
      }
  </code></pre>
  
  <p>Any kind of help will be appreciated. Any tutorial/link anything!!!</p>