效果

项目

代码
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);
        }
    }
}
 
下载
源码下载



















