C# OpenCvSharp DNN 部署L2CS-Net人脸朝向估计

news2025/1/16 2:40:51

效果

项目

代码

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

namespace OpenCvSharp_DNN_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;

        L2CSNet gaze_predictor;

        private void Form1_Load(object sender, EventArgs e)
        {
            startupPath = System.Windows.Forms.Application.StartupPath;
            model_path = startupPath + "\\yolov8n-face.onnx";
            //初始化网络类,读取本地模型
            opencv_net = CvDnn.ReadNetFromOnnx(model_path);

            gaze_predictor = new L2CSNet("l2cs_net_1x3x448x448.onnx");
        }

        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;

            dt1 = DateTime.Now;

            //数据归一化处理
            BN_image = CvDnn.BlobFromImage(resize_img, 1 / 255.0, new OpenCvSharp.Size(inpWidth, inpHeight), new Scalar(0, 0, 0), true, false);

            //配置图片输入数据
            opencv_net.SetInput(BN_image);

            //模型推理,读取推理结果
            Mat[] outs = new Mat[3] { new Mat(), new Mat(), new Mat() };
            string[] outBlobNames = opencv_net.GetUnconnectedOutLayersNames().ToArray();

            opencv_net.Forward(outs, outBlobNames);

            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非极大值抑制
            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]);
            }

            float[] gaze_yaw_pitch = new float[2];
            float length = (float)(image.Cols / 1.5);

            result_image = image.Clone();


            if (re_result.Count > 0)
            {
                sb.Clear();

                for (int i = 0; i < re_result.Count; i++)
                {
                    Mat crop_img = new Mat(result_image, re_result[i]);

                    gaze_predictor.Detect(crop_img, gaze_yaw_pitch);

                    //draw gaze	
                    float pos_x = (float)(re_result[i].X + 0.5 * re_result[i].Width);
                    float pos_y = (float)(re_result[i].Y + 0.5 * re_result[i].Height);

                    float dy = (float)(-length * Math.Sin(gaze_yaw_pitch[0]) * Math.Cos(gaze_yaw_pitch[1]));
                    float dx = (float)(-length * Math.Sin(gaze_yaw_pitch[1]));

                    OpenCvSharp.Point from = new OpenCvSharp.Point((int)pos_x, (int)pos_y);
                    OpenCvSharp.Point to = new OpenCvSharp.Point((int)(pos_x + dx), (int)(pos_y + dy));

                    Cv2.ArrowedLine(result_image, from, to, new Scalar(255, 0, 0), 2, 0, 0, 0.18);

                    Cv2.Rectangle(result_image, re_result[i], new Scalar(0, 0, 255), 2, LineTypes.Link8);
                    //Cv2.Rectangle(result_image, new OpenCvSharp.Point(re_result[i].X, re_result[i].Y), new OpenCvSharp.Point(re_result[i].X + re_result[i].Width, re_result[i].Y+ re_result[i].Height), new Scalar(0, 255, 0), 2);

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

                }

                dt2 = DateTime.Now;

                sb.AppendLine("--------------------------");
                sb.AppendLine("耗时:" + (dt2 - dt1).TotalMilliseconds + "ms");

                pictureBox2.Image = new Bitmap(result_image.ToMemoryStream());
                textBox1.Text = sb.ToString();
            }
            else
            {
                textBox1.Text = "无信息";
            }
        }

    }
}

参考

GitHub - Ahmednull/L2CS-Net: The official PyTorch implementation of L2CS-Net for gaze estimation and tracking

下载

可执行程序exe包0积分下载

源码下载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1149183.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(1)(1.10) JSN-SR04T声纳

文章目录 前言 1 连接到自动驾驶仪 2 参数说明 前言 JSN-SR04T 是一种超声波距离传感器。有两个版本 v2.0 和 v3.0。v2.0 的作用范围为 25 至 450cm&#xff0c;v3.0 的作用范围为 20 至 600cm。也更稳定。由于量程很短&#xff0c;因此使用范围有限。 1 连接到自动驾驶仪 …

TensorFlow学习笔记(未完待续)

文章目录 tf.Graph().as_default()sessiontensorflow.placeholder()tf.summary tf.Graph().as_default() with tf.Graph().as_default():with tf.device(/gpu:str(GPU_INDEX)):TensorFlow中所有计算都会被转化为计算图上的节点。是一个通过计算图的形式来表述计算的编程系统&a…

SAP软件如何查询销售订单的删除记录 <转载>

原文链接&#xff1a;https://mp.weixin.qq.com/s/SFC5enOcH1tizeU8N3JHXQ SAP软件中销售订单如果被删除是不能通过VA02和VA3或VA05查询的‍‍到相关记录的&#xff0c;系统会报错&#xff08;如图&#xff09; 销售订单不像某些凭证&#xff08;比如采购订单&#xff0c;采购…

无线接收芯片CMT2219A/无线发射芯片CMT2119A实现无线遥控开关、插座、门铃无线方案

CMT2219A 是一款超低功耗、高性能、OOK 和 (G)FSK 接收器&#xff0c;适用于各种 300 至 960 MHz 无线应用。 它是 CMOSTEK NextGenRFTM 系列的一部分&#xff0c;该系列包括完整的发射器、接收器和收发器系列。 所有功能均可通过离线 EEPROM 编程或在线寄存器写入进行配置。 …

飞利浦的台灯好用吗?飞利浦、书客、雷士护眼台灯对比测评

虽然台灯是许多家庭都会有的照明设备&#xff0c;但是很多家长并不清楚孩子学习时使用的台灯其实是非常有讲究的。如果孩子长时间使用不适合或者劣质的台灯&#xff0c;会在不知不觉中造成视力的损伤&#xff0c;从而近视。所以一款合适的护眼台灯是真的能够很好的起到护眼效果…

不知道怎么显示长标题?这里有小技巧,让你的内容更简洁明了!

&#x1f3ac; 江城开朗的豌豆&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 &#x1f4dd; 个人网站 :《 江城开朗的豌豆&#x1fadb; 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! ​ 目录 &#x1f4d8; 文章内容 ⭐ 写在最后 ⭐…

嵌入式软件工程师面试题——2025校招社招通用(五)

说明&#xff1a; 面试题来源于网络书籍&#xff0c;公司题目以及博主原创或修改&#xff08;题目大部分来源于各种公司&#xff09;&#xff1b;文中很多题目&#xff0c;或许大家直接编译器写完&#xff0c;1分钟就出结果了。但在这里博主希望每一个题目&#xff0c;大家都要…

仿真翻页企业内刊制作方法

现如今很多企业都会把自身的企业文化做成电子内刊形式&#xff0c;不再停留于传统纸质的形式&#xff0c;而这种电子版的书更容易被翻阅和传播。特别是员工可以随时随地来阅读企业的文化价值和发展趋向&#xff0c;进而创造出更多的经济效益。不得不说&#xff0c;一本企业文化…

Vue3最佳实践 第八章 ESLint 与 测试 (TypeScript 中Jest与检测环境集成)

TypeScript 中Jest与检测环境集成 ​Vite 已经发布很久了现在Vue3和Vite的生态正在蓬勃发展&#xff0c;现在很多项目中都用到了Vite vue3TypeScript技术栈&#xff0c;进行企业级的项目开发。本文将一步步帮助你创建一个标准的Vite Vue3 TypeScriptJest企业级开发与测试环境…

wxpython如何设置window上任务栏的进度条

该功能是各大编译器或者一些软件在执行耗时操作时&#xff0c;显示进度的一种方式&#xff1a; Qt 如果是使用的pyQt或者是Qt就很简单了&#xff0c;直接使用QWinTaskbarProgress就可以完成该功能。 Wxpython 但是wxpython就没有那么简单了&#xff0c;需要了解一些window的特…

项目经理有责任,没权利,如何确保项目顺利交付?

由于项目经理在项目中所背负的责任并未被赋予相应的权力&#xff0c;因此在协调资源和组织协同工作方面&#xff0c;他们无法简单地借助权力来解决问题。一旦项目出现问题&#xff0c;不论责任在哪一方&#xff0c;项目经理都首当其冲地需要承担责任。 虽然项目经理看似权力很…

SVN出现Cleanup failed to process the following paths...

SVN报错&#xff0c;需要执行SVN的清理命令clean up&#xff0c;但clean up时出现错误Cleanup failed to process the following paths... 解决办法&#xff1a; 1、clean up的窗口&#xff0c;勾选Break locks和Fix time stamps&#xff08;简单方便&#xff09;&#xff1b…

ESP8266模块常规调试过程讲解

ESP8266-WIFI模块串口调试过程讲解 一、ESP8266介绍 ESP8266是一个高度集成的无线SoC(System on a Chip)模块,基于ESP8266芯片,集成了Wi-Fi功能。具有丰富的特性和功能,广泛应用于各种物联网项目中。 ESP8266模块支持802.11b/g/n无线标准,内置TCP/IP协议栈,可以实现串…

Linux之centos7安装配置及Linux常用命令

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是君易--鑨&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的博客专栏《LInux实战开发》。&#x1f3af;&#x1f3af; …

私有云:【7】VCenter安装Composer服务

私有云&#xff1a;【7】VCenter安装Composer服务 1、创建Composer数据库2、VCenter安装Composer服务2.1、安装Native Client组件2.2、对Composer服务器扩容出一个安装盘 3、安装Composer服务 服务器创建好后配置IP&#xff0c;加入域以及添加域管理员cloudadmin&#xff0c;可…

如何校准振弦采集模块以获得更准确的读数?

如何校准振弦采集模块以获得更准确的读数&#xff1f; 振弦采集模块是一种用于测量振弦传感器输出的模块。在使用振弦采集模块时&#xff0c;校准是非常重要的&#xff0c;因为它可以确保您获得准确的测量结果。本文将介绍如何校准振弦采集模块以获得更准确的读数。 1. 使用标…

华为OD机试 - 堆栈中的剩余数字 - 逻辑分析(Java 2023 B卷 200分)

目录 专栏导读一、题目描述二、输入描述三、输出描述1、输入2、输出3、说明 四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&a…

如何零样本实现语义分割

CLIPTeacher&#xff1a;一种基于VLM的通用零样本语义分割框架&#xff0c;有效地利用了可见和忽略区域&#xff0c;而不需要对原CLIP模型进行任何更改&#xff0c;性能提升显著&#xff01;单位&#xff1a;名古屋大学 现有的通用零样本语义分割&#xff08;GZLSS&#xff09…

校园快递派送互助系统 微信小程序设计与实现

本毕业设计的内容是设计实现一个基于Springboot微信小程序的快递校园帮。使用微信开发者是以java语言进行开发&#xff0c;MYSQL为数据库开发平台&#xff0c;Tomcat网络信息服务作为应用服务器。快递校园帮的功能已基本实现&#xff0c;主要包括有用户、快递员、快递公司、快递…

使用Panda-Gym的机器臂模拟进行Deep Q-learning强化学习

强化学习(RL)是一种机器学习方法&#xff0c;它允许代理通过试错来学习如何在环境中表现。行为主体因采取行动导致预期结果而获得奖励&#xff0c;因采取行动导致预期结果而受到惩罚。随着时间的推移&#xff0c;代理学会采取行动&#xff0c;使其预期回报最大化。 RL代理通常使…