C# yolov8 TensorRT Demo

效果

2e011828e0c8b27bbac9aff964adc988.png

说明

环境

NVIDIA GeForce RTX 4060 Laptop GPU

cuda12.1+cudnn 8.8.1+TensorRT-8.6.1.6

版本和我不一致的需要重新编译TensorRtExtern.dll,TensorRtExtern源码地址:

https://github.com/guojin-yan/TensorRT-CSharp-API/tree/TensorRtSharp2.0/src/TensorRtExtern

Windows版 CUDA安装参考:

https://blog.csdn.net/lw112190/article/details/137049845

项目

356f2dbe51792624a33d84d5f8e2ea83.png

代码

Form2.cs

using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using TensorRtSharp.Custom;
 
namespace yolov8_TensorRT_Demo
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }
 
        string imgFilter = "*.*|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png";
 
        YoloV8 yoloV8;
        Mat image;
 
        string image_path = "";
        string model_path;
 
        string video_path = "";
        string videoFilter = "*.mp4|*.mp4;";
        VideoCapture vcapture;
        VideoWriter vwriter;
        bool saveDetVideo = false;
 
 
        /// <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 = "";
 
            Application.DoEvents();
 
            image = new Mat(image_path);
 
            List<DetectionResult> detResults = yoloV8.Detect(image);
 
            //绘制结果
            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);
            }
 
            if (pictureBox2.Image != null)
            {
                pictureBox2.Image.Dispose();
            }
            pictureBox2.Image = new Bitmap(result_image.ToMemoryStream());
            textBox1.Text = yoloV8.DetectTime();
 
            button2.Enabled = true;
 
        }
 
        /// <summary>
        /// 窗体加载,初始化
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Load(object sender, EventArgs e)
        {
            image_path = "test/zidane.jpg";
            pictureBox1.Image = new Bitmap(image_path);
 
            model_path = "model/yolov8n.engine";
 
            if (!File.Exists(model_path))
            {
                //有点耗时,需等待
                Nvinfer.OnnxToEngine("model/yolov8n.onnx", 20);
            }
 
            yoloV8 = new YoloV8(model_path, "model/lable.txt");
 
        }
 
        /// <summary>
        /// 选择图片
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click_1(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = imgFilter;
            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 button4_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = videoFilter;
            ofd.InitialDirectory = Application.StartupPath + "\\test";
 
            if (ofd.ShowDialog() != DialogResult.OK) return;
 
            video_path = ofd.FileName;
 
            button3_Click(null, null);
 
        }
 
        /// <summary>
        /// 视频推理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click(object sender, EventArgs e)
        {
            if (video_path == null)
            {
                return;
            }
 
            textBox1.Text = "开始检测";
 
            Application.DoEvents();
 
            Thread thread = new Thread(new ThreadStart(VideoDetection));
 
            thread.Start();
            thread.Join();
 
            textBox1.Text = "检测完成!";
        }
 
        void VideoDetection()
        {
            vcapture = new VideoCapture(video_path);
            if (!vcapture.IsOpened())
            {
                MessageBox.Show("打开视频文件失败");
                return;
            }
 
            Mat frame = new Mat();
            List<DetectionResult> detResults;
 
            // 获取视频的fps
            double videoFps = vcapture.Get(VideoCaptureProperties.Fps);
            // 计算等待时间(毫秒)
            int delay = (int)(1000 / videoFps);
            Stopwatch _stopwatch = new Stopwatch();
 
            if (checkBox1.Checked)
            {
                vwriter = new VideoWriter("out.mp4", FourCC.X264, vcapture.Fps, new OpenCvSharp.Size(vcapture.FrameWidth, vcapture.FrameHeight));
                saveDetVideo = true;
            }
            else {
                saveDetVideo = false;
            }
 
            while (vcapture.Read(frame))
            {
                if (frame.Empty())
                {
                    MessageBox.Show("读取失败");
                    return;
                }
 
                _stopwatch.Restart();
 
                delay = (int)(1000 / videoFps);
 
                detResults = yoloV8.Detect(frame);
 
                //绘制结果
                foreach (DetectionResult r in detResults)
                {
                    Cv2.PutText(frame, $"{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(frame, r.Rect, Scalar.Red, thickness: 2);
                }
                Cv2.PutText(frame, "preprocessTime:" + yoloV8.preprocessTime.ToString("F2")+"ms", new OpenCvSharp.Point(10, 30), HersheyFonts.HersheySimplex, 1, Scalar.Red, 2);
                Cv2.PutText(frame, "inferTime:" + yoloV8.inferTime.ToString("F2") + "ms", new OpenCvSharp.Point(10, 70), HersheyFonts.HersheySimplex, 1, Scalar.Red, 2);
                Cv2.PutText(frame, "postprocessTime:" + yoloV8.postprocessTime.ToString("F2") + "ms", new OpenCvSharp.Point(10, 110), HersheyFonts.HersheySimplex, 1, Scalar.Red, 2);
                Cv2.PutText(frame, "totalTime:" + yoloV8.totalTime.ToString("F2") + "ms", new OpenCvSharp.Point(10, 150), HersheyFonts.HersheySimplex, 1, Scalar.Red, 2);
                Cv2.PutText(frame, "video fps:" + videoFps.ToString("F2"), new OpenCvSharp.Point(10, 190), HersheyFonts.HersheySimplex, 1, Scalar.Red, 2);
                Cv2.PutText(frame, "det fps:" + yoloV8.detFps.ToString("F2"), new OpenCvSharp.Point(10, 230), HersheyFonts.HersheySimplex, 1, Scalar.Red, 2);
 
                if (saveDetVideo)
                {
                    vwriter.Write(frame);
                }
 
                Cv2.ImShow("DetectionResult", frame);
 
                // for test
                // delay = 1;
 
                delay = (int)(delay - _stopwatch.ElapsedMilliseconds);
                if (delay <= 0)
                {
                    delay = 1;
                }
                //Console.WriteLine("delay:" + delay.ToString()) ;
                if (Cv2.WaitKey(delay) == 27)
                {
                    break; // 如果按下ESC,退出循环
                }
            }
 
            Cv2.DestroyAllWindows();
            vcapture.Release();
            if (saveDetVideo)
            {
                vwriter.Release();
            }
 
        }
    }
 
}

YoloV8.cs

using OpenCvSharp;
using OpenCvSharp.Dnn;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using TensorRtSharp.Custom;
 
namespace yolov8_TensorRT_Demo
{
    public class YoloV8
    {
 
        float[] input_tensor_data;
        float[] outputData;
        List<DetectionResult> detectionResults;
 
        int input_height;
        int input_width;
 
        Nvinfer predictor;
 
        string[] class_names;
        int class_num;
        int box_num;
 
        float conf_threshold;
        float nms_threshold;
 
        float ratio_height;
        float ratio_width;
 
        public double preprocessTime;
        public double inferTime;
        public double postprocessTime;
        public double totalTime;
        public double detFps;
 
        public String DetectTime()
        {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.AppendLine($"Preprocess: {preprocessTime:F2}ms");
            stringBuilder.AppendLine($"Infer: {inferTime:F2}ms");
            stringBuilder.AppendLine($"Postprocess: {postprocessTime:F2}ms");
            stringBuilder.AppendLine($"Total: {totalTime:F2}ms");
 
            return stringBuilder.ToString();
        }
 
        public YoloV8(string model_path, string classer_path)
        {
            predictor = new Nvinfer(model_path);
 
            class_names = File.ReadAllLines(classer_path, Encoding.UTF8);
            class_num = class_names.Length;
 
            input_height = 640;
            input_width = 640;
 
            box_num = 8400;
 
            conf_threshold = 0.25f;
            nms_threshold = 0.5f;
 
            detectionResults = new List<DetectionResult>();
        }
 
        void Preprocess(Mat image)
        {
            //图片缩放
            int height = image.Rows;
            int width = image.Cols;
            Mat temp_image = image.Clone();
            if (height > input_height || width > input_width)
            {
                float scale = Math.Min((float)input_height / height, (float)input_width / width);
                OpenCvSharp.Size new_size = new OpenCvSharp.Size((int)(width * scale), (int)(height * scale));
                Cv2.Resize(image, temp_image, new_size);
            }
            ratio_height = (float)height / temp_image.Rows;
            ratio_width = (float)width / temp_image.Cols;
            Mat input_img = new Mat();
            Cv2.CopyMakeBorder(temp_image, input_img, 0, input_height - temp_image.Rows, 0, input_width - temp_image.Cols, BorderTypes.Constant, 0);
 
            //归一化
            input_img.ConvertTo(input_img, MatType.CV_32FC3, 1.0 / 255);
 
            input_tensor_data = Common.ExtractMat(input_img);
 
            input_img.Dispose();
            temp_image.Dispose();
        }
 
        void Postprocess(float[] outputData)
        {
            detectionResults.Clear();
 
            float[] data = Common.Transpose(outputData, class_num + 4, 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 _centerX = (int)(rectData[0] * ratio_width);
                int _centerY = (int)(rectData[1] * ratio_height);
                int _width = (int)(rectData[2] * ratio_width);
                int _height = (int)(rectData[3] * ratio_height);
 
                detResults.Add(new DetectionResult(
                   maxIndex,
                   class_names[maxIndex],
                   new Rect(_centerX - _width / 2, _centerY - _height / 2, _width, _height),
                   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();
 
            detectionResults = detResults;
        }
 
        internal List<DetectionResult> Detect(Mat image)
        {
 
            var t1 = Cv2.GetTickCount();
 
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
 
            Preprocess(image);
 
            preprocessTime = stopwatch.Elapsed.TotalMilliseconds;
            stopwatch.Restart();
 
            predictor.LoadInferenceData("images", input_tensor_data);
 
            predictor.infer();
 
            inferTime = stopwatch.Elapsed.TotalMilliseconds;
            stopwatch.Restart();
 
            outputData = predictor.GetInferenceResult("output0");
 
            Postprocess(outputData);
 
            postprocessTime = stopwatch.Elapsed.TotalMilliseconds;
            stopwatch.Stop();
 
            totalTime = preprocessTime + inferTime + postprocessTime;
 
            detFps = (double)stopwatch.Elapsed.TotalSeconds / (double)stopwatch.Elapsed.Ticks;
 
            var t2 = Cv2.GetTickCount();
 
            detFps = 1 / ((t2 - t1) / Cv2.GetTickFrequency());
 
            return detectionResults;
 
        }
 
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值