使用Kinect进行人脸识别

10

最近我一直在尝试使用Kinect和新的开发者工具包(v1.5.1)进行人脸识别。FaceTracking工具的API可以在这里找到: http://msdn.microsoft.com/en-us/library/jj130970.aspx。我试图做的是获取每个人独特的“面部签名”。为此,我引用了Kinect跟踪的这些面部点(http://i.msdn.microsoft.com/dynimg/IC584330.png)。

然后我跟踪了我的脸(还有几个朋友的脸),并使用基本代数计算了点39和点8之间的距离。我还获取了头部当前深度的值。下面是我得到的数据样本:

DISTANCE FROM RIGHT SIDE OF NOSE TO LEFT EYE: 10.1919198899636
CURRENT DEPTH OF HEAD: 1.65177881717682
DISTANCE FROM RIGHT SIDE OF NOSE TO LEFT EYE: 11.0429381713623
CURRENT DEPTH OF HEAD: 1.65189981460571
DISTANCE FROM RIGHT SIDE OF NOSE TO LEFT EYE: 11.0023324541865
CURRENT DEPTH OF HEAD: 1.65261101722717

这些是我获得的一些数值。所以接下来,我使用Excel对它们进行了绘图。我的预期结果是深度和距离之间存在非常线性的趋势。因为随着深度的增加,距离应该变小,反之亦然。对于X先生的数据,趋势相当线性。但对于我的朋友Y先生,这个图则无法说明问题。因此,我得出结论,我不能使用这种方法进行面部识别。我无法获得跟踪如此小距离所需的精度。

我的目标是能够在人们进入房间时识别他们,保存他们的“档案”,并在他们退出后删除它。如果我描述得有点太多,那么抱歉,我只是想解释我迄今为止取得的进展。那么,你们认为我如何实现面部识别?任何想法或帮助将不胜感激。


1
请添加一些代码(甚至包括您使用的代数),以及距离图表。 - Liam McInroy
3个回答

4

如果您使用EnumIndexableCollection<FeaturePoint, PointF>,那么您可以使用FaceTrackFrameGetProjected3DShape()方法来进行操作。使用方法如下:

  private byte[] colorImage;

  private ColorImageFormat colorImageFormat = ColorImageFormat.Undefined;

  private short[] depthImage;

  private DepthImageFormat depthImageFormat = DepthImageFormat.Undefined;

  KinectSensor Kinect = KinectSensor.KinectSensors[0];

  private Skeleton[] skeletonData;

  colorImageFrame = allFramesReadyEventArgs.OpenColorImageFrame();
  depthImageFrame = allFramesReadyEventArgs.OpenDepthImageFrame();
  skeletonFrame = allFramesReadyEventArgs.OpenSkeletonFrame();
  colorImageFrame.CopyPixelDataTo(this.colorImage);
  depthImageFrame.CopyPixelDataTo(this.depthImage);
  skeletonFrame.CopySkeletonDataTo(this.skeletonData);
  skeletonData = new Skeleton[skeletonFrame.SkeletonArrayLength];

  foreach(Skeleton skeletonOfInterest in skeletonData)
  {
       FaceTrackFrame frame = faceTracker.Track(
           colorImageFormat, colorImage, depthImageFormat, depthImage, skeletonOfInterest);
  }

  private EnumIndexableCollection<FeaturePoint, PointF> facePoints = frame.GetProjected3DShape();

然后您可以使用图像中的每个点。我会有一个const double preferedDistance,您可以将当前深度和不同点的x和y乘以它,以找到x和y的首选版本以及用下面的公式计算的深度:

preferredDistance / currentDistance

例如:

        const double preferredDistance = 500.0;//this can be any number you want.

        double currentDistance = //however you are calculating the distance

        double whatToMultiply = preferredDistance / currentDistance;

        double x1 = this.facePoints[39].X;
        double y1 = this.facePoints[39].Y;
        double x2 = this.facePoints[8].X;
        double y2 = this.facePoints[8].Y;

        double result = whatToMultiply * //however you are calculating distance.

然后你可以拥有一个距离搜索结果的 List<>。我建议你还要有一个布尔类型的 List<> ,与距离对应,如果结果匹配则将其设置为 true ,这样你就可以追踪哪些布尔值是 true/false 了。
示例:

        List<double> DistanceFromEyeToNose = new List<double>
        {
            1,
            2,
            3 //etc
        };


        List<bool> IsMatch = new List<bool>
        {
            false,
            false,
            false //etc
        };

然后使用 for 循环进行搜索。
        for (int i = 0; i < DistanceFromEyeToNose.Count; i++)
        {
            if (result == DistanceFromEyeToNose[i]) IsMatch[i] = true;
        } 

希望这能帮到你!

仍在进展中... 我开始怀疑Kinect的面部识别能力。 - Ray
@Ray 记住 Kinect 不是设计用来识别你的脸的,此外你应该得到不止一个距离数值。 - Liam McInroy
@Ray,既然你在聊天中提到你要转向Aforge.NET,如果这对这个问题有帮助,请接受。 - Liam McInroy

0
您附加的图片是指2D模型。 GetProjected3DShape与该图片无关。
使用IFTResult.Get2DShapePoints获取2D面部点。如果您正在使用FaceTrackingBasics-WPF示例,则必须为该方法编写C#包装器。

这是我的Get2DShapePoints包装器 - Ondrej Galbavý

0
我正在为我的硕士学位做一个类似这样的项目,我正在使用马哈拉诺比斯距离来计算距离,这是一种尺度不变的方法。这是公式:d(x,y)=sqrt(Pow((Xi-Yi),2)/Pow(Si,2)) ; i:1-->N,其中Si是样本集中Xi和Yi的标准差。这是维基百科链接:http://en.wikipedia.org/wiki/Mahalanobis_distance

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接