C# OpenCvSharp Yolov8 Face Landmarks facial feature detection

Table of Contents

introduce

Effect

Model information

project

code

download


Introduction

Github address: https://github.com/derronqi/yolov8-face

yolov8 face detection with landmark

Effect

Model information

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]
————————————————– ————-

project

code

GenerateProposal function

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); ///Restore to the original image
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; ///Restore to original image
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);
}
}
}
}

using OpenCvSharp;
using OpenCvSharp.Dnn;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace OpenCvSharp_Yolov8_Demo
{
    public partial class frmMain : Form
    {
        public frmMain()
        {
            InitializeComponent();
        }

        string fileFilter = "*.*|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png";
        string image_path = "";
        string startupPath;

        DateTime dt1 = DateTime.Now;
        DateTime dt2 = DateTime.Now;
        string model_path;
        Mat image;
        Mat result_image;

        Net opencv_net;
        Mat BN_image;

        StringBuilder sb = new StringBuilder();

        int reg_max = 16;
        int num_class = 1;

        int inpWidth = 640;
        int inpHeight = 640;

        float score_threshold = 0.25f;
        float nms_threshold = 0.5f;

        private void Form1_Load(object sender, EventArgs e)
        {
            startupPath = System.Windows.Forms.Application.StartupPath;
            model_path = startupPath + "\yolov8-lite-t.onnx";
            //Initialize the network class and read the local model
            opencv_net = CvDnn.ReadNetFromOnnx(model_path);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = fileFilter;
            if (ofd.ShowDialog() != DialogResult.OK) return;
            pictureBox1.Image = null;
            image_path = ofd.FileName;
            pictureBox1.Image = new Bitmap(image_path);
            textBox1.Text = "";
            image = new Mat(image_path);
            pictureBox2.Image = null;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (image_path == "")
            {
                return;
            }
            int newh = 0, neww = 0, padh = 0, padw = 0;
            Mat resize_img = Common.ResizeImage(image, inpHeight, inpWidth, ref newh, ref neww, ref padh, ref padw);
            float ratioh = (float)image.Rows / newh, ratiow = (float)image.Cols / neww;

            //Data normalization processing
            BN_image = CvDnn.BlobFromImage(resize_img, 1 / 255.0, new OpenCvSharp.Size(inpWidth, inpHeight), new Scalar(0, 0, 0), true, false);

            //Configure image input data
            opencv_net.SetInput(BN_image);

            //Model inference, read inference results
            Mat[] outs = new Mat[3] { new Mat(), new Mat(), new Mat() };
            string[] outBlobNames = opencv_net.GetUnconnectedOutLayersNames().ToArray();

            dt1 = DateTime.Now;
            opencv_net.Forward(outs, outBlobNames);
            dt2 = DateTime.Now;

            List<Rect> position_boxes = new List<Rect>();
            List<float> confidences = new List<float>();
            List<List<OpenCvSharp.Point>> landmarks = new List<List<OpenCvSharp.Point>>();

            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);
            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);
            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);

            //NMS non-maximum suppression
            int[] indexes = new int[position_boxes.Count];
            CvDnn.NMSBoxes(position_boxes, confidences, score_threshold, nms_threshold, out indexes);

            List<Rect> re_result = new List<Rect>();
            List<List<OpenCvSharp.Point>> re_landmarks = new List<List<OpenCvSharp.Point>>();
            List<float> re_confidences = new List<float>();

            for (int i = 0; i < indexes.Length; i + + )
            {
                int index = indexes[i];
                re_result.Add(position_boxes[index]);
                re_landmarks.Add(landmarks[index]);
                re_confidences.Add(confidences[index]);
            }

            if (re_result.Count > 0)
            {
                sb.Clear();
                sb.AppendLine("Inference time consumption:" + (dt2 - dt1).TotalMilliseconds + "ms");
                sb.AppendLine("--------------------------");

                //Draw the recognition results onto the picture
                result_image = image.Clone();

                for (int i = 0; i < re_result.Count; i + + )
                {
                    Cv2.Rectangle(result_image, re_result[i], new Scalar(0, 0, 255), 2, LineTypes.Link8);

                    Cv2.PutText(result_image, "face-" + re_confidences[i].ToString("0.00"),
                        new OpenCvSharp.Point(re_result[i].X, re_result[i].Y - 10),
                        HersheyFonts.HersheySimplex, 1, new Scalar(0, 0, 255), 2);

                    foreach (var item in re_landmarks[i])
                    {
                        Cv2.Circle(result_image, item, 4, new Scalar(0, 255, 0), -1);
                    }

                    sb.AppendLine(string.Format("{0}:{1},({2},{3},{4},{5})"
                        , "face"
                        , re_confidences[i].ToString("0.00")
                        , re_result[i].TopLeft.X
                        , re_result[i].TopLeft.Y
                        , re_result[i].BottomRight.X
                        , re_result[i].BottomRight.Y
                        ));
                }

                pictureBox2.Image = new Bitmap(result_image.ToMemoryStream());
                textBox1.Text = sb.ToString();

            }
            else
            {
                textBox1.Text = "No information";
            }

        }

    }
}

Download

exe executable package free download

Source code download

The knowledge points of the article match the official knowledge files, and you can further learn related knowledge. OpenCV skill tree Home page Overview 23664 people are learning the system