[C#][winform]基于yolov8的8种人脸表情检测系统C#源码+onnx模型+评估指标曲线+精美GUI界面

【重要说明】

该系统以opencvsharp作图像处理,onnxruntime做推理引擎,使用CPU进行推理,适合有显卡或者没有显卡windows x64系统均可,不支持macOS和Linux系统,不支持x86的windows操作系统。由于采用CPU推理,要比GPU慢。为了适合大部分操作系统我们暂时只写了CPU推理源码,GPU推理源码后期根据需要可能会调整,目前只考虑CPU推理,主要是为了照顾现在大部分使用该源码是学生,很多人并没有显卡的电脑情况。

【算法介绍】

基于YOLOv8的人脸表情检测系统是一个结合了先进目标检测算法(YOLOv8)与深度学习技术的项目,旨在实时或离线地识别并分类人脸表情(如快乐、悲伤、愤怒、惊讶、恐惧、厌恶、中立等)。以下是一个简短的介绍,概述了该系统Python源码的核心要点:

该系统直接利用YOLOv8模型进行人脸表情识别。YOLOv8以其高效的速度和准确性著称,非常适合实时应用。

Python源码实现通常包括以下几个关键部分:

  1. 环境配置:安装必要的库,如onnxruntime(用于YOLOv8模型推理)、OpenCV(用于图像处理)等。
  2. 模型加载:加载预训练的YOLOv8人脸表情识别模型。
  3. 图像/视频处理:读取输入图像或视频,进行预处理(如缩放、归一化)。
  4. 人脸检测与表情识别:使用YOLOv8直接输出人脸表情检测结果。
  5. 结果展示:在图像或视频帧上标注检测到的人脸和表情,并显示结果。

这样的系统可以广泛应用于人机交互、情感分析、安全监控等领域。

【效果演示】

【测试环境】

windows10 x64系统

VS2019

netframework4.7.2

opencvsharp4.8.0

onnxruntime1.16.3

【模型可以检测出类别】

anger

content

disgust

fear

happy

neutral

sad

surprise

【相关参考训练数据集】

https://blog.csdn.net/FL1623863129/article/details/128648951

【训练信息】

|-----------------|-------|
| 参数 | 值 |
| 训练集图片数 | 6586 |
| 验证集图片数 | 1873 |
| 训练map | 76.6% |
| 训练精度(Precision) | 64.1% |
| 训练召回率(Recall) | 75.4% |

【部分实现源码】

复制代码
using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
 
namespace FIRC
{
    public partial class Form1 : Form
    {
 
        public bool videoStart = false;//视频停止标志
        string weightsPath = Application.StartupPath + "\\weights";//模型目录
        string labelTxt= Application.StartupPath + "\\weights\\class_names.txt";//类别文件
        Yolov8Manager detetor = new Yolov8Manager();//推理引擎
        public Form1()
        {
            InitializeComponent();
            CheckForIllegalCrossThreadCalls = false;//线程更新控件不报错
        }
        private void LoadWeightsFromDir()
        {
            var di = new DirectoryInfo(weightsPath);
            foreach(var fi in di.GetFiles("*.onnx"))
            {
                comboBox1.Items.Add(fi.Name);
            }
            if(comboBox1.Items.Count>0)
            {
                comboBox1.SelectedIndex = 0;
            }
            else
            {
                tssl_show.Text = "未找到模型,请关闭程序,放入模型到weights文件夹!";
                tsb_pic.Enabled = false;
                tsb_video.Enabled = false;
                tsb_camera.Enabled = false;
            }
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            LoadWeightsFromDir();//从目录加载模型
        }
        public string GetResultString(Result result)
        {
            Dictionary<string, int> resultDict = new Dictionary<string, int>();
            for (int i = 0; i < result.length; i++)
            {
                if(resultDict.ContainsKey( result.classes[i]) )
                {
                    resultDict[result.classes[i]]++;
                }
                else
                {
                    resultDict[result.classes[i]]=1;
                }
            }
 
            var resultStr = "";
            foreach(var item in resultDict)
            {
                resultStr += string.Format("{0}:{1}\n",item.Key,item.Value);
            }
            return resultStr;
        }
        private void tsb_pic_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "*.*|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png";
            if (ofd.ShowDialog() != DialogResult.OK) return;
            tssl_show.Text = "正在检测中...";
            Task.Run(() => {
                var sw = new Stopwatch();
                sw.Start();
                Mat image = Cv2.ImRead(ofd.FileName);
                detetor.Confidence =Convert.ToSingle(numericUpDown1.Value);
                detetor.IOU = Convert.ToSingle(numericUpDown2.Value);
                var results=detetor.Inference(image);
                
                var resultImage = detetor.DrawImage(OpenCvSharp.Extensions.BitmapConverter.ToBitmap(image), results);
    
                sw.Stop();
                pb_show.Image = resultImage;
                tb_res.Text = GetResultString(results);
                tssl_show.Text = "检测已完成!总计耗时"+sw.Elapsed.TotalSeconds+"秒";
            });
           
 
 
        }
 
        public void VideoProcess(string videoPath)
        {
            Task.Run(() => {
 
                detetor.Confidence = Convert.ToSingle(numericUpDown1.Value);
                detetor.IOU = Convert.ToSingle(numericUpDown2.Value);
                VideoCapture capture = new VideoCapture(videoPath);
                if (!capture.IsOpened())
                {
                    tssl_show.Text="视频打开失败!";
                    return;
                }
                Mat frame = new Mat();
                var sw = new Stopwatch();
                int fps = 0;
                while (videoStart)
                {
 
                    capture.Read(frame);
                    if (frame.Empty())
                    {
                        Console.WriteLine("data is empty!");
                        break;
                    }
                    sw.Start();
                    var results = detetor.Inference(frame);
                    var resultImg = detetor.DrawImage(frame,results);
                    sw.Stop();
                    fps = Convert.ToInt32(1 / sw.Elapsed.TotalSeconds);
                    sw.Reset();
                    Cv2.PutText(resultImg, "FPS=" + fps, new OpenCvSharp.Point(30, 30), HersheyFonts.HersheyComplex, 1.0, new Scalar(255, 0, 0), 3);
                    //显示结果
                    pb_show.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(resultImg);
                    tb_res.Text = GetResultString(results);
                    Thread.Sleep(5);
 
 
                }
 
                capture.Release();
 
                pb_show.Image = null;
                tssl_show.Text = "视频已停止!";
                tsb_video.Text = "选择视频";
 
            });
        }
        public void CameraProcess(int cameraIndex=0)
        {
            Task.Run(() => {
 
                detetor.Confidence = Convert.ToSingle(numericUpDown1.Value);
                detetor.IOU = Convert.ToSingle(numericUpDown2.Value);
                VideoCapture capture = new VideoCapture(cameraIndex);
                if (!capture.IsOpened())
                {
                    tssl_show.Text = "摄像头打开失败!";
                    return;
                }
                Mat frame = new Mat();
                var sw = new Stopwatch();
                int fps = 0;
                while (videoStart)
                {
 
                    capture.Read(frame);
                    if (frame.Empty())
                    {
                        Console.WriteLine("data is empty!");
                        break;
                    }
                    sw.Start();
                    var results = detetor.Inference(frame);
                    var resultImg = detetor.DrawImage(frame, results);
                    sw.Stop();
                    fps = Convert.ToInt32(1 / sw.Elapsed.TotalSeconds);
                    sw.Reset();
                    Cv2.PutText(resultImg, "FPS=" + fps, new OpenCvSharp.Point(30, 30), HersheyFonts.HersheyComplex, 1.0, new Scalar(255, 0, 0), 3);
                    //显示结果
                    pb_show.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(resultImg);
                    tb_res.Text = GetResultString(results);
                    Thread.Sleep(5);
 
 
                }
 
                capture.Release();
 
                pb_show.Image = null;
                tssl_show.Text = "摄像头已停止!";
                tsb_camera.Text = "打开摄像头";
 
            });
        }
        private void tsb_video_Click(object sender, EventArgs e)
        {
            if(tsb_video.Text=="选择视频")
            {
                OpenFileDialog ofd = new OpenFileDialog();
                ofd.Filter = "视频文件(*.*)|*.mp4;*.avi";
                if (ofd.ShowDialog() != DialogResult.OK) return;
                videoStart = true;
                VideoProcess(ofd.FileName);
                tsb_video.Text = "停止";
                tssl_show.Text = "视频正在检测中...";
 
            }
            else
            {
                videoStart = false;
               
            }
        }
 
        private void tsb_camera_Click(object sender, EventArgs e)
        {
            if (tsb_camera.Text == "打开摄像头")
            {
                videoStart = true;
                CameraProcess(0);
                tsb_camera.Text = "停止";
                tssl_show.Text = "摄像头正在检测中...";
 
            }
            else
            {
                videoStart = false;
 
            }
        }
 
        private void tsb_exit_Click(object sender, EventArgs e)
        {
            videoStart = false;
            this.Close();
        }
 
        private void trackBar1_Scroll(object sender, EventArgs e)
        {
            numericUpDown1.Value = Convert.ToDecimal(trackBar1.Value / 100.0f);
        }
 
        private void trackBar2_Scroll(object sender, EventArgs e)
        {
            numericUpDown2.Value = Convert.ToDecimal(trackBar2.Value / 100.0f);
        }
 
        private void numericUpDown1_ValueChanged(object sender, EventArgs e)
        {
            trackBar1.Value = (int)(Convert.ToSingle(numericUpDown1.Value) * 100);
        }
 
        private void numericUpDown2_ValueChanged(object sender, EventArgs e)
        {
            trackBar2.Value = (int)(Convert.ToSingle(numericUpDown2.Value) * 100);
        }
 
        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            tssl_show.Text="加载模型:"+comboBox1.Text;
            detetor.LoadWeights(weightsPath+"\\"+comboBox1.Text,labelTxt);
            tssl_show.Text = "模型加载已完成!";
        }
    }
}

【使用步骤】

使用步骤:

(1)首先根据官方框架https://github.com/ultralytics/ultralytics安装教程安装好yolov8环境,并根据官方export命令将自己pt模型转成onnx模型

(2)使用vs2019打开sln项目,选择x64 release并且修改一些必要的参数,比如输入shape等,点击运行即可查看最后效果

特别注意如果运行报错了,请参考我的博文进行重新引用我源码的DLL:[C#]opencvsharp报错System.Memory,Version=4.0.1.2,Culture=neutral,PublicKeyToken=cc7b13fcd2ddd51"版本高于所引_未能加载文件或程序集"system.memory, version=4.0.1.2, culture-CSDN博客

【提供文件】

C#源码

yolov8n.onnx模型(不提供pytorch模型)

训练的map,P,R曲线图(在weights\results.png)

测试图片(在test_img文件夹下面)

【源码下载地址】

关注下方名片并回复【firc7】即可获取下载方式

相关推荐
思绪无限17 小时前
YOLOv5至YOLOv12升级:交通信号灯识别系统的设计与实现(完整代码+界面+数据集项目)
深度学习·yolo·目标检测·交通信号灯识别·yolov12·yolo全家桶
一休哥※19 小时前
YOLOv11改进系列 | 引入CVPR2024 DCMPNet的C3k2_LEGM模块,局部增强全局建模补强C3k2,适合精度优先分割实验
深度学习·yolo·计算机视觉
思绪无限19 小时前
YOLOv5至YOLOv12升级:水下目标检测系统的设计与实现(完整代码+界面+数据集项目)
人工智能·深度学习·yolo·目标检测·水下目标检测·yolov12·yolo全家桶
懷淰メ1 天前
【AI加持】基于PyQt+YOLO+DeepSeek的口罩佩戴检测系统(详细介绍)
yolo·计算机视觉·pyqt·口罩检测·deepseek·ai加持
是梦终空1 天前
计算机毕业设计271—基于python+深度学习+YOLOV7的车牌识别系统(源代码+数据库+3万字论文)
python·深度学习·opencv·yolo·毕业设计·pyqt5·车牌识别系统
思绪无限2 天前
YOLOv5至YOLOv12升级:石头剪刀布手势识别系统的设计与实现(完整代码+界面+数据集项目)
深度学习·yolo·目标检测·yolov12·yolo全家桶·石头剪刀布手势识别系统
思绪无限2 天前
YOLOv5至YOLOv12升级:舰船检测与识别系统的设计与实现(完整代码+界面+数据集项目)
深度学习·yolo·目标检测·yolov12·yolo全家桶·舰船检测与识别
殷忆枫2 天前
AI学习笔记三十六:基于 YOLOv8 与 Qwen3.5 的多模态视频行为分析系统
笔记·学习·yolo
深度学习lover2 天前
<数据集>yolo 葡萄叶片病害识别<目标检测>
人工智能·python·yolo·目标检测·计算机视觉·葡萄叶片病害识别
思绪无限2 天前
YOLOv5至YOLOv12升级:稻田虫害检测系统的设计与实现(完整代码+界面+数据集项目)
深度学习·yolo·目标检测·yolov12·yolo全家桶·稻田虫害检测