隐藏

C# OpenCvSharp DNN 部署yolov5不规则四边形目标检测

发布:2024/2/4 14:41:59作者:管理员 来源:本站 浏览次数:428

目录


效果


模型信息


项目


代码


下载


C# OpenCvSharp DNN 部署yolov5不规则四边形目标检测

效果


模型信息


Inputs

-------------------------

name:images

tensor:Float[1, 3, 1024, 1024]

---------------------------------------------------------------


Outputs

-------------------------

name:output

tensor:Float[1, 64512, 11]

---------------------------------------------------------------

项目


代码


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, 6] {

                                          {31, 30, 28, 49, 50, 31},

                                          {46, 45, 58, 58, 74, 74},

                                          {94, 94, 115, 115, 151, 151}

                                          };


       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;

       }


       float IoU(BoxInfo polya, BoxInfo polyb, int max_w, int max_h)

       {

           List<List<OpenCvSharp.Point>> poly_array0 = new List<List<OpenCvSharp.Point>>();

           List<List<OpenCvSharp.Point>> poly_array1 = new List<List<OpenCvSharp.Point>>();

           poly_array0.Add(polya.pts);

           poly_array1.Add(polyb.pts);


           Mat _poly0 = Mat.Zeros(max_h, max_w, MatType.CV_8UC1);

           Mat _poly1 = Mat.Zeros(max_h, max_w, MatType.CV_8UC1);

           Mat _result = new Mat();


           List<List<OpenCvSharp.Point>> _pts0 = new List<List<OpenCvSharp.Point>>();

           List<int> _npts0 = new List<int>();


           foreach (var item in poly_array0)

           {

               if (item.Count < 3)//invalid poly

                   return -1f;


               _pts0.Add(item);

               _npts0.Add(item.Count);


           }


           List<List<OpenCvSharp.Point>> _pts1 = new List<List<OpenCvSharp.Point>>();

           List<int> _npts1 = new List<int>();


           foreach (var item in poly_array1)

           {

               if (item.Count < 3)//invalid poly

                   return -1f;


               _pts1.Add(item);

               _npts1.Add(item.Count);


           }


           Cv2.FillPoly(_poly0, _pts0, new Scalar(1));

           Cv2.FillPoly(_poly1, _pts1, new Scalar(1));


           Cv2.BitwiseAnd(_poly0, _poly1, _result);


           int _area0 = Cv2.CountNonZero(_poly0);

           int _area1 = Cv2.CountNonZero(_poly1);

           int _intersection_area = Cv2.CountNonZero(_result);

           float _iou = (float)_intersection_area / (float)(_area0 + _area1 - _intersection_area);

           return _iou;

       }


       void nms(List<BoxInfo> input_boxes, int max_w, int max_h)

       {

           input_boxes.Sort((a, b) => { return a.score > b.score ? -1 : 1; });


           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; }

                   float ovr = IoU(input_boxes[i], input_boxes[j], max_w, max_h);

                   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 < 3; 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[8]);

                           if (box_score > objThreshold)

                           {


                               Mat scores = outs[0].Row(row_ind).ColRange(9, 9 + 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)

                               {

                                   List<OpenCvSharp.Point> pts = new List<OpenCvSharp.Point>();

                                   for (int k = 0; k < 8; k += 2)

                                   {

                                       float x = (pdata[k] + j) * stride[n];  //x

                                       float y = (pdata[k + 1] + i) * stride[n];   //y

                                       x = (x - padw) * ratiow;

                                       y = (y - padh) * ratioh;

                                       pts.Add(new OpenCvSharp.Point(x, y));

                                   }


                                   Rect r = Cv2.BoundingRect(pts);


                                   generate_boxes.Add(new BoxInfo(pts, (float)max_class_socre, class_idx));

                               }

                           }

                           row_ind++;

                           pdata += nout;

                       }

                   }


               }


           }


           nms(generate_boxes, image.Cols, image.Rows);


           result_image = image.Clone();


           for (int ii = 0; ii < generate_boxes.Count; ++ii)

           {

               int idx = generate_boxes[ii].label;


               for (int jj = 0; jj < 4; jj++)

               {

                   Cv2.Line(result_image, generate_boxes[ii].pts[jj], generate_boxes[ii].pts[(jj + 1) % 4], new Scalar(0, 0, 255), 2);

               }


               string label = class_names[idx] + ":" + generate_boxes[ii].score.ToString("0.00");


               int xmin = (int)generate_boxes[ii].pts[0].X;

               int ymin = (int)generate_boxes[ii].pts[0].Y - 10;


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

       }

   }

}


   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, 6] {

                                              {31, 30, 28, 49, 50, 31},

                                              {46, 45, 58, 58, 74, 74},

                                              {94, 94, 115, 115, 151, 151}

                                              };

   

           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;

           }

   

           float IoU(BoxInfo polya, BoxInfo polyb, int max_w, int max_h)

           {

               List<List<OpenCvSharp.Point>> poly_array0 = new List<List<OpenCvSharp.Point>>();

               List<List<OpenCvSharp.Point>> poly_array1 = new List<List<OpenCvSharp.Point>>();

               poly_array0.Add(polya.pts);

               poly_array1.Add(polyb.pts);

   

               Mat _poly0 = Mat.Zeros(max_h, max_w, MatType.CV_8UC1);

               Mat _poly1 = Mat.Zeros(max_h, max_w, MatType.CV_8UC1);

               Mat _result = new Mat();

   

               List<List<OpenCvSharp.Point>> _pts0 = new List<List<OpenCvSharp.Point>>();

               List<int> _npts0 = new List<int>();

   

               foreach (var item in poly_array0)

               {

                   if (item.Count < 3)//invalid poly

                       return -1f;

   

                   _pts0.Add(item);

                   _npts0.Add(item.Count);

   

               }

   

               List<List<OpenCvSharp.Point>> _pts1 = new List<List<OpenCvSharp.Point>>();

               List<int> _npts1 = new List<int>();

   

               foreach (var item in poly_array1)

               {

                   if (item.Count < 3)//invalid poly

                       return -1f;

   

                   _pts1.Add(item);

                   _npts1.Add(item.Count);

   

               }

   

               Cv2.FillPoly(_poly0, _pts0, new Scalar(1));

               Cv2.FillPoly(_poly1, _pts1, new Scalar(1));

   

               Cv2.BitwiseAnd(_poly0, _poly1, _result);

   

               int _area0 = Cv2.CountNonZero(_poly0);

               int _area1 = Cv2.CountNonZero(_poly1);

               int _intersection_area = Cv2.CountNonZero(_result);

               float _iou = (float)_intersection_area / (float)(_area0 + _area1 - _intersection_area);

               return _iou;

           }

   

           void nms(List<BoxInfo> input_boxes, int max_w, int max_h)

           {

               input_boxes.Sort((a, b) => { return a.score > b.score ? -1 : 1; });

   

               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; }

                       float ovr = IoU(input_boxes[i], input_boxes[j], max_w, max_h);

                       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 < 3; 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[8]);

                               if (box_score > objThreshold)

                               {

   

                                   Mat scores = outs[0].Row(row_ind).ColRange(9, 9 + 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)

                                   {

                                       List<OpenCvSharp.Point> pts = new List<OpenCvSharp.Point>();

                                       for (int k = 0; k < 8; k += 2)

                                       {

                                           float x = (pdata[k] + j) * stride[n];  //x

                                           float y = (pdata[k + 1] + i) * stride[n];   //y

                                           x = (x - padw) * ratiow;

                                           y = (y - padh) * ratioh;

                                           pts.Add(new OpenCvSharp.Point(x, y));

                                       }

   

                                       Rect r = Cv2.BoundingRect(pts);

   

                                       generate_boxes.Add(new BoxInfo(pts, (float)max_class_socre, class_idx));

                                   }

                               }

                               row_ind++;

                               pdata += nout;

                           }

                       }

   

                   }

   

               }

   

               nms(generate_boxes, image.Cols, image.Rows);

   

               result_image = image.Clone();

   

               for (int ii = 0; ii < generate_boxes.Count; ++ii)

               {

                   int idx = generate_boxes[ii].label;

   

                   for (int jj = 0; jj < 4; jj++)

                   {

                       Cv2.Line(result_image, generate_boxes[ii].pts[jj], generate_boxes[ii].pts[(jj + 1) % 4], new Scalar(0, 0, 255), 2);

                   }

   

                   string label = class_names[idx] + ":" + generate_boxes[ii].score.ToString("0.00");

   

                   int xmin = (int)generate_boxes[ii].pts[0].X;

                   int ymin = (int)generate_boxes[ii].pts[0].Y - 10;

   

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

           }

       }

   }


下载


源码下载