C# DlibDotNet 人脸识别、人脸68特征点识别、人脸5特征点识别、人脸对齐,三角剖分,人脸特征比对...

先看效果,测试图片来自网络,侵权联系删除。

人脸识别

922e970e50335134ab2fdf7ccf20dae2.png

人脸68特征点识别

36b016b7661937711979e0957cf00805.png

人脸5特征点识别

f5b2bb91ec3ce7b2b4edce30a09cc0dd.png

人脸对齐

8687a6b188614ca8f80a0070b2364164.png

三角剖分

9e05d896aa21af5211285463c76588b3.png

人脸特征比对

5dfc79c8dc4e9a0f07f850f23f420e80.png

项目

VS2022+.net4.8+OpenCvSharp4+DlibDotNet

0f782a22cdaa58895d5cab857b16a33d.png

代码

using DlibDotNet.Extensions;
using DlibDotNet;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using OpenCvSharp;
using System.Drawing.Imaging;
using System.Globalization;
 
namespace DlibDotNet_人脸识别_人脸68特征点识别_人脸5特征点识别
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
        string fileFilter = "*.*|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png";
        string imgPath = "";
        string imgPath2 = "";
        string startupPath = "";
 
 
        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = fileFilter;
            if (ofd.ShowDialog() != DialogResult.OK) return;
 
            pictureBox1.Image = null;
 
            imgPath = ofd.FileName;
            pictureBox1.Image = new Bitmap(imgPath);
 
        }
 
        private void button2_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = fileFilter;
            if (ofd.ShowDialog() != DialogResult.OK) return;
 
            pictureBox2.Image = null;
 
            imgPath2 = ofd.FileName;
            pictureBox2.Image = new Bitmap(imgPath2);
 
        }
 
        private void Form1_Load(object sender, EventArgs e)
        {
            string startupPath = Application.StartupPath;
            Dlib.Encoding = Environment.OSVersion.Platform == PlatformID.Win32NT ? Encoding.GetEncoding(CultureInfo.CurrentCulture.TextInfo.ANSICodePage) : Encoding.UTF8;
 
        }
 
        /// <summary>
        /// 人脸识别
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click(object sender, EventArgs e)
        {
 
            if (imgPath == "")
            {
                return;
            }
 
            using (var faceDetector = Dlib.GetFrontalFaceDetector())
            using (var image = Dlib.LoadImage<RgbPixel>(imgPath))
            {
                var dets = faceDetector.Operator(image);
                foreach (var r in dets)
                    Dlib.DrawRectangle(image, r, new RgbPixel { Green = 255 });
 
                var result = image.ToBitmap();
                this.pictureBox1.Invoke(new Action(() =>
                {
                    this.pictureBox1.Image?.Dispose();
                    this.pictureBox1.Image = result;
                }));
            }
 
        }
 
        /// <summary>
        /// 5特征点识别
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button5_Click(object sender, EventArgs e)
        {
            if (imgPath == "")
            {
                return;
            }
 
            string faceDataPath = "shape_predictor_5_face_landmarks.dat";
 
            Mat mat = new Mat(imgPath);
 
            Bitmap bmp = new Bitmap(imgPath);
            bmp = Get24bppRgb(bmp);
 
            // 图像转换到Dlib的图像类中
            Array2D<RgbPixel> img = DlibDotNet.Extensions.BitmapExtensions.ToArray2D<RgbPixel>(bmp);
            var faceDetector = Dlib.GetFrontalFaceDetector();
            var shapePredictor = ShapePredictor.Deserialize(faceDataPath);
 
            // 检测人脸
            var faces = faceDetector.Operator(img);
 
            if (faces.Count() == 0) { return; }
 
            // 人脸区域中识别脸部特征
            var shape = shapePredictor.Detect(img, faces[0]);
 
            var bradleyPoints = (from i in Enumerable.Range(0, (int)shape.Parts)
                                 let p = shape.GetPart((uint)i)
                                 select new OpenCvSharp.Point(p.X, p.Y)).ToArray();
 
            foreach (var item in bradleyPoints)
            {
                Cv2.Circle(mat, item.X, item.Y, 2, Scalar.Green, 2);
            }
 
            pictureBox1.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat);
        }
 
        // Convert to Format24bppRgb
        private static Bitmap Get24bppRgb(System.Drawing.Image image)
        {
            var bitmap = new Bitmap(image);
            var bitmap24 = new Bitmap(bitmap.Width, bitmap.Height, PixelFormat.Format24bppRgb);
            using (var gr = Graphics.FromImage(bitmap24))
            {
                gr.DrawImage(bitmap, new System.Drawing.Rectangle(0, 0, bitmap24.Width, bitmap24.Height));
            }
            return bitmap24;
        }
 
        /// <summary>
        /// 68特征点识别
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button4_Click(object sender, EventArgs e)
        {
            if (imgPath == "")
            {
                return;
            }
 
            string faceDataPath = "shape_predictor_68_face_landmarks.dat";
 
            Mat mat = new Mat(imgPath);
 
            Bitmap bmp = new Bitmap(imgPath);
            bmp = Get24bppRgb(bmp);
 
            // 图像转换到Dlib的图像类中
            Array2D<RgbPixel> img = DlibDotNet.Extensions.BitmapExtensions.ToArray2D<RgbPixel>(bmp);
            var faceDetector = Dlib.GetFrontalFaceDetector();
            var shapePredictor = ShapePredictor.Deserialize(faceDataPath);
 
            // 检测人脸
            var faces = faceDetector.Operator(img);
 
            if (faces.Count() == 0) { return; }
 
            // 人脸区域中识别脸部特征
            var shape = shapePredictor.Detect(img, faces[0]);
 
            var bradleyPoints = (from i in Enumerable.Range(0, (int)shape.Parts)
                                 let p = shape.GetPart((uint)i)
                                 select new OpenCvSharp.Point(p.X, p.Y)).ToArray();
 
            foreach (var item in bradleyPoints)
            {
                Cv2.Circle(mat, item.X, item.Y, 2, Scalar.Green, 2);
            }
 
            pictureBox1.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat);
        }
 
        /// <summary>
        /// 人脸对齐
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button6_Click(object sender, EventArgs e)
        {
            if (imgPath == "")
            {
                return;
            }
            var path = imgPath;
            string faceDataPath = "shape_predictor_68_face_landmarks.dat";
            using (var faceDetector = Dlib.GetFrontalFaceDetector())
            using (var img = Dlib.LoadImage<RgbPixel>(path))
            {
                Dlib.PyramidUp(img);
                var shapePredictor = ShapePredictor.Deserialize(faceDataPath);
                var dets = faceDetector.Operator(img);
                var shapes = new List<FullObjectDetection>();
                foreach (var rect in dets)
                {
                    var shape = shapePredictor.Detect(img, rect);
                    if (shape.Parts <= 2)
                        continue;
                    shapes.Add(shape);
                }
 
                if (shapes.Any())
                {
                    var lines = Dlib.RenderFaceDetections(shapes);
                    foreach (var line in lines)
                        Dlib.DrawLine(img, line.Point1, line.Point2, new RgbPixel
                        {
                            Green = 255
                        });
 
                    var wb = img.ToBitmap();
                    this.pictureBox1.Image?.Dispose();
                    this.pictureBox1.Image = wb;
                    foreach (var l in lines)
                        l.Dispose();
                    var chipLocations = Dlib.GetFaceChipDetails(shapes);
                    using (var faceChips = Dlib.ExtractImageChips<RgbPixel>(img, chipLocations))
                    using (var tileImage = Dlib.TileImages(faceChips))
                    {
                        // It is NOT necessary to re-convert WriteableBitmap to Matrix.
                        // This sample demonstrate converting managed image class to
                        // dlib class and vice versa.
                        using (var tile = tileImage.ToBitmap())
                        using (var mat = tile.ToMatrix<RgbPixel>())
                        {
                            var tile2 = mat.ToBitmap();
                            this.pictureBox1.Image?.Dispose();
                            this.pictureBox1.Image = tile2;
                        }
                    }
 
                    foreach (var c in chipLocations)
                        c.Dispose();
                }
 
                foreach (var s in shapes)
                    s.Dispose();
            }
        }
 
        /// <summary>
        /// 人脸特征比对
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button7_Click(object sender, EventArgs e)
        {
            textBox1.Text = "";
 
            if (imgPath == "" || imgPath2 == "")
            {
                return;
            }
 
            var detector = Dlib.GetFrontalFaceDetector();
            var sp = ShapePredictor.Deserialize("shape_predictor_5_face_landmarks.dat");
            var net = DlibDotNet.Dnn.LossMetric.Deserialize("dlib_face_recognition_resnet_model_v1.dat");
 
 
            var img1 = Dlib.LoadImageAsMatrix<RgbPixel>(imgPath);
            var img2 = Dlib.LoadImageAsMatrix<RgbPixel>(imgPath2);
 
            var faces = new List<Matrix<RgbPixel>>();
            foreach (var face in detector.Operator(img1))
            {
                var shape = sp.Detect(img1, face);
                var faceChipDetail = Dlib.GetFaceChipDetails(shape, 150, 0.25);
                var faceChip = Dlib.ExtractImageChip<RgbPixel>(img1, faceChipDetail);
                faces.Add(faceChip);
            }
 
            foreach (var face in detector.Operator(img2))
            {
                var shape = sp.Detect(img2, face);
                var faceChipDetail = Dlib.GetFaceChipDetails(shape, 150, 0.25);
                var faceChip = Dlib.ExtractImageChip<RgbPixel>(img2, faceChipDetail);
                faces.Add(faceChip);
            }
 
            if (faces.Count != 2)
            {
                return;
            }
 
            var faceDescriptors = net.Operator(faces);
 
            // Faces are connected in the graph if they are close enough.  Here we check if
            // the distance between two face descriptors is less than 0.6, which is the
            // decision threshold the network was trained to use.  Although you can
            // certainly use any other threshold you find useful.
            var diff = faceDescriptors[1] - faceDescriptors[0];
            float len = Dlib.Length(diff);
 
            String str = "";
            if (len < 0.6)
            {
                str += "图片1和图片2距离:" + len.ToString() + "   是一个人" + "\r\n";
            }
            else
            {
                str += "图片1和图片2距离:" + len.ToString() + "   不是一个人" + "\r\n";
            }
 
            str += "图片1特征值:[" + faceDescriptors[0].ToString() + "]\r\n";
            str += "图片2特征值:[" + faceDescriptors[1].ToString() + "]\r\n";
 
            textBox1.Text = str;
 
        }
 
        /// <summary>
        /// 三角剖分
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button8_Click(object sender, EventArgs e)
        {
 
            if (imgPath == "")
            {
                return;
            }
 
            string faceDataPath = "shape_predictor_68_face_landmarks.dat";
            Mat mat = new Mat(imgPath);
            Bitmap bmp = new Bitmap(imgPath);
            bmp = Get24bppRgb(bmp);
            // 图像转换到Dlib的图像类中
            Array2D<RgbPixel> img = DlibDotNet.Extensions.BitmapExtensions.ToArray2D<RgbPixel>(bmp);
            var faceDetector = Dlib.GetFrontalFaceDetector();
            var shapePredictor = ShapePredictor.Deserialize(faceDataPath);
            // 检测人脸
            var faces = faceDetector.Operator(img);
            if (faces.Count() == 0)
            {
                return;
            }
            // 人脸区域中识别脸部特征
            var shape = shapePredictor.Detect(img, faces[0]);
 
            var bradleyPoints = (from i in Enumerable.Range(0, (int)shape.Parts)
                                 let p = shape.GetPart((uint)i)
                                 select new OpenCvSharp.Point(p.X, p.Y)).ToArray();
 
            pictureBox1.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat);
 
            //凸包提取
            var hull = Cv2.ConvexHullIndices(bradleyPoints);
            var bradleyHull = (from i in hull
                               select bradleyPoints[i]).ToArray();
 
            for (int i = 0; i < bradleyHull.Length - 1; i++)
            {
                Cv2.Line(mat, bradleyHull[i].X, bradleyHull[i].Y, bradleyHull[i + 1].X, bradleyHull[i + 1].Y, Scalar.Red);
            }
            Cv2.Line(mat, bradleyHull[bradleyHull.Length - 1].X, bradleyHull[bradleyHull.Length - 1].Y, bradleyHull[0].X, bradleyHull[0].Y, Scalar.Red);
 
            pictureBox1.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat);
 
            RotatedRect minAreaRect = Cv2.MinAreaRect(bradleyPoints);
            //三角剖分
            Subdiv2D subdiv = new Subdiv2D();
            Rect rect = new Rect(0, 0, pictureBox1.Image.Width, pictureBox1.Image.Height);
            subdiv.InitDelaunay(rect);
 
            // 添加与绘制特征点
            for (int i = 0; i < bradleyPoints.Length; i++)
            {
                subdiv.Insert(new Point2f(bradleyPoints[i].X, bradleyPoints[i].Y));
            }
            // 生成剖分三角形
            Vec6f[] triangleList = subdiv.GetTriangleList();
            OpenCvSharp.Point[] pt = new OpenCvSharp.Point[3];
            // 绘制剖分三角形
            for (int i = 0; i < triangleList.Length; i++)
            {
                Vec6f t = triangleList[i];
                pt[0] = new OpenCvSharp.Point((int)t[0], (int)t[1]);
                pt[1] = new OpenCvSharp.Point((int)t[2], (int)t[3]);
                pt[2] = new OpenCvSharp.Point((int)t[4], (int)t[5]);
 
                Cv2.Line(mat, pt[0], pt[1], Scalar.Green, 1);
                Cv2.Line(mat, pt[1], pt[2], Scalar.Green, 1);
                Cv2.Line(mat, pt[2], pt[1], Scalar.Green, 1);
            }
 
            pictureBox1.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat);
 
        }
    }
}
}

其他

C#版Facefusion:让你的脸与世界融为一体!》中的Demo程序已经在QQ群(758616458)中分享,需要的可以去QQ群文件中下载体验。

134eb4101fb8198f8c8c64a498a447ac.png

8287e900df80a67d4e45b4f6638a33d8.gif

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值