人脸68特征点定位

人脸68特征点定位

dlib库是C++中包含一些机器学习场景的库。使用C++或Python进行开发可以通过阅读官网 http://dlib.net/ 文档了解使用方法。在C#当然可以用DllImport导入用C++版本的动态链接库,不过有更方便的方法,在Nuget程序包管理中安装DlibDotNet,直接在C#中使用dlib库。

主要的识别流程都是在dlib库函数中执行的,所以我们自己的程序只需要读入数据,将数据传到dlib中,然后输出运算结果即可。C#中在Nuget程序管理包中安装好DlibDotNet之后,先引入命名空间 using DlibDotNet; Dlib的图片是Array2D<DlibDotNet.RgbPixel>格式,使用函数 Dlib.LoadImage<RgbPixel>(filePath);读入图片。接下来就开始检测:

img = Dlib.LoadImage<RgbPixel>(filePath);
var detector = Dlib.GetFrontalFaceDetector();
var sp = ShapePredictor.Deserialize("shape_predictor_68_face_landmarks.dat");
Dlib.PyramidUp(img);
var dets = detector.Operator(img);
shapes = new List<FullObjectDetection>();
foreach (var rect in dets)
{
  shape = sp.Detect(img, rect);

  Console.WriteLine($"number of parts: {shape.Parts}");
  if (shape.Parts > 2)
  {
    shapes.Add(shape);
  }
}

其中"shape_predictor_68_face_landmarks.dat"就是模型文件,可以在dlib官网下载到。这样操作后在名为shapes的列表中就存储着shape,每个shape是一个包含68个特征点的FullObjectDetection对象。

每个FullObjectDetection对象的Parts属性表示了特征点的个数(当前任务当然是68个),对象的GetPart(i)方法可以获得第i个对象的平面坐标。我们将之画在pictureBox1上:

private void drawPoint(ref Graphics gr,string msg,double x,double y)
{
  // gr.DrawString(msg, this.Font, Brushes.White, (float)x+2, (float)y - 4);
  float _w = 3;
  gr.DrawLine(Pens.White, (float)x - _w, (float)y, (float)x + _w, (float)y);

  gr.DrawLine(Pens.White, (float)x , (float)y- _w, (float)x , (float)y+ _w);
}
private void draw68points()
{
  var gr = pictureBox1.CreateGraphics();
  for(int i=0;i<shape.Parts;i++)
  {
    var p = shape.GetPart((uint)i);
    drawPoint(ref gr, (i + 1).ToString(), 
              p.X* pictureBox1.Width * 1.0/ img.Columns, 
              p.Y* pictureBox1.Height * 1.0/img.Rows);
  }
}

数据集(第1和2张)来自 http://www.vision.caltech.edu/Image_Datasets/Caltech_10K_WebFaces/
第3和4张来自影视剧《地下交通站》截图..

效果如图示:

(这张图的判定存在问题,由于此图不是完全正脸,所以右侧外轮廓定位在了错误的位置。)

发表评论

电子邮件地址不会被公开。 必填项已用*标注