当前位置:   article > 正文

C# OpenCvSharp DNN 部署yolov5旋转目标检测_c#yolov5

c#yolov5

目录

效果

模型信息

项目

代码

下载


C# OpenCvSharp DNN 部署yolov5旋转目标检测

效果

模型信息

Inputs
-------------------------
name:images
tensor:Float[1, 3, 1024, 1024]
---------------------------------------------------------------

Outputs
-------------------------
name:output
tensor:Float[1, 107520, 9]
---------------------------------------------------------------

项目

代码

using OpenCvSharp;
using OpenCvSharp.Dnn;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Numerics;
using System.Reflection;
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 = "";

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

        float confThreshold;
        float nmsThreshold;
        float objThreshold;

        float[,] anchors = new float[3, 10] {
                                 {27, 26, 20, 40, 44, 19, 34, 34, 25, 47},
                                 {55, 24, 44, 38, 31, 61, 50, 50, 63, 45},
                                 {65, 62, 88, 60, 84, 79, 113, 85, 148, 122}
        };

        float[] stride = new float[3] { 8.0f, 16.0f, 32.0f };

        string modelpath;

        int inpHeight;
        int inpWidth;

        List<string> class_names;
        int num_class;

        Net opencv_net;
        Mat BN_image;

        Mat image;
        Mat result_image;

        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 Bitmap(image_path);
            image = new Mat(image_path);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            confThreshold = 0.5f;
            nmsThreshold = 0.5f;
            objThreshold = 0.5f;

            modelpath = "model/best.onnx";

            inpHeight = 1024;
            inpWidth = 1024;

            opencv_net = CvDnn.ReadNetFromOnnx(modelpath);

            class_names = new List<string>();
            StreamReader sr = new StreamReader("model/coco.names");
            string line;
            while ((line = sr.ReadLine()) != null)
            {
                class_names.Add(line);
            }
            num_class = class_names.Count();

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

        }

        float sigmoid(float x)
        {
            return (float)(1.0 / (1 + Math.Exp(-x)));
        }

        Mat ResizeImage(Mat srcimg, out int newh, out int neww, out int top, out int left)
        {
            int srch = srcimg.Rows, srcw = srcimg.Cols;
            top = 0;
            left = 0;
            newh = inpHeight;
            neww = inpWidth;
            Mat dstimg = new Mat();
            if (srch != srcw)
            {
                float hw_scale = (float)srch / srcw;
                if (hw_scale > 1)
                {
                    newh = inpHeight;
                    neww = (int)(inpWidth / hw_scale);
                    Cv2.Resize(srcimg, dstimg, new OpenCvSharp.Size(neww, newh), 0, 0, InterpolationFlags.Area);
                    left = (int)((inpWidth - neww) * 0.5);
                    Cv2.CopyMakeBorder(dstimg, dstimg, 0, 0, left, inpWidth - neww - left, BorderTypes.Constant);
                }
                else
                {
                    newh = (int)(inpHeight * hw_scale);
                    neww = inpWidth;
                    Cv2.Resize(srcimg, dstimg, new OpenCvSharp.Size(neww, newh), 0, 0, InterpolationFlags.Area);
                    top = (int)((inpHeight - newh) * 0.5);
                    Cv2.CopyMakeBorder(dstimg, dstimg, top, inpHeight - newh - top, 0, 0, BorderTypes.Constant);
                }
            }
            else
            {
                Cv2.Resize(srcimg, dstimg, new OpenCvSharp.Size(neww, newh));
            }
            return dstimg;
        }

        void nms_angle(List<BoxInfo> input_boxes)
        {
            input_boxes.Sort((a, b) => { return a.score > b.score ? -1 : 1; });

            float[] vArea = new float[input_boxes.Count];
            for (int i = 0; i < input_boxes.Count; ++i)
            {
                vArea[i] = input_boxes[i].box.Size.Height* input_boxes[i].box.Size.Width;
            }

            bool[] isSuppressed = new bool[input_boxes.Count];

            for (int i = 0; i < input_boxes.Count(); ++i)
            {
                if (isSuppressed[i]) { continue; }
                for (int j = i + 1; j < input_boxes.Count(); ++j)
                {
                    if (isSuppressed[j]) { continue; }
                    Point2f[] intersectingRegion;

                    Cv2.RotatedRectangleIntersection(input_boxes[i].box, input_boxes[j].box, out intersectingRegion);

                    if (intersectingRegion.Length==0) { continue; }

                    float inter = (float)Cv2.ContourArea(intersectingRegion);
                    float ovr = inter / (vArea[i] + vArea[j] - inter);

                    if (ovr >= nmsThreshold)
                    {
                        isSuppressed[j] = true;
                    }
                }
            }

            for (int i = isSuppressed.Length - 1; i >= 0; i--)
            {
                if (isSuppressed[i])
                {
                    input_boxes.RemoveAt(i);
                }
            }

        }

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

            image = new Mat(image_path);

            int newh = 0, neww = 0, padh = 0, padw = 0;
            Mat dstimg = ResizeImage(image, out newh, out neww, out padh, out padw);

            BN_image = CvDnn.BlobFromImage(dstimg, 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();

            dt1 = DateTime.Now;

            opencv_net.Forward(outs, outBlobNames);

            dt2 = DateTime.Now;

            int num_proposal = outs[0].Size(1);
            int nout = outs[0].Size(2);

            if (outs[0].Dims > 2)
            {
                outs[0] = outs[0].Reshape(0, num_proposal);
            }

            float ratioh = 1.0f * image.Rows / newh, ratiow = 1.0f * image.Cols / neww;

            float* pdata = (float*)outs[0].Data;

            List<BoxInfo> generate_boxes = new List<BoxInfo>();

            int row_ind = 0;

            for (int n = 0; n < 3; n++)
            {

                int num_grid_x = (int)(inpWidth / stride[n]);
                int num_grid_y = (int)(inpHeight / stride[n]);

                for (int q = 0; q < 5; q++)    ///anchor
                {
                    float anchor_w = anchors[n, q * 2];
                    float anchor_h = anchors[n, q * 2 + 1];
                    for (int i = 0; i < num_grid_y; i++)
                    {
                        for (int j = 0; j < num_grid_x; j++)
                        {
                            float box_score = sigmoid(pdata[6]);
                            if (box_score > objThreshold)
                            {
                                Mat scores = outs[0].Row(row_ind).ColRange(7, 7 + num_class);
                                double minVal, max_class_socre;
                                OpenCvSharp.Point minLoc, classIdPoint;
                                //Get the value and location of the maximum score
                                Cv2.MinMaxLoc(scores, out minVal, out max_class_socre, out minLoc, out classIdPoint);
                                int class_idx = classIdPoint.X;
                                max_class_socre = sigmoid((float)max_class_socre) * box_score;
                                if (max_class_socre > confThreshold)
                                {
                                    float cx = (sigmoid(pdata[0]) * 2.0f - 0.5f + j) * stride[n];  //cx
                                    float cy = (sigmoid(pdata[1]) * 2.0f - 0.5f + i) * stride[n];   //cy
                                    float w = (float)(Math.Pow(sigmoid(pdata[2]) * 2.0f, 2.0f) * anchor_w);   //w
                                    float h = (float)(Math.Pow(sigmoid(pdata[3]) * 2.0f, 2.0f) * anchor_h);  //h
                                    
                                    cx = (cx - padw) * ratiow;
                                    cy = (cy - padh) * ratioh;
                                   
                                    w *= ratiow;
                                    h *= ratioh;

                                    float angle = (float)(Math.Acos(sigmoid(pdata[4])) * 180 / Math.PI);
                                    RotatedRect box = new RotatedRect(new Point2f(cx, cy), new Size2f(w, h), angle);
                                    generate_boxes.Add(new BoxInfo(box, (float)max_class_socre, class_idx));
                                }
                            }
                            row_ind++;
                            pdata += nout;
                        }
                    }
                }

            }

            nms_angle(generate_boxes);

            result_image = image.Clone();

            for (int i = 0; i < generate_boxes.Count(); ++i)
            {
                RotatedRect rectInput = generate_boxes[i].box;
                
                Point2f[] vertices =rectInput.Points();

                for (int j = 0; j < 4; j++)
                {
                    Cv2.Line(result_image, (OpenCvSharp.Point)vertices[j], (OpenCvSharp.Point)vertices[(j + 1) % 4], new Scalar(0, 0, 255), 2);
                }

                int xmin = (int)vertices[0].X;
                int ymin = (int)vertices[0].Y - 10;
                int idx = generate_boxes[i].label;
                string label = class_names[idx] + ":" + generate_boxes[i].score.ToString("0.00");
 
                Cv2.PutText(result_image, label, new OpenCvSharp.Point(xmin, ymin - 5), HersheyFonts.HersheySimplex, 0.75, new Scalar(0, 0, 255), 1);

            }

            pictureBox2.Image = new 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);
        }
    }
}

  1. using OpenCvSharp;
  2. using OpenCvSharp.Dnn;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Drawing;
  6. using System.IO;
  7. using System.Linq;
  8. using System.Linq.Expressions;
  9. using System.Numerics;
  10. using System.Reflection;
  11. using System.Windows.Forms;
  12. namespace OpenCvSharp_DNN_Demo
  13. {
  14. public partial class frmMain : Form
  15. {
  16. public frmMain()
  17. {
  18. InitializeComponent();
  19. }
  20. string fileFilter = "*.*|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png";
  21. string image_path = "";
  22. DateTime dt1 = DateTime.Now;
  23. DateTime dt2 = DateTime.Now;
  24. float confThreshold;
  25. float nmsThreshold;
  26. float objThreshold;
  27. float[,] anchors = new float[3, 10] {
  28. {27, 26, 20, 40, 44, 19, 34, 34, 25, 47},
  29. {55, 24, 44, 38, 31, 61, 50, 50, 63, 45},
  30. {65, 62, 88, 60, 84, 79, 113, 85, 148, 122}
  31. };
  32. float[] stride = new float[3] { 8.0f, 16.0f, 32.0f };
  33. string modelpath;
  34. int inpHeight;
  35. int inpWidth;
  36. List<string> class_names;
  37. int num_class;
  38. Net opencv_net;
  39. Mat BN_image;
  40. Mat image;
  41. Mat result_image;
  42. private void button1_Click(object sender, EventArgs e)
  43. {
  44. OpenFileDialog ofd = new OpenFileDialog();
  45. ofd.Filter = fileFilter;
  46. if (ofd.ShowDialog() != DialogResult.OK) return;
  47. pictureBox1.Image = null;
  48. pictureBox2.Image = null;
  49. textBox1.Text = "";
  50. image_path = ofd.FileName;
  51. pictureBox1.Image = new Bitmap(image_path);
  52. image = new Mat(image_path);
  53. }
  54. private void Form1_Load(object sender, EventArgs e)
  55. {
  56. confThreshold = 0.5f;
  57. nmsThreshold = 0.5f;
  58. objThreshold = 0.5f;
  59. modelpath = "model/best.onnx";
  60. inpHeight = 1024;
  61. inpWidth = 1024;
  62. opencv_net = CvDnn.ReadNetFromOnnx(modelpath);
  63. class_names = new List<string>();
  64. StreamReader sr = new StreamReader("model/coco.names");
  65. string line;
  66. while ((line = sr.ReadLine()) != null)
  67. {
  68. class_names.Add(line);
  69. }
  70. num_class = class_names.Count();
  71. image_path = "test_img/1.png";
  72. pictureBox1.Image = new Bitmap(image_path);
  73. }
  74. float sigmoid(float x)
  75. {
  76. return (float)(1.0 / (1 + Math.Exp(-x)));
  77. }
  78. Mat ResizeImage(Mat srcimg, out int newh, out int neww, out int top, out int left)
  79. {
  80. int srch = srcimg.Rows, srcw = srcimg.Cols;
  81. top = 0;
  82. left = 0;
  83. newh = inpHeight;
  84. neww = inpWidth;
  85. Mat dstimg = new Mat();
  86. if (srch != srcw)
  87. {
  88. float hw_scale = (float)srch / srcw;
  89. if (hw_scale > 1)
  90. {
  91. newh = inpHeight;
  92. neww = (int)(inpWidth / hw_scale);
  93. Cv2.Resize(srcimg, dstimg, new OpenCvSharp.Size(neww, newh), 0, 0, InterpolationFlags.Area);
  94. left = (int)((inpWidth - neww) * 0.5);
  95. Cv2.CopyMakeBorder(dstimg, dstimg, 0, 0, left, inpWidth - neww - left, BorderTypes.Constant);
  96. }
  97. else
  98. {
  99. newh = (int)(inpHeight * hw_scale);
  100. neww = inpWidth;
  101. Cv2.Resize(srcimg, dstimg, new OpenCvSharp.Size(neww, newh), 0, 0, InterpolationFlags.Area);
  102. top = (int)((inpHeight - newh) * 0.5);
  103. Cv2.CopyMakeBorder(dstimg, dstimg, top, inpHeight - newh - top, 0, 0, BorderTypes.Constant);
  104. }
  105. }
  106. else
  107. {
  108. Cv2.Resize(srcimg, dstimg, new OpenCvSharp.Size(neww, newh));
  109. }
  110. return dstimg;
  111. }
  112. void nms_angle(List<BoxInfo> input_boxes)
  113. {
  114. input_boxes.Sort((a, b) => { return a.score > b.score ? -1 : 1; });
  115. float[] vArea = new float[input_boxes.Count];
  116. for (int i = 0; i < input_boxes.Count; ++i)
  117. {
  118. vArea[i] = input_boxes[i].box.Size.Height* input_boxes[i].box.Size.Width;
  119. }
  120. bool[] isSuppressed = new bool[input_boxes.Count];
  121. for (int i = 0; i < input_boxes.Count(); ++i)
  122. {
  123. if (isSuppressed[i]) { continue; }
  124. for (int j = i + 1; j < input_boxes.Count(); ++j)
  125. {
  126. if (isSuppressed[j]) { continue; }
  127. Point2f[] intersectingRegion;
  128. Cv2.RotatedRectangleIntersection(input_boxes[i].box, input_boxes[j].box, out intersectingRegion);
  129. if (intersectingRegion.Length==0) { continue; }
  130. float inter = (float)Cv2.ContourArea(intersectingRegion);
  131. float ovr = inter / (vArea[i] + vArea[j] - inter);
  132. if (ovr >= nmsThreshold)
  133. {
  134. isSuppressed[j] = true;
  135. }
  136. }
  137. }
  138. for (int i = isSuppressed.Length - 1; i >= 0; i--)
  139. {
  140. if (isSuppressed[i])
  141. {
  142. input_boxes.RemoveAt(i);
  143. }
  144. }
  145. }
  146. private unsafe void button2_Click(object sender, EventArgs e)
  147. {
  148. if (image_path == "")
  149. {
  150. return;
  151. }
  152. textBox1.Text = "检测中,请稍等……";
  153. pictureBox2.Image = null;
  154. Application.DoEvents();
  155. image = new Mat(image_path);
  156. int newh = 0, neww = 0, padh = 0, padw = 0;
  157. Mat dstimg = ResizeImage(image, out newh, out neww, out padh, out padw);
  158. BN_image = CvDnn.BlobFromImage(dstimg, 1 / 255.0, new OpenCvSharp.Size(inpWidth, inpHeight), new Scalar(0, 0, 0), true, false);
  159. //配置图片输入数据
  160. opencv_net.SetInput(BN_image);
  161. //模型推理,读取推理结果
  162. Mat[] outs = new Mat[3] { new Mat(), new Mat(), new Mat() };
  163. string[] outBlobNames = opencv_net.GetUnconnectedOutLayersNames().ToArray();
  164. dt1 = DateTime.Now;
  165. opencv_net.Forward(outs, outBlobNames);
  166. dt2 = DateTime.Now;
  167. int num_proposal = outs[0].Size(1);
  168. int nout = outs[0].Size(2);
  169. if (outs[0].Dims > 2)
  170. {
  171. outs[0] = outs[0].Reshape(0, num_proposal);
  172. }
  173. float ratioh = 1.0f * image.Rows / newh, ratiow = 1.0f * image.Cols / neww;
  174. float* pdata = (float*)outs[0].Data;
  175. List<BoxInfo> generate_boxes = new List<BoxInfo>();
  176. int row_ind = 0;
  177. for (int n = 0; n < 3; n++)
  178. {
  179. int num_grid_x = (int)(inpWidth / stride[n]);
  180. int num_grid_y = (int)(inpHeight / stride[n]);
  181. for (int q = 0; q < 5; q++) ///anchor
  182. {
  183. float anchor_w = anchors[n, q * 2];
  184. float anchor_h = anchors[n, q * 2 + 1];
  185. for (int i = 0; i < num_grid_y; i++)
  186. {
  187. for (int j = 0; j < num_grid_x; j++)
  188. {
  189. float box_score = sigmoid(pdata[6]);
  190. if (box_score > objThreshold)
  191. {
  192. Mat scores = outs[0].Row(row_ind).ColRange(7, 7 + num_class);
  193. double minVal, max_class_socre;
  194. OpenCvSharp.Point minLoc, classIdPoint;
  195. //Get the value and location of the maximum score
  196. Cv2.MinMaxLoc(scores, out minVal, out max_class_socre, out minLoc, out classIdPoint);
  197. int class_idx = classIdPoint.X;
  198. max_class_socre = sigmoid((float)max_class_socre) * box_score;
  199. if (max_class_socre > confThreshold)
  200. {
  201. float cx = (sigmoid(pdata[0]) * 2.0f - 0.5f + j) * stride[n]; //cx
  202. float cy = (sigmoid(pdata[1]) * 2.0f - 0.5f + i) * stride[n]; //cy
  203. float w = (float)(Math.Pow(sigmoid(pdata[2]) * 2.0f, 2.0f) * anchor_w); //w
  204. float h = (float)(Math.Pow(sigmoid(pdata[3]) * 2.0f, 2.0f) * anchor_h); //h
  205. cx = (cx - padw) * ratiow;
  206. cy = (cy - padh) * ratioh;
  207. w *= ratiow;
  208. h *= ratioh;
  209. float angle = (float)(Math.Acos(sigmoid(pdata[4])) * 180 / Math.PI);
  210. RotatedRect box = new RotatedRect(new Point2f(cx, cy), new Size2f(w, h), angle);
  211. generate_boxes.Add(new BoxInfo(box, (float)max_class_socre, class_idx));
  212. }
  213. }
  214. row_ind++;
  215. pdata += nout;
  216. }
  217. }
  218. }
  219. }
  220. nms_angle(generate_boxes);
  221. result_image = image.Clone();
  222. for (int i = 0; i < generate_boxes.Count(); ++i)
  223. {
  224. RotatedRect rectInput = generate_boxes[i].box;
  225. Point2f[] vertices =rectInput.Points();
  226. for (int j = 0; j < 4; j++)
  227. {
  228. Cv2.Line(result_image, (OpenCvSharp.Point)vertices[j], (OpenCvSharp.Point)vertices[(j + 1) % 4], new Scalar(0, 0, 255), 2);
  229. }
  230. int xmin = (int)vertices[0].X;
  231. int ymin = (int)vertices[0].Y - 10;
  232. int idx = generate_boxes[i].label;
  233. string label = class_names[idx] + ":" + generate_boxes[i].score.ToString("0.00");
  234. Cv2.PutText(result_image, label, new OpenCvSharp.Point(xmin, ymin - 5), HersheyFonts.HersheySimplex, 0.75, new Scalar(0, 0, 255), 1);
  235. }
  236. pictureBox2.Image = new Bitmap(result_image.ToMemoryStream());
  237. textBox1.Text = "推理耗时:" + (dt2 - dt1).TotalMilliseconds + "ms";
  238. }
  239. private void pictureBox2_DoubleClick(object sender, EventArgs e)
  240. {
  241. Common.ShowNormalImg(pictureBox2.Image);
  242. }
  243. private void pictureBox1_DoubleClick(object sender, EventArgs e)
  244. {
  245. Common.ShowNormalImg(pictureBox1.Image);
  246. }
  247. }
  248. }

下载

源码下载

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/509372
推荐阅读
相关标签
  

闽ICP备14008679号