C# Onnx DirectMHP 全范围角度2D多人头部姿势估计

news2024/11/28 14:15:17

效果

项目

代码

using Microsoft.ML.OnnxRuntime.Tensors;
using Microsoft.ML.OnnxRuntime;
using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Linq;
using System.Numerics;

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

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

        DateTime dt1 = DateTime.Now;
        DateTime dt2 = DateTime.Now;

        Mat image;

        string model_path = "";

        float[] factors = new float[2];

        SessionOptions options;
        InferenceSession onnx_session;
        Tensor<float> input_tensor;
        List<NamedOnnxValue> input_ontainer;

        IDisposableReadOnlyCollection<DisposableNamedOnnxValue> result_infer;
        DisposableNamedOnnxValue[] results_onnxvalue;

        Tensor<float> result_tensors;
        float[] result_array;

        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = fileFilter;
            if (ofd.ShowDialog() != DialogResult.OK) return;

            pictureBox1.Image = null;
            pictureBox2.Image = null;
            textBox1.Text = "";

            image_path = ofd.FileName;
            pictureBox1.Image = new System.Drawing.Bitmap(image_path);
            image = new Mat(image_path);
        }

        private void Form1_Load(object sender, EventArgs e)
        {

            // 创建输入容器
            input_ontainer = new List<NamedOnnxValue>();

            // 创建输出会话
            options = new SessionOptions();
            options.LogSeverityLevel = OrtLoggingLevel.ORT_LOGGING_LEVEL_INFO;
            options.AppendExecutionProvider_CPU(0);// 设置为CPU上运行

            // 创建推理模型类,读取本地模型文件
            model_path = "model/directmhp_cmu_m_post_640x640.onnx";
            onnx_session = new InferenceSession(model_path, options);

            // 输入Tensor
            input_tensor = new DenseTensor<float>(new[] { 1, 3, 640, 640 });

            // 创建输入容器
            input_ontainer = new List<NamedOnnxValue>();

        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (image_path == "")
            {
                return;
            }
            textBox1.Text = "检测中,请稍等……";
            pictureBox2.Image = null;
            Application.DoEvents();

            //图片缩放
            image = new Mat(image_path);

            int max_image_length = image.Cols > image.Rows ? image.Cols : image.Rows;
            Mat max_image = Mat.Zeros(new OpenCvSharp.Size(max_image_length, max_image_length), MatType.CV_8UC3);
            Rect roi = new Rect(0, 0, image.Cols, image.Rows);
            image.CopyTo(new Mat(max_image, roi));

            factors[0] = factors[1] = (float)(max_image_length / 640.0);

            //将图片转为RGB通道
            Mat image_rgb = new Mat();
            Cv2.CvtColor(max_image, image_rgb, ColorConversionCodes.BGR2RGB);

            Mat resize_image = new Mat();
            Cv2.Resize(image_rgb, resize_image, new OpenCvSharp.Size(640, 640));

            //输入Tensor
            for (int y = 0; y < resize_image.Height; y++)
            {
                for (int x = 0; x < resize_image.Width; x++)
                {
                    input_tensor[0, 0, y, x] = resize_image.At<Vec3b>(y, x)[0] / 255f;
                    input_tensor[0, 1, y, x] = resize_image.At<Vec3b>(y, x)[1] / 255f;
                    input_tensor[0, 2, y, x] = resize_image.At<Vec3b>(y, x)[2] / 255f;
                }
            }

            resize_image.Dispose();
            image_rgb.Dispose();

            //将 input_tensor 放入一个输入参数的容器,并指定名称
            input_ontainer.Add(NamedOnnxValue.CreateFromTensor("input", input_tensor));

            dt1 = DateTime.Now;
            //运行 Inference 并获取结果
            result_infer = onnx_session.Run(input_ontainer);
            dt2 = DateTime.Now;

            //将输出结果转为DisposableNamedOnnxValue数组
            results_onnxvalue = result_infer.ToArray();

            //读取第一个节点输出并转为Tensor数据
            result_tensors = results_onnxvalue[0].AsTensor<float>();

            result_array = result_tensors.ToArray();

            int num_face = result_tensors.Dimensions[0];
            int len = result_tensors.Dimensions[1];

            List<BoxInfo> faceboxes = new List<BoxInfo>();
            float scale_h = factors[0];
            float scale_w = factors[1];

            float confThreshold = 0.5f;

            for (int i = 0; i < num_face; i++)
            {
                float score = result_array[i * len + 6];
                if (score > confThreshold)
                {
                    float xmin = Math.Max(result_array[i * len + 2] * scale_w, 0f);
                    float ymin = Math.Max(result_array[i * len + 3] * scale_h, 0f);
                    float xmax = Math.Min(result_array[i * len + 4] * scale_w, (float)image.Cols);
                    float ymax = Math.Min(result_array[i * len + 5] * scale_h, (float)image.Rows);
                    faceboxes.Add(new BoxInfo(xmin, ymin, xmax, ymax, score, result_array[i * len + 7], result_array[i * len + 8], result_array[i * len + 9]));
                }
            }

            Mat result_image = image.Clone();

            foreach (BoxInfo item in faceboxes)
            {
                Cv2.Rectangle(result_image, new OpenCvSharp.Point(item.xmin, item.ymin), new OpenCvSharp.Point(item.xmax, item.ymax), new Scalar(0, 0, 255), 2);

                float pitch = (float)(item.pitch * Math.PI / 180);
                float yaw = (float)(-item.yaw * Math.PI / 180);
                float roll = (float)(item.roll * Math.PI / 180);
                float tdx = (float)((item.xmin + item.xmax) * 0.5);
                float tdy = (float)((item.ymin + item.ymax) * 0.5);
                int size_ = (int)(Math.Floor(item.xmax - item.xmin) / 3);

                //X - Axis pointing to right.drawn in red
                float x1 = (float)(size_ * (Math.Cos(yaw) * Math.Cos(roll)) + tdx);
                float y1 = (float)(size_ * (Math.Cos(pitch) * Math.Sin(roll) + Math.Cos(roll) * Math.Sin(pitch) * Math.Sin(yaw)) + tdy);

                //Y-Axis | drawn in green
                float x2 = (float)(size_ * (-Math.Cos(yaw) * Math.Sin(roll)) + tdx);
                float y2 = (float)(size_ * (Math.Cos(pitch) * Math.Cos(roll) - Math.Sin(pitch) * Math.Sin(yaw) * Math.Sin(roll)) + tdy);

                //Z-Axis (out of the screen) drawn in blue
                float x3 = (float)(size_ * (Math.Sin(yaw)) + tdx);
                float y3 = (float)(size_ * (-Math.Cos(yaw) * Math.Sin(pitch)) + tdy);

                Cv2.Line(result_image, new OpenCvSharp.Point(tdx, tdy), new OpenCvSharp.Point(x1, y1), new Scalar(0, 0, 255), 2);
                Cv2.Line(result_image, new OpenCvSharp.Point(tdx, tdy), new OpenCvSharp.Point(x2, y2), new Scalar(0, 255, 0), 2);
                Cv2.Line(result_image, new OpenCvSharp.Point(tdx, tdy), new OpenCvSharp.Point(x3, y3), new Scalar(255, 0, 0), 2);

            }


            pictureBox2.Image = new System.Drawing.Bitmap(result_image.ToMemoryStream());
            textBox1.Text = "推理耗时:" + (dt2 - dt1).TotalMilliseconds + "ms";
        }

        private void pictureBox2_DoubleClick(object sender, EventArgs e)
        {
            Common.ShowNormalImg(pictureBox2.Image);
        }

        private void pictureBox1_DoubleClick(object sender, EventArgs e)
        {
            Common.ShowNormalImg(pictureBox1.Image);
        }
    }
}

下载

源码下载

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

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

相关文章

Leetcode-876 链表的中间结点

本人解法有点硬凑答案… /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val val; }* ListNode(int val, ListNode next) { this.val val; this.next next; …

京东数据分析:2023年10月京东洗衣机行业品牌销售排行榜

鲸参谋监测的京东平台10月份洗衣机市场销售数据已出炉&#xff01; 10月份&#xff0c;洗衣机市场整体销售呈上升走势。鲸参谋数据显示&#xff0c;今年10月&#xff0c;京东平台洗衣机市场的销量为143万&#xff0c;环比增长约23%&#xff0c;同比增长约1%&#xff1b;销售额约…

千兆工业交换机——工业环境的高速以太网交换机

千兆工业交换机&#xff08;Gigabit Industrial Switch&#xff09;是一种用于工业环境的高速以太网交换机&#xff0c;具有以下特性&#xff1a; 1. 高速传输&#xff1a;支持千兆以太网速率&#xff08;1000Mbps&#xff09;&#xff0c;提供更快的数据传输速度和高带宽。 2.…

C#中.NET 7.0控制台应用使用LINQtoSQL、LINQtoXML

目录 一、新建控制台应用和数据库连接 二、手动添加System.Data.Linq程序包 三、手动添加System.Data.SqlClient程序包 四、再次操作DataClasses1.dbml 五、示例 1.源码 2.xml文件 默认安装的.NET 7.0控制台应用是不支持使用LINQtoSQL、LINQtoXML的。 默认安装的.NET F…

配置无线路由器

配置无线路由器 将Linux配置为无线路由器。使用hostapd&#xff0c;可以配置无线网卡为AP模式。 这里使用buildroot来生成这个工具。Wi-Fi模块使用的是 rt8188eus。 1. 内核配置 2. buildroot配置 开启 rt8188eus 驱动 3. 启动hostapd 系统启动后&#xff0c;会自动加载无线…

【测开求职】面试题:计算机网络 精简版整理

本篇文章整理的是在秋招过程中遇到的计算机网络高频面试题&#xff0c;应付部分中小厂的测试开发工程师面试完全没有问题&#xff0c;如果时间充足的话&#xff0c;建议再看一下笔者的另外一篇文章&#xff1a;【测开求职】面试题&#xff1a;计算机网络 详细版整理&#xff0c…

JavaScript 基本数据类型

字符串 在JS中&#xff0c;数据类型有&#xff1a;字符串、数字、布尔、数组、对象、Null、Undefined 用到最多的还是字符串和数组的转换。 <!DOCTYPE html> <html> <head><meta charset"UTF-8"><title>首页</title><style&g…

TSINGSEE智能分析网关V4车辆结构化数据检测算法及车辆布控

车辆结构化视频AI检测技术&#xff0c;可通过AI识别对视频图像中划定区域内的出现的车辆进行检测、抓拍和识别&#xff0c;系统通过视频采集设备获取车辆特征信息&#xff0c;经过预处理之后&#xff0c;接入AI识别算法并与车辆底库进行对比&#xff0c;快速识别车辆身份和属性…

cmake vs2022编译opencv4.5.2 x86 版本

cmake 编译opencv 452 x86 版本 where is the source code 选项放置你的源文件 where to build the binaries 放置你生成结果的文件夹 点击按钮Configure,弹出提示&#xff0c;选择Win32&#xff0c;finishi 等待生成 列表中出现红色的选项&#xff0c;根据你的需要取消或…

Java http请求工具连接超时时间

研究了一下三种java常用的http请求工具框架hutool、okhttp3、spring RestTemplate 对于连接超时和读超时的处理机制。 运行环境 jdk8 windows 连接超时 hutool、okhttp3、spring RestTemplate 三种请求&#xff0c;底层使用的都是jdk里的java.net.DualStackPlainSocketImpl#…

RS232通讯转485通讯接线心得

最近在接can 485 232的通讯线&#xff0c;无可避免的遇到了一系列问题&#xff0c;各个厂家之间的引脚定义不太一样&#xff0c;这就导致我们要经常的接线&#xff0c;现在也是有了一点心得所以记录下来。接下来进入标题&#xff1a; 目前我遇到的问题是&#xff1a;转接泰琪丰…

Android选项卡TabHost

选项卡主要由TabHost(标签&#xff0c;主人)&#xff0c;TabWidget(微件)和FrameLayout3个组件组成&#xff0c;用于实现一个多标签页的用户界面。 1. TabHost在XML文件中添加&#xff1a; XML布局文件中添加选项卡时必须使用系统id来为各组件指定id属性。 <TabHostandro…

交易中最佳的建仓时机,fpmarkets一个指标搞定

你是不是也是这样?经常因为自己的后知后觉错过了潜在的盈利机会&#xff0c;甚至在错误的时间点进行交易而产生亏损。其实很简单&#xff0c;fpmarkets一个指标搞定&#xff0c;解一下鳄鱼指标。 通过鳄鱼线选择最佳的建仓时机。绿线是大量合约进入市场并偏向一个方向的第一个…

Makefile(详细教程)

Makefile&#xff08;详细教程&#xff09; 1. Makefile的相关概念介绍 1.1 Makefile是什么 一个工程中的源文件不计其数&#xff0c;其按类型、功能、模块分别放在若干个目录中&#xff0c;Makefile定义了一系列的规则来指定哪些文件需要先编译&#xff0c;哪些文件需要后编…

阿里云99元服务器2核2G3M带宽_4年396元_新老用户同享

阿里云99元服务器新老用户同享活动 aliyunfuwuqi.com/go/aliyun 首先要在2023年11月1日去阿里云活动页下单新购这个套餐&#xff0c;享受99元包1年。同天再续费1年又享受了99元包1年&#xff1b;等到明年2024年11月1日之后&#xff0c;又可以以99元续1年&#xff1b;最后等到20…

【OpenCV实现图像:图像处理技巧之空间滤波】

文章目录 概要导入库空间过滤器模板展示效果分析与总结 概要 空间滤波器是数字图像处理中的基本工具之一。它通过在图像的每个像素位置上应用一个特定的滤波模板&#xff0c;根据该位置周围的相邻像素值进行加权操作&#xff0c;从而修改该像素的值。这种加权操作能够突出或模…

3.28每日一题(微分方程的计算)

注&#xff1a; 1、题目中的变上限x在 被积函数中&#xff0c;所以不能直接求导&#xff0c;需要先将等式拆分 2、拆完求导的时候&#xff0c;注意x的平方和定积分是乘法求导的法则&#xff0c;容易忽略 3、两边求导后还有变上限积分存在&#xff0c;此时用莱布尼兹公式&#x…

天青色等烟雨追风k9羞涩来袭

新一代追风k9服务器硬件技术的进步是推动追风k9服务器未来前景的重要因素。随着科技的不断进步&#xff0c;服务器的算力和效率都得到了显著提升。比特大陆科技作为领先的区块链服务器制造商&#xff0c;一直致力于研发和应用先进的芯片技术&#xff0c;不断提高服务器的算力和…

深度学习读取txt训练数据绘制参数曲线图的方法

有一些深度学习模型是并不像yolo系列那样最终输出相应的参数图,有很多训练形成了一个训练log文件,于是需要读取log文件中的内容并绘制成曲线图。 如下实例,有一个log文件的部分截图,需要将其读取出来并绘制曲线图 废话不多说,直接上代码 import os import re import p…

多VLAN之间的通信,静态路由

一、适用场景 1、多个C类网络&#xff08;不同网段&#xff09;之间需要通信&#xff0c;每个网段有1个网关ip。 2、当网络结构比较简单时&#xff0c;只需配置静态路由就可以使网络正常工作。本例采用简单网络结构 3、在复杂网络环境中&#xff0c;配置静态路由可以改进网络的…