我正在用 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();
}
}
}
任何形式的帮助将不胜感激。任何教程/链接任何东西!!!