主页 > 开源代码  > 

C#OnnxRuntime部署DAMO-YOLO交通标识检测

C#OnnxRuntime部署DAMO-YOLO交通标识检测

目录

说明

效果

模型信息

项目

代码

下载

参考


说明

效果

模型信息

Model Properties ------------------------- ---------------------------------------------------------------

Inputs ------------------------- name:input tensor:Float[1, 3, 640, 640] ---------------------------------------------------------------

Outputs ------------------------- name:transposed_output tensor:Float[1, 5, 8400] ---------------------------------------------------------------

项目

代码

using Microsoft.ML.OnnxRuntime; using Microsoft.ML.OnnxRuntime.Tensors; using OpenCvSharp; using OpenCvSharp.Dnn; using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Text; using System.Windows.Forms;

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

        string fileFilter = "*.*|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png";         string image_path = "";         string model_path;         string classer_path;         public string[] class_names;         public int class_num;

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

        int input_height;         int input_width;

        InferenceSession onnx_session;

        int box_num;         float conf_threshold;         float nms_threshold;

        StringBuilder sb = new StringBuilder();

        /// <summary>         /// 选择图片         /// </summary>         /// <param name="sender"></param>         /// <param name="e"></param>         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 = "";             pictureBox2.Image = null;         }

        /// <summary>         /// 推理         /// </summary>         /// <param name="sender"></param>         /// <param name="e"></param>         private void button2_Click(object sender, EventArgs e)         {             if (image_path == "")             {                 return;             }

            button2.Enabled = false;             pictureBox2.Image = null;             textBox1.Text = "";             sb.Clear();             Application.DoEvents();

            Mat image = new Mat(image_path);

            float ratio = Math.Min(input_height * 1.0f / image.Rows, input_width * 1.0f / image.Cols);             int neww = (int)(image.Cols * ratio);             int newh = (int)(image.Rows * ratio);             Mat dstimg = new Mat();             Cv2.CvtColor(image, dstimg, ColorConversionCodes.BGR2RGB);             Cv2.Resize(dstimg, dstimg, new OpenCvSharp.Size(neww, newh));             Cv2.CopyMakeBorder(dstimg, dstimg, 0, input_height - newh, 0, input_width - neww, BorderTypes.Constant, new Scalar(1));

            //Cv2.ImShow("input_img", dstimg);

            //输入Tensor             Tensor<float> input_tensor = new DenseTensor<float>(new[] { 1, 3, 640, 640 });             for (int y = 0; y < dstimg.Height; y++)             {                 for (int x = 0; x < dstimg.Width; x++)                 {                     input_tensor[0, 0, y, x] = dstimg.At<Vec3b>(y, x)[0];                     input_tensor[0, 1, y, x] = dstimg.At<Vec3b>(y, x)[1];                     input_tensor[0, 2, y, x] = dstimg.At<Vec3b>(y, x)[2];                 }             }

            dstimg.Dispose();

            List<NamedOnnxValue> input_container = new List<NamedOnnxValue>             {                 NamedOnnxValue.CreateFromTensor("input", input_tensor)             };

            //推理             dt1 = DateTime.Now;             var ort_outputs = onnx_session.Run(input_container).ToArray();             dt2 = DateTime.Now;

            float[] data = Transpose(ort_outputs[0].AsTensor<float>().ToArray(), 4 + class_num, box_num);

            float[] confidenceInfo = new float[class_num];             float[] rectData = new float[4];

            List<DetectionResult> detResults = new List<DetectionResult>();

            for (int i = 0; i < box_num; i++)             {                 Array.Copy(data, i * (class_num + 4), rectData, 0, 4);                 Array.Copy(data, i * (class_num + 4) + 4, confidenceInfo, 0, class_num);

                float score = confidenceInfo.Max(); // 获取最大值

                int maxIndex = Array.IndexOf(confidenceInfo, score); // 获取最大值的位置

                int xmin = (int)(rectData[0] / ratio);                 int ymin = (int)(rectData[1] / ratio);                 int xmax = (int)(rectData[2] / ratio);                 int ymax = (int)(rectData[3] / ratio);

                Rect box = new Rect();                 box.X = (int)xmin;                 box.Y = (int)ymin;                 box.Width = (int)(xmax - xmin);                 box.Height = (int)(ymax - ymin);

                detResults.Add(new DetectionResult(                    maxIndex,                    class_names[maxIndex],                    box,                    score));             }

            //NMS             CvDnn.NMSBoxes(detResults.Select(x => x.Rect), detResults.Select(x => x.Confidence), conf_threshold, nms_threshold, out int[] indices);             detResults = detResults.Where((x, index) => indices.Contains(index)).ToList();

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

            //绘制结果             Mat result_image = image.Clone();             foreach (DetectionResult r in detResults)             {                 Cv2.PutText(result_image, $"{r.Class}:{r.Confidence:P0}", new OpenCvSharp.Point(r.Rect.TopLeft.X, r.Rect.TopLeft.Y - 10), HersheyFonts.HersheySimplex, 1, Scalar.Red, 2);                 Cv2.Rectangle(result_image, r.Rect, Scalar.Red, thickness: 2);

                sb.AppendLine(string.Format("{0}:{1},({2},{3},{4},{5})"                    , r.Class                    , r.Confidence.ToString("P0")                    , r.Rect.TopLeft.X                    , r.Rect.TopLeft.Y                    , r.Rect.BottomRight.X                    , r.Rect.BottomRight.Y                    ));             }

            if (pictureBox2.Image != null)             {                 pictureBox2.Image.Dispose();             }

            pictureBox2.Image = new Bitmap(result_image.ToMemoryStream());

            result_image.Dispose();

            textBox1.Text = sb.ToString();

            button2.Enabled = true;         }

        /// <summary>         ///窗体加载         /// </summary>         /// <param name="sender"></param>         /// <param name="e"></param>         private void Form1_Load(object sender, EventArgs e)         {             model_path = "model/damoyolo_traffic_sign.onnx";

            //创建输出会话,用于输出模型读取信息             SessionOptions options = new SessionOptions();             options.LogSeverityLevel = OrtLoggingLevel.ORT_LOGGING_LEVEL_INFO;             options.AppendExecutionProvider_CPU(0);// 设置为CPU上运行

            // 创建推理模型类,读取模型文件             onnx_session = new InferenceSession(model_path, options);//model_path 为onnx模型文件的路径

            input_height = 640;             input_width = 640;

            box_num = 8400;             conf_threshold = 0.25f;             nms_threshold = 0.5f;

            classer_path = "model/lable.txt";             class_names = File.ReadAllLines(classer_path, Encoding.UTF8);             class_num = class_names.Length;

            image_path = "test_img/1.jpg";             pictureBox1.Image = new Bitmap(image_path);         }

        /// <summary>         /// 保存         /// </summary>         /// <param name="sender"></param>         /// <param name="e"></param>         private void button3_Click(object sender, EventArgs e)         {             if (pictureBox2.Image == null)             {                 return;             }             Bitmap output = new Bitmap(pictureBox2.Image);             SaveFileDialog sdf = new SaveFileDialog();             sdf.Title = "保存";             sdf.Filter = "Images (*.jpg)|*.jpg|Images (*.png)|*.png|Images (*.bmp)|*.bmp|Images (*.emf)|*.emf|Images (*.exif)|*.exif|Images (*.gif)|*.gif|Images (*.ico)|*.ico|Images (*.tiff)|*.tiff|Images (*.wmf)|*.wmf";             if (sdf.ShowDialog() == DialogResult.OK)             {                 switch (sdf.FilterIndex)                 {                     case 1:                         {                             output.Save(sdf.FileName, ImageFormat.Jpeg);                             break;                         }                     case 2:                         {                             output.Save(sdf.FileName, ImageFormat.Png);                             break;                         }                     case 3:                         {                             output.Save(sdf.FileName, ImageFormat.Bmp);                             break;                         }                     case 4:                         {                             output.Save(sdf.FileName, ImageFormat.Emf);                             break;                         }                     case 5:                         {                             output.Save(sdf.FileName, ImageFormat.Exif);                             break;                         }                     case 6:                         {                             output.Save(sdf.FileName, ImageFormat.Gif);                             break;                         }                     case 7:                         {                             output.Save(sdf.FileName, ImageFormat.Icon);                             break;                         }

                    case 8:                         {                             output.Save(sdf.FileName, ImageFormat.Tiff);                             break;                         }                     case 9:                         {                             output.Save(sdf.FileName, ImageFormat.Wmf);                             break;                         }                 }                 MessageBox.Show("保存成功,位置:" + sdf.FileName);             }         }

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

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

        public void ShowNormalImg(Image img)         {             if (img == null) return;

            frmShow frm = new frmShow();

            frm.Width = Screen.PrimaryScreen.Bounds.Width;             frm.Height = Screen.PrimaryScreen.Bounds.Height;

            if (frm.Width > img.Width)             {                 frm.Width = img.Width;             }

            if (frm.Height > img.Height)             {                 frm.Height = img.Height;             }

            bool b = frm.richTextBox1.ReadOnly;             Clipboard.SetDataObject(img, true);             frm.richTextBox1.ReadOnly = false;             frm.richTextBox1.Paste(DataFormats.GetFormat(DataFormats.Bitmap));             frm.richTextBox1.ReadOnly = b;

            frm.ShowDialog();

        }

        public unsafe float[] Transpose(float[] tensorData, int rows, int cols)         {             float[] transposedTensorData = new float[tensorData.Length];

            fixed (float* pTensorData = tensorData)             {                 fixed (float* pTransposedData = transposedTensorData)                 {                     for (int i = 0; i < rows; i++)                     {                         for (int j = 0; j < cols; j++)                         {                             int index = i * cols + j;                             int transposedIndex = j * rows + i;                             pTransposedData[transposedIndex] = pTensorData[index];                         }                     }                 }             }             return transposedTensorData;         }     }

    public class DetectionResult     {         public DetectionResult(int ClassId, string Class, Rect Rect, float Confidence)         {             this.ClassId = ClassId;             this.Confidence = Confidence;             this.Rect = Rect;             this.Class = Class;         }

        public string Class { get; set; }

        public int ClassId { get; set; }

        public float Confidence { get; set; }

        public Rect Rect { get; set; }

    }

}  

using Microsoft.ML.OnnxRuntime; using Microsoft.ML.OnnxRuntime.Tensors; using OpenCvSharp; using OpenCvSharp.Dnn; using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Text; using System.Windows.Forms; namespace Onnx_Demo { public partial class Form1 : Form { public Form1() { InitializeComponent(); } string fileFilter = "*.*|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png"; string image_path = ""; string model_path; string classer_path; public string[] class_names; public int class_num; DateTime dt1 = DateTime.Now; DateTime dt2 = DateTime.Now; int input_height; int input_width; InferenceSession onnx_session; int box_num; float conf_threshold; float nms_threshold; StringBuilder sb = new StringBuilder(); /// <summary> /// 选择图片 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> 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 = ""; pictureBox2.Image = null; } /// <summary> /// 推理 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button2_Click(object sender, EventArgs e) { if (image_path == "") { return; } button2.Enabled = false; pictureBox2.Image = null; textBox1.Text = ""; sb.Clear(); Application.DoEvents(); Mat image = new Mat(image_path); float ratio = Math.Min(input_height * 1.0f / image.Rows, input_width * 1.0f / image.Cols); int neww = (int)(image.Cols * ratio); int newh = (int)(image.Rows * ratio); Mat dstimg = new Mat(); Cv2.CvtColor(image, dstimg, ColorConversionCodes.BGR2RGB); Cv2.Resize(dstimg, dstimg, new OpenCvSharp.Size(neww, newh)); Cv2.CopyMakeBorder(dstimg, dstimg, 0, input_height - newh, 0, input_width - neww, BorderTypes.Constant, new Scalar(1)); //Cv2.ImShow("input_img", dstimg); //输入Tensor Tensor<float> input_tensor = new DenseTensor<float>(new[] { 1, 3, 640, 640 }); for (int y = 0; y < dstimg.Height; y++) { for (int x = 0; x < dstimg.Width; x++) { input_tensor[0, 0, y, x] = dstimg.At<Vec3b>(y, x)[0]; input_tensor[0, 1, y, x] = dstimg.At<Vec3b>(y, x)[1]; input_tensor[0, 2, y, x] = dstimg.At<Vec3b>(y, x)[2]; } } dstimg.Dispose(); List<NamedOnnxValue> input_container = new List<NamedOnnxValue> { NamedOnnxValue.CreateFromTensor("input", input_tensor) }; //推理 dt1 = DateTime.Now; var ort_outputs = onnx_session.Run(input_container).ToArray(); dt2 = DateTime.Now; float[] data = Transpose(ort_outputs[0].AsTensor<float>().ToArray(), 4 + class_num, box_num); float[] confidenceInfo = new float[class_num]; float[] rectData = new float[4]; List<DetectionResult> detResults = new List<DetectionResult>(); for (int i = 0; i < box_num; i++) { Array.Copy(data, i * (class_num + 4), rectData, 0, 4); Array.Copy(data, i * (class_num + 4) + 4, confidenceInfo, 0, class_num); float score = confidenceInfo.Max(); // 获取最大值 int maxIndex = Array.IndexOf(confidenceInfo, score); // 获取最大值的位置 int xmin = (int)(rectData[0] / ratio); int ymin = (int)(rectData[1] / ratio); int xmax = (int)(rectData[2] / ratio); int ymax = (int)(rectData[3] / ratio); Rect box = new Rect(); box.X = (int)xmin; box.Y = (int)ymin; box.Width = (int)(xmax - xmin); box.Height = (int)(ymax - ymin); detResults.Add(new DetectionResult( maxIndex, class_names[maxIndex], box, score)); } //NMS CvDnn.NMSBoxes(detResults.Select(x => x.Rect), detResults.Select(x => x.Confidence), conf_threshold, nms_threshold, out int[] indices); detResults = detResults.Where((x, index) => indices.Contains(index)).ToList(); sb.AppendLine("推理耗时:" + (dt2 - dt1).TotalMilliseconds + "ms"); sb.AppendLine("------------------------------"); //绘制结果 Mat result_image = image.Clone(); foreach (DetectionResult r in detResults) { Cv2.PutText(result_image, $"{r.Class}:{r.Confidence:P0}", new OpenCvSharp.Point(r.Rect.TopLeft.X, r.Rect.TopLeft.Y - 10), HersheyFonts.HersheySimplex, 1, Scalar.Red, 2); Cv2.Rectangle(result_image, r.Rect, Scalar.Red, thickness: 2); sb.AppendLine(string.Format("{0}:{1},({2},{3},{4},{5})" , r.Class , r.Confidence.ToString("P0") , r.Rect.TopLeft.X , r.Rect.TopLeft.Y , r.Rect.BottomRight.X , r.Rect.BottomRight.Y )); } if (pictureBox2.Image != null) { pictureBox2.Image.Dispose(); } pictureBox2.Image = new Bitmap(result_image.ToMemoryStream()); result_image.Dispose(); textBox1.Text = sb.ToString(); button2.Enabled = true; } /// <summary> ///窗体加载 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Form1_Load(object sender, EventArgs e) { model_path = "model/damoyolo_traffic_sign.onnx"; //创建输出会话,用于输出模型读取信息 SessionOptions options = new SessionOptions(); options.LogSeverityLevel = OrtLoggingLevel.ORT_LOGGING_LEVEL_INFO; options.AppendExecutionProvider_CPU(0);// 设置为CPU上运行 // 创建推理模型类,读取模型文件 onnx_session = new InferenceSession(model_path, options);//model_path 为onnx模型文件的路径 input_height = 640; input_width = 640; box_num = 8400; conf_threshold = 0.25f; nms_threshold = 0.5f; classer_path = "model/lable.txt"; class_names = File.ReadAllLines(classer_path, Encoding.UTF8); class_num = class_names.Length; image_path = "test_img/1.jpg"; pictureBox1.Image = new Bitmap(image_path); } /// <summary> /// 保存 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button3_Click(object sender, EventArgs e) { if (pictureBox2.Image == null) { return; } Bitmap output = new Bitmap(pictureBox2.Image); SaveFileDialog sdf = new SaveFileDialog(); sdf.Title = "保存"; sdf.Filter = "Images (*.jpg)|*.jpg|Images (*.png)|*.png|Images (*.bmp)|*.bmp|Images (*.emf)|*.emf|Images (*.exif)|*.exif|Images (*.gif)|*.gif|Images (*.ico)|*.ico|Images (*.tiff)|*.tiff|Images (*.wmf)|*.wmf"; if (sdf.ShowDialog() == DialogResult.OK) { switch (sdf.FilterIndex) { case 1: { output.Save(sdf.FileName, ImageFormat.Jpeg); break; } case 2: { output.Save(sdf.FileName, ImageFormat.Png); break; } case 3: { output.Save(sdf.FileName, ImageFormat.Bmp); break; } case 4: { output.Save(sdf.FileName, ImageFormat.Emf); break; } case 5: { output.Save(sdf.FileName, ImageFormat.Exif); break; } case 6: { output.Save(sdf.FileName, ImageFormat.Gif); break; } case 7: { output.Save(sdf.FileName, ImageFormat.Icon); break; } case 8: { output.Save(sdf.FileName, ImageFormat.Tiff); break; } case 9: { output.Save(sdf.FileName, ImageFormat.Wmf); break; } } MessageBox.Show("保存成功,位置:" + sdf.FileName); } } private void pictureBox1_DoubleClick(object sender, EventArgs e) { ShowNormalImg(pictureBox1.Image); } private void pictureBox2_DoubleClick(object sender, EventArgs e) { ShowNormalImg(pictureBox2.Image); } public void ShowNormalImg(Image img) { if (img == null) return; frmShow frm = new frmShow(); frm.Width = Screen.PrimaryScreen.Bounds.Width; frm.Height = Screen.PrimaryScreen.Bounds.Height; if (frm.Width > img.Width) { frm.Width = img.Width; } if (frm.Height > img.Height) { frm.Height = img.Height; } bool b = frm.richTextBox1.ReadOnly; Clipboard.SetDataObject(img, true); frm.richTextBox1.ReadOnly = false; frm.richTextBox1.Paste(DataFormats.GetFormat(DataFormats.Bitmap)); frm.richTextBox1.ReadOnly = b; frm.ShowDialog(); } public unsafe float[] Transpose(float[] tensorData, int rows, int cols) { float[] transposedTensorData = new float[tensorData.Length]; fixed (float* pTensorData = tensorData) { fixed (float* pTransposedData = transposedTensorData) { for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { int index = i * cols + j; int transposedIndex = j * rows + i; pTransposedData[transposedIndex] = pTensorData[index]; } } } } return transposedTensorData; } } public class DetectionResult { public DetectionResult(int ClassId, string Class, Rect Rect, float Confidence) { this.ClassId = ClassId; this.Confidence = Confidence; this.Rect = Rect; this.Class = Class; } public string Class { get; set; } public int ClassId { get; set; } public float Confidence { get; set; } public Rect Rect { get; set; } } } 下载

源码下载

参考

modelscope /models/iic/cv_tinynas_object-detection_damoyolo_traffic_sign/summary

标签:

C#OnnxRuntime部署DAMO-YOLO交通标识检测由讯客互联开源代码栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“C#OnnxRuntime部署DAMO-YOLO交通标识检测