人脸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张来自影视剧《地下交通站》截图..
效果如图示: