C# OpenCvSharp DNN Yolov8-OBB 旋转目标检测

目录

效果

模型信息

项目

代码

下载


C# OpenCvSharp DNN Yolov8-OBB 旋转目标检测

效果

模型信息

Model Properties


date:2024-02-26T08:38:44.171849

description:Ultralytics YOLOv8s-obb model trained on runs/DOTAv1.0-ms.yaml

author:Ultralytics

task:obb

license:AGPL-3.0 https://ultralytics.com/license

version:8.1.18

stride:32

batch:1

imgsz:[640, 640]

names:{0: 'plane', 1: 'ship', 2: 'storage tank', 3: 'baseball diamond', 4: 'tennis court', 5: 'basketball court', 6: 'ground track field', 7: 'harbor', 8: 'bridge', 9: 'large vehicle', 10: 'small vehicle', 11: 'helicopter', 12: 'roundabout', 13: 'soccer ball field', 14: 'swimming pool'}


Inputs


name:images

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


Outputs


name:output0

tensor:Float[1, 20, 8400]


项目

代码

using OpenCvSharp;

using OpenCvSharp.Dnn;

using System;

using System.Collections.Generic;

using System.Drawing;

using System.IO;

using System.Linq;

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;

string modelpath;

string classer_path;

List<string> class_names;

Net opencv_net;

Mat BN_image;

Mat image;

Mat result_image;

string[] class_lables;

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)

{

modelpath = "model/yolov8s-obb.onnx";

classer_path = "model/lable.txt";

opencv_net = CvDnn.ReadNetFromOnnx(modelpath);

List<string> str = new List<string>();

StreamReader sr = new StreamReader(classer_path);

string line;

while ((line = sr.ReadLine()) != null)

{

str.Add(line);

}

class_lables = str.ToArray();

image_path = "test_img/1.png";

pictureBox1.Image = new Bitmap(image_path);

}

private void button2_Click(object sender, EventArgs e)

{

if (image_path == "")

{

return;

}

textBox1.Text = "检测中,请稍等......";

pictureBox2.Image = null;

button2.Enabled = false;

Application.DoEvents();

image = new Mat(image_path);

//图片缩放

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

float[] result_array;

float factor = (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));

BN_image = CvDnn.BlobFromImage(resize_image, 1 / 255.0, new OpenCvSharp.Size(640, 640), new Scalar(0, 0, 0), true, false);

//配置图片输入数据

opencv_net.SetInput(BN_image);

//模型推理,读取推理结果

Mat[] outs = new Mat[1] { 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);

}

Mat result_data = new Mat(20, 8400, MatType.CV_32F);

result_data = outs[0].T();

List<Rect2d> position_boxes = new List<Rect2d>();

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

List<float> confidences = new List<float>();

List<float> rotations = new List<float>();

// Preprocessing output results

for (int i = 0; i < result_data.Rows; i++)

{

Mat classes_scores = new Mat(result_data, new Rect(4, i, 15, 1));

OpenCvSharp.Point max_classId_point, min_classId_point;

double max_score, min_score;

// Obtain the maximum value and its position in a set of data

Cv2.MinMaxLoc(classes_scores, out min_score, out max_score,

out min_classId_point, out max_classId_point);

// Confidence level between 0 ~ 1

// Obtain identification box information

if (max_score > 0.25)

{

float cx = result_data.At<float>(i, 0);

float cy = result_data.At<float>(i, 1);

float ow = result_data.At<float>(i, 2);

float oh = result_data.At<float>(i, 3);

double x = (cx - 0.5 * ow) * factor;

double y = (cy - 0.5 * oh) * factor;

double width = ow * factor;

double height = oh * factor;

Rect2d box = new Rect2d();

box.X = x;

box.Y = y;

box.Width = width;

box.Height = height;

position_boxes.Add(box);

class_ids.Add(max_classId_point.X);

confidences.Add((float)max_score);

rotations.Add(result_data.At<float>(i, 19));

}

}

// NMS

int[] indexes = new int[position_boxes.Count];

CvDnn.NMSBoxes(position_boxes, confidences, 0.25f, 0.7f, out indexes);

List<RotatedRect> rotated_rects = new List<RotatedRect>();

for (int i = 0; i < indexes.Length; i++)

{

int index = indexes[i];

float w = (float)position_boxes[index].Width;

float h = (float)position_boxes[index].Height;

float x = (float)position_boxes[index].X + w / 2;

float y = (float)position_boxes[index].Y + h / 2;

float r = rotations[index];

float w_ = w > h ? w : h;

float h_ = w > h ? h : w;

r = (float)((w > h ? r : (float)(r + Math.PI / 2)) % Math.PI);

RotatedRect rotate = new RotatedRect(new Point2f(x, y), new Size2f(w_, h_), (float)(r * 180.0 / Math.PI));

rotated_rects.Add(rotate);

}

result_image = image.Clone();

for (int i = 0; i < indexes.Length; i++)

{

int index = indexes[i];

Point2f[] points = rotated_rects[i].Points();

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

{

Cv2.Line(result_image, (OpenCvSharp.Point)points[j], (OpenCvSharp.Point)points[(j + 1) % 4], new Scalar(0, 255, 0), 2);

}

Cv2.PutText(result_image, class_lables[class_ids[index]] + "-" + confidences[index].ToString("0.00"),

(OpenCvSharp.Point)points[0], HersheyFonts.HersheySimplex, 0.8, new Scalar(0, 0, 255), 2);

}

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

textBox1.Text = "推理耗时:" + (dt2 - dt1).TotalMilliseconds + "ms";

button2.Enabled = true;

}

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

        string modelpath;
        string classer_path;

        List<string> class_names;

        Net opencv_net;
        Mat BN_image;

        Mat image;
        Mat result_image;

        string[] class_lables;

        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)
        {
            modelpath = "model/yolov8s-obb.onnx";
            classer_path = "model/lable.txt";

            opencv_net = CvDnn.ReadNetFromOnnx(modelpath);

            List<string> str = new List<string>();
            StreamReader sr = new StreamReader(classer_path);
            string line;
            while ((line = sr.ReadLine()) != null)
            {
                str.Add(line);
            }
            class_lables = str.ToArray();

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

        }

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

            image = new Mat(image_path);

            //图片缩放
            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));

            float[] result_array;
            float factor = (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));

            BN_image = CvDnn.BlobFromImage(resize_image, 1 / 255.0, new OpenCvSharp.Size(640, 640), new Scalar(0, 0, 0), true, false);

            //配置图片输入数据
            opencv_net.SetInput(BN_image);

            //模型推理,读取推理结果
            Mat[] outs = new Mat[1] { 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);
            }

            Mat result_data = new Mat(20, 8400, MatType.CV_32F);
            result_data = outs[0].T();
            List<Rect2d> position_boxes = new List<Rect2d>();
            List<int> class_ids = new List<int>();
            List<float> confidences = new List<float>();
            List<float> rotations = new List<float>();
            // Preprocessing output results
            for (int i = 0; i < result_data.Rows; i++)
            {
                Mat classes_scores = new Mat(result_data, new Rect(4, i, 15, 1));
                OpenCvSharp.Point max_classId_point, min_classId_point;
                double max_score, min_score;
                // Obtain the maximum value and its position in a set of data
                Cv2.MinMaxLoc(classes_scores, out min_score, out max_score,
                    out min_classId_point, out max_classId_point);
                // Confidence level between 0 ~ 1
                // Obtain identification box information
                if (max_score > 0.25)
                {
                    float cx = result_data.At<float>(i, 0);
                    float cy = result_data.At<float>(i, 1);
                    float ow = result_data.At<float>(i, 2);
                    float oh = result_data.At<float>(i, 3);
                    double x = (cx - 0.5 * ow) * factor;
                    double y = (cy - 0.5 * oh) * factor;
                    double width = ow * factor;
                    double height = oh * factor;
                    Rect2d box = new Rect2d();
                    box.X = x;
                    box.Y = y;
                    box.Width = width;
                    box.Height = height;
                    position_boxes.Add(box);
                    class_ids.Add(max_classId_point.X);
                    confidences.Add((float)max_score);
                    rotations.Add(result_data.At<float>(i, 19));
                }
            }

            // NMS 
            int[] indexes = new int[position_boxes.Count];
            CvDnn.NMSBoxes(position_boxes, confidences, 0.25f, 0.7f, out indexes);
            List<RotatedRect> rotated_rects = new List<RotatedRect>();
            for (int i = 0; i < indexes.Length; i++)
            {
                int index = indexes[i];
                float w = (float)position_boxes[index].Width;
                float h = (float)position_boxes[index].Height;
                float x = (float)position_boxes[index].X + w / 2;
                float y = (float)position_boxes[index].Y + h / 2;
                float r = rotations[index];
                float w_ = w > h ? w : h;
                float h_ = w > h ? h : w;
                r = (float)((w > h ? r : (float)(r + Math.PI / 2)) % Math.PI);
                RotatedRect rotate = new RotatedRect(new Point2f(x, y), new Size2f(w_, h_), (float)(r * 180.0 / Math.PI));
                rotated_rects.Add(rotate);
            }

            result_image = image.Clone();

            for (int i = 0; i < indexes.Length; i++)
            {
                int index = indexes[i];
                Point2f[] points = rotated_rects[i].Points();

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

                Cv2.PutText(result_image, class_lables[class_ids[index]] + "-" + confidences[index].ToString("0.00"),
                    (OpenCvSharp.Point)points[0], HersheyFonts.HersheySimplex, 0.8, new Scalar(0, 0, 255), 2);
            }

            pictureBox2.Image = new Bitmap(result_image.ToMemoryStream());
            textBox1.Text = "推理耗时:" + (dt2 - dt1).TotalMilliseconds + "ms";

            button2.Enabled = true;
        }

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

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

下载

源码下载

相关推荐
四口鲸鱼爱吃盐2 分钟前
Pytorch | 利用SMI-FGRM针对CIFAR10上的ResNet分类器进行对抗攻击
人工智能·pytorch·python·深度学习·机器学习·计算机视觉
云天徽上9 分钟前
【机器学习案列】车牌自动识别系统:基于YOLO11的高效实现
人工智能·机器学习
monstercl16 分钟前
【C#】元组
开发语言·c#
DashVector18 分钟前
如何通过HTTP API插入Doc
数据库·人工智能·http·阿里云·向量检索
顾道长生'1 小时前
(NIPS-2024)PISSA:大型语言模型的主奇异值和奇异向量适配
人工智能·语言模型·自然语言处理
语音之家1 小时前
CultureLLM 与 CulturePark:增强大语言模型对多元文化的理解
人工智能·语言模型·自然语言处理
Tasfa1 小时前
【AI系列】从零开始学习大模型GPT (1)- Build a Large Language Model (From Scratch)
人工智能·gpt·学习
一个处女座的程序猿1 小时前
LLMs之o3:《Deliberative Alignment: Reasoning Enables Safer Language Models》翻译与解读
人工智能·深度学习·机器学习
奔跑的犀牛先生1 小时前
C#学习1:初接触,C#的一些基础,和相关报错
开发语言·c#
静静AI学堂1 小时前
动态头部:利用注意力机制统一目标检测头部
人工智能·目标检测·计算机视觉