[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】即可获取下载方式

相关推荐
AI莫大猫8 小时前
(6)YOLOv4算法基本原理以及和YOLOv3 的差异
算法·yolo
KeepThinking!10 小时前
YOLO-World:Real-Time Open-Vocabulary Object Detection
人工智能·yolo·目标检测·多模态
前网易架构师-高司机14 小时前
游泳溺水识别数据集,对9984张原始图片进行YOLO,COCO JSON, VOC XML 格式的标注,平均识别率在91.7%以上
yolo·溺水·游泳溺水·游泳安全
发呆小天才O.oᯅ15 小时前
YOLOv8目标检测——详细记录使用OpenCV的DNN模块进行推理部署C++实现
c++·图像处理·人工智能·opencv·yolo·目标检测·dnn
深度学习lover16 小时前
<项目代码>YOLO Visdrone航拍目标识别<目标检测>
python·yolo·目标检测·计算机视觉·visdrone航拍目标识别
深度学习lover1 天前
[项目代码] YOLOv8 遥感航拍飞机和船舶识别 [目标检测]
python·yolo·目标检测·计算机视觉·遥感航拍飞机和船舶识别
学习BigData1 天前
【使用PyQt5和YOLOv11开发电脑屏幕区域的实时分类GUI】——选择检测区域
qt·yolo·分类
红色的山茶花1 天前
YOLOv9-0.1部分代码阅读笔记-dataloaders.py
笔记·深度学习·yolo
千天夜2 天前
YOLO系列正传(三)神经网络的反向传播(back propagation)与公式推导
人工智能·python·深度学习·神经网络·学习·yolo·卷积神经网络
红色的山茶花2 天前
YOLOv9-0.1部分代码阅读笔记-downloads.py
笔记·深度学习·yolo