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

效果

C# Onnx DirectMHP 全范围角度2D多人头部姿势估计_第1张图片

项目

C# Onnx DirectMHP 全范围角度2D多人头部姿势估计_第2张图片

代码

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 input_tensor;
        List input_ontainer;

        IDisposableReadOnlyCollection result_infer;
        DisposableNamedOnnxValue[] results_onnxvalue;

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

            // 创建输出会话
            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(new[] { 1, 3, 640, 640 });

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

        }

        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(y, x)[0] / 255f;
                    input_tensor[0, 1, y, x] = resize_image.At(y, x)[1] / 255f;
                    input_tensor[0, 2, y, x] = resize_image.At(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();

            result_array = result_tensors.ToArray();

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

            List faceboxes = new List();
            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);
        }
    }
}

下载

源码下载

你可能感兴趣的:(AI,C#,Onnx,2D人头姿势估计,DirectMHP)