1

我正在用 C# 开发一个 Windows 窗体应用程序。我必须添加人脸识别功能。为此,我正在使用 OpenNI 库。用于视频捕获的硬件是Xtion PRO LIVE. 我已成功安装它,并且能够运行示例代码。此代码连续录制视频,仅此而已。我已经修改了它,按下Capture按钮后,它将当前图片保存到硬盘驱动器(很好!)。
现在我想要完成的是通过面部标志检测面部,以便我可以使用数据库中保存的图像来验证一个人的图像。如何使用 OpenNI 做到这一点?

这是我的代码:

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 < this.histogram.Length; ++i)
    this.histogram[i] = 0;

    ushort* pDepth = (ushort*)depthMD.DepthMapPtr.ToPointer();

    int points = 0;
    for (int y = 0; y < depthMD.YRes; ++y)
    {
    for (int x = 0; x < depthMD.XRes; ++x, ++pDepth)
    {
    ushort depthVal = *pDepth;
    if (depthVal != 0)
    {
    this.histogram[depthVal]++;
    points++;
    }
    }
    }

    for (int i = 1; i < this.histogram.Length; i++)
    {
    this.histogram[i] += this.histogram[i - 1];
    }

    if (points > 0)
    {
    for (int i = 1; i < 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 < depthMD.YRes; ++y)
    //{
    // byte* pDest = (byte*)data.Scan0.ToPointer() + y * data.Stride;
    // for (int x = 0; x < 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 & RGB values.
    for (int y = 0; y < 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 < 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->Red;
    byte green = pRGB->Green;
    byte blue = pRGB->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();
    }
    }
    }

任何形式的帮助将不胜感激。任何教程/链接任何东西!!!

4

0 回答 0