• C# OpenCvSharp Yolov8 Face Landmarks 人脸特征检测


    目录

    介绍

    效果

    模型信息

    项目

    代码

    下载


    介绍

    github地址:https://github.com/derronqi/yolov8-face

    yolov8 face detection with landmark

    效果

    模型信息

    Model Properties
    -------------------------
    description:Ultralytics YOLOv8-lite-t-pose model trained on widerface.yaml
    author:Ultralytics
    kpt_shape:[5, 3]
    task:pose
    license:AGPL-3.0 https://ultralytics.com/license
    version:8.0.85
    stride:32
    batch:1
    imgsz:[640, 640]
    names:{0: 'face'}
    ---------------------------------------------------------------

    Inputs
    -------------------------
    name:images
    tensor:Float[1, 3, 640, 640]
    ---------------------------------------------------------------

    Outputs
    -------------------------
    name:output0
    tensor:Float[1, 80, 80, 80]
    name:884
    tensor:Float[1, 80, 40, 40]
    name:892
    tensor:Float[1, 80, 20, 20]
    ---------------------------------------------------------------

    项目

    代码

    GenerateProposal函数

    public static unsafe void GenerateProposal(int inpHeight, int inpWidth, int reg_max, int num_class, float score_threshold, int feat_h, int feat_w, Mat output, List position_boxes, List confidences, List> landmarks, int imgh, int imgw, float ratioh, float ratiow, int padh, int padw)
    {
        int stride = (int)Math.Ceiling((double)(inpHeight / feat_h));
        int area = feat_h * feat_w;

        float* ptr = (float*)output.DataStart;
        float* ptr_cls = ptr + area * reg_max * 4;
        float* ptr_kp = ptr + area * (reg_max * 4 + num_class);

        for (int i = 0; i < feat_h; i++)
        {
            for (int j = 0; j < feat_w; j++)
            {
                int cls_id = -1;
                float max_conf = -10000;
                int index = i * feat_w + j;
                for (int k = 0; k < num_class; k++)
                {
                    float conf = ptr_cls[k * area + index];
                    if (conf > max_conf)
                    {
                        max_conf = conf;
                        cls_id = k;
                    }
                }
                float box_prob = Common.sigmoid_x(max_conf);
                if (box_prob > score_threshold)
                {
                    float[] pred_ltrb = new float[4];
                    float[] dfl_value = new float[reg_max];
                    float[] dfl_softmax = new float[reg_max];
                    for (int k = 0; k < 4; k++)
                    {
                        for (int n = 0; n < reg_max; n++)
                        {
                            dfl_value[n] = ptr[(k * reg_max + n) * area + index];
                        }
                        Common.softmax_(ref dfl_value, ref dfl_softmax, reg_max);
                        float dis = 0f;
                        for (int n = 0; n < reg_max; n++)
                        {
                            dis += n * dfl_softmax[n];
                        }
                        pred_ltrb[k] = dis * stride;
                    }
                    float cx = (j + 0.5f) * stride;
                    float cy = (i + 0.5f) * stride;
                    float xmin = Math.Max((cx - pred_ltrb[0] - padw) * ratiow, 0f);  ///还原回到原图
                    float ymin = Math.Max((cy - pred_ltrb[1] - padh) * ratioh, 0f);
                    float xmax = Math.Min((cx + pred_ltrb[2] - padw) * ratiow, (float)(imgw - 1));
                    float ymax = Math.Min((cy + pred_ltrb[3] - padh) * ratioh, (float)(imgh - 1));

                    Rect box = new Rect((int)xmin, (int)ymin, (int)(xmax - xmin), (int)(ymax - ymin));

                    position_boxes.Add(box);
                    confidences.Add(box_prob);

                    List kpts = new List();

                    for (int k = 0; k < 5; k++)
                    {
                        float x = ((ptr_kp[(k * 3) * area + index] * 2 + j) * stride - padw) * ratiow;  ///还原回到原图
                        float y = ((ptr_kp[(k * 3 + 1) * area + index] * 2 + i) * stride - padh) * ratioh;
                        kpts.Add(new OpenCvSharp.Point((int)x, (int)y));
                    }
                    landmarks.Add(kpts);
                }
            }
        }
    }

    1. using OpenCvSharp;
    2. using OpenCvSharp.Dnn;
    3. using System;
    4. using System.Collections.Generic;
    5. using System.Drawing;
    6. using System.Linq;
    7. using System.Text;
    8. using System.Windows.Forms;
    9. namespace OpenCvSharp_Yolov8_Demo
    10. {
    11. public partial class frmMain : Form
    12. {
    13. public frmMain()
    14. {
    15. InitializeComponent();
    16. }
    17. string fileFilter = "*.*|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png";
    18. string image_path = "";
    19. string startupPath;
    20. DateTime dt1 = DateTime.Now;
    21. DateTime dt2 = DateTime.Now;
    22. string model_path;
    23. Mat image;
    24. Mat result_image;
    25. Net opencv_net;
    26. Mat BN_image;
    27. StringBuilder sb = new StringBuilder();
    28. int reg_max = 16;
    29. int num_class = 1;
    30. int inpWidth = 640;
    31. int inpHeight = 640;
    32. float score_threshold = 0.25f;
    33. float nms_threshold = 0.5f;
    34. private void Form1_Load(object sender, EventArgs e)
    35. {
    36. startupPath = System.Windows.Forms.Application.StartupPath;
    37. model_path = startupPath + "\\yolov8-lite-t.onnx";
    38. //初始化网络类,读取本地模型
    39. opencv_net = CvDnn.ReadNetFromOnnx(model_path);
    40. }
    41. private void button1_Click(object sender, EventArgs e)
    42. {
    43. OpenFileDialog ofd = new OpenFileDialog();
    44. ofd.Filter = fileFilter;
    45. if (ofd.ShowDialog() != DialogResult.OK) return;
    46. pictureBox1.Image = null;
    47. image_path = ofd.FileName;
    48. pictureBox1.Image = new Bitmap(image_path);
    49. textBox1.Text = "";
    50. image = new Mat(image_path);
    51. pictureBox2.Image = null;
    52. }
    53. private void button2_Click(object sender, EventArgs e)
    54. {
    55. if (image_path == "")
    56. {
    57. return;
    58. }
    59. int newh = 0, neww = 0, padh = 0, padw = 0;
    60. Mat resize_img = Common.ResizeImage(image, inpHeight, inpWidth, ref newh, ref neww, ref padh, ref padw);
    61. float ratioh = (float)image.Rows / newh, ratiow = (float)image.Cols / neww;
    62. //数据归一化处理
    63. BN_image = CvDnn.BlobFromImage(resize_img, 1 / 255.0, new OpenCvSharp.Size(inpWidth, inpHeight), new Scalar(0, 0, 0), true, false);
    64. //配置图片输入数据
    65. opencv_net.SetInput(BN_image);
    66. //模型推理,读取推理结果
    67. Mat[] outs = new Mat[3] { new Mat(), new Mat(), new Mat() };
    68. string[] outBlobNames = opencv_net.GetUnconnectedOutLayersNames().ToArray();
    69. dt1 = DateTime.Now;
    70. opencv_net.Forward(outs, outBlobNames);
    71. dt2 = DateTime.Now;
    72. List<Rect> position_boxes = new List<Rect>();
    73. List<float> confidences = new List<float>();
    74. List<List<OpenCvSharp.Point>> landmarks = new List>();
    75. Common.GenerateProposal(inpHeight, inpWidth, reg_max, num_class, score_threshold, 40, 40, outs[0], position_boxes, confidences, landmarks, image.Rows, image.Cols, ratioh, ratiow, padh, padw);
    76. Common.GenerateProposal(inpHeight, inpWidth, reg_max, num_class, score_threshold, 20, 20, outs[1], position_boxes, confidences, landmarks, image.Rows, image.Cols, ratioh, ratiow, padh, padw);
    77. Common.GenerateProposal(inpHeight, inpWidth, reg_max, num_class, score_threshold, 80, 80, outs[2], position_boxes, confidences, landmarks, image.Rows, image.Cols, ratioh, ratiow, padh, padw);
    78. //NMS非极大值抑制
    79. int[] indexes = new int[position_boxes.Count];
    80. CvDnn.NMSBoxes(position_boxes, confidences, score_threshold, nms_threshold, out indexes);
    81. List<Rect> re_result = new List<Rect>();
    82. List<List<OpenCvSharp.Point>> re_landmarks = new List>();
    83. List<float> re_confidences = new List<float>();
    84. for (int i = 0; i < indexes.Length; i++)
    85. {
    86. int index = indexes[i];
    87. re_result.Add(position_boxes[index]);
    88. re_landmarks.Add(landmarks[index]);
    89. re_confidences.Add(confidences[index]);
    90. }
    91. if (re_result.Count > 0)
    92. {
    93. sb.Clear();
    94. sb.AppendLine("推理耗时:" + (dt2 - dt1).TotalMilliseconds + "ms");
    95. sb.AppendLine("--------------------------");
    96. //将识别结果绘制到图片上
    97. result_image = image.Clone();
    98. for (int i = 0; i < re_result.Count; i++)
    99. {
    100. Cv2.Rectangle(result_image, re_result[i], new Scalar(0, 0, 255), 2, LineTypes.Link8);
    101. Cv2.PutText(result_image, "face-" + re_confidences[i].ToString("0.00"),
    102. new OpenCvSharp.Point(re_result[i].X, re_result[i].Y - 10),
    103. HersheyFonts.HersheySimplex, 1, new Scalar(0, 0, 255), 2);
    104. foreach (var item in re_landmarks[i])
    105. {
    106. Cv2.Circle(result_image, item, 4, new Scalar(0, 255, 0), -1);
    107. }
    108. sb.AppendLine(string.Format("{0}:{1},({2},{3},{4},{5})"
    109. , "face"
    110. , re_confidences[i].ToString("0.00")
    111. , re_result[i].TopLeft.X
    112. , re_result[i].TopLeft.Y
    113. , re_result[i].BottomRight.X
    114. , re_result[i].BottomRight.Y
    115. ));
    116. }
    117. pictureBox2.Image = new Bitmap(result_image.ToMemoryStream());
    118. textBox1.Text = sb.ToString();
    119. }
    120. else
    121. {
    122. textBox1.Text = "无信息";
    123. }
    124. }
    125. }
    126. }

    下载

    exe可执行程序包免费下载

    源码下载

  • 相关阅读:
    ATFX汇市:美国5月PCE数据来袭,EURUSD或迎剧烈波动
    java毕业生设计学习类视频网计算机源码+系统+mysql+调试部署+lw
    Java核心技术卷Ⅰ-第一章Java程序设计概述
    【Redis专题】RedisCluster集群运维与核心原理剖析
    Java:什么是Java框架?
    常见外贸英语缩写词
    如何在 ASP.NET Core 中使用 Quartz.NET
    AD9680配置与数据还原说明
    Codeforces Round 953 (Div. 2) A - C 题解
    Leetcode754. 到达终点数字 --数论+思维
  • 原文地址:https://blog.csdn.net/lw112190/article/details/134077292