C# yolov8 TensorRT +ByteTrack Demo

C# yolov8 TensorRT +ByteTrack ?Demo

目錄

效果

說明?

項目

代碼

Form2.cs

YoloV8.cs

ByteTracker.cs

下載

參考?


效果

說明?

環境

NVIDIA GeForce RTX 4060 Laptop GPU

cuda12.1+cudnn 8.8.1+TensorRT-8.6.1.6

版本和我不一致的需要重新編譯TensorRtExtern.dll,TensorRtExtern源碼地址:TensorRT-CSharp-API/src/TensorRtExtern at TensorRtSharp2.0 · guojin-yan/TensorRT-CSharp-API · GitHub

Windows版 CUDA安裝參考:Windows版 CUDA安裝_win cuda安裝-CSDN博客

項目

?

代碼

Form2.cs

using ByteTrack;
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;
? ? ? ? ByteTracker tracker;


? ? ? ? /// <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/dog.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;

? ? ? ? ? ? textBox1.Text = "";
? ? ? ? ? ? pictureBox1.Image = null;
? ? ? ? ? ? pictureBox2.Image = null;

? ? ? ? ? ? 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 == "")
? ? ? ? ? ? {
? ? ? ? ? ? ? ? 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;
? ? ? ? ? ? }

? ? ? ? ? ? tracker = new ByteTracker((int)vcapture.Fps, 200);

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

? ? ? ? ? ? ? ? List<Track> track = new List<Track>();
? ? ? ? ? ? ? ? Track temp;
? ? ? ? ? ? ? ? foreach (DetectionResult r in detResults)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? RectBox _box = new RectBox(r.Rect.X, r.Rect.Y, r.Rect.Width, r.Rect.Height);
? ? ? ? ? ? ? ? ? ? temp = new Track(_box, r.Confidence, ("label", r.ClassId), ("name", r.Class));
? ? ? ? ? ? ? ? ? ? track.Add(temp);
? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? var trackOutputs = tracker.Update(track);

? ? ? ? ? ? ? ? foreach (var t in trackOutputs)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? Rect rect = new Rect((int)t.RectBox.X, (int)t.RectBox.Y, (int)t.RectBox.Width, (int)t.RectBox.Height);
? ? ? ? ? ? ? ? ? ? //string txt = $"{t["name"]}-{t.TrackId}:{t.Score:P0}";
? ? ? ? ? ? ? ? ? ? string txt = $"{t["name"]}-{t.TrackId}";
? ? ? ? ? ? ? ? ? ? Cv2.PutText(frame, txt, new OpenCvSharp.Point(rect.TopLeft.X, rect.TopLeft.Y - 10), HersheyFonts.HersheySimplex, 1, Scalar.Red, 2);
? ? ? ? ? ? ? ? ? ? Cv2.Rectangle(frame, rect, Scalar.Red, thickness: 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();
? ? ? ? ? ? }

? ? ? ? }

? ? }

}

using ByteTrack;
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;ByteTracker tracker;/// <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/dog.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;textBox1.Text = "";pictureBox1.Image = null;pictureBox2.Image = null;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 == ""){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;}tracker = new ByteTracker((int)vcapture.Fps, 200);Mat frame = new Mat();List<DetectionResult> detResults;// 獲取視頻的fpsdouble 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);List<Track> track = new List<Track>();Track temp;foreach (DetectionResult r in detResults){RectBox _box = new RectBox(r.Rect.X, r.Rect.Y, r.Rect.Width, r.Rect.Height);temp = new Track(_box, r.Confidence, ("label", r.ClassId), ("name", r.Class));track.Add(temp);}var trackOutputs = tracker.Update(track);foreach (var t in trackOutputs){Rect rect = new Rect((int)t.RectBox.X, (int)t.RectBox.Y, (int)t.RectBox.Width, (int)t.RectBox.Height);//string txt = $"{t["name"]}-{t.TrackId}:{t.Score:P0}";string txt = $"{t["name"]}-{t.TrackId}";Cv2.PutText(frame, txt, new OpenCvSharp.Point(rect.TopLeft.X, rect.TopLeft.Y - 10), HersheyFonts.HersheySimplex, 1, Scalar.Red, 2);Cv2.Rectangle(frame, rect, Scalar.Red, thickness: 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;public 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));}//NMSCvDnn.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;}}
}

ByteTracker.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace ByteTrack
{public class ByteTracker{readonly float _trackThresh;readonly float _highThresh;readonly float _matchThresh;readonly int _maxTimeLost;int _frameId = 0;int _trackIdCount = 0;readonly List<Track> _trackedTracks = new List<Track>(100);readonly List<Track> _lostTracks = new List<Track>(100);List<Track> _removedTracks = new List<Track>(100);public ByteTracker(int frameRate = 30, int trackBuffer = 30, float trackThresh = 0.5f, float highThresh = 0.6f, float matchThresh = 0.8f){_trackThresh = trackThresh;_highThresh = highThresh;_matchThresh = matchThresh;_maxTimeLost = (int)(frameRate / 30.0 * trackBuffer);}/// <summary>/// /// </summary>/// <param name="objects"></param>/// <returns></returns>public IList<Track> Update(List<Track> tracks){#region Step 1: Get detections _frameId++;// Create new Tracks using the result of object detectionList<Track> detTracks = new List<Track>();List<Track> detLowTracks = new List<Track>();foreach (var obj in tracks){if (obj.Score >= _trackThresh){detTracks.Add(obj);}else{detLowTracks.Add(obj);}}// Create lists of existing STrackList<Track> activeTracks = new List<Track>();List<Track> nonActiveTracks = new List<Track>();foreach (var trackedTrack in _trackedTracks){if (!trackedTrack.IsActivated){nonActiveTracks.Add(trackedTrack);}else{activeTracks.Add(trackedTrack);}}var trackPool = activeTracks.Union(_lostTracks).ToArray();// Predict current pose by KFforeach (var track in trackPool){track.Predict();}#endregion#region Step 2: First association, with IoU List<Track> currentTrackedTracks = new List<Track>();Track[] remainTrackedTracks;Track[] remainDetTracks;List<Track> refindTracks = new List<Track>();{var dists = CalcIouDistance(trackPool, detTracks);LinearAssignment(dists, trackPool.Length, detTracks.Count, _matchThresh,out var matchesIdx,out var unmatchTrackIdx,out var unmatchDetectionIdx);foreach (var matchIdx in matchesIdx){var track = trackPool[matchIdx[0]];var det = detTracks[matchIdx[1]];if (track.State == TrackState.Tracked){track.Update(det, _frameId);currentTrackedTracks.Add(track);}else{track.ReActivate(det, _frameId);refindTracks.Add(track);}}remainDetTracks = unmatchDetectionIdx.Select(unmatchIdx => detTracks[unmatchIdx]).ToArray();remainTrackedTracks = unmatchTrackIdx.Where(unmatchIdx => trackPool[unmatchIdx].State == TrackState.Tracked).Select(unmatchIdx => trackPool[unmatchIdx]).ToArray();}#endregion#region Step 3: Second association, using low score dets List<Track> currentLostTracks = new List<Track>();{var dists = CalcIouDistance(remainTrackedTracks, detLowTracks);LinearAssignment(dists, remainTrackedTracks.Length, detLowTracks.Count, 0.5f,out var matchesIdx,out var unmatchTrackIdx,out var unmatchDetectionIdx);foreach (var matchIdx in matchesIdx){var track = remainTrackedTracks[matchIdx[0]];var det = detLowTracks[matchIdx[1]];if (track.State == TrackState.Tracked){track.Update(det, _frameId);currentTrackedTracks.Add(track);}else{track.ReActivate(det, _frameId);refindTracks.Add(track);}}foreach (var unmatchTrack in unmatchTrackIdx){var track = remainTrackedTracks[unmatchTrack];if (track.State != TrackState.Lost){track.MarkAsLost();currentLostTracks.Add(track);}}}#endregion#region Step 4: Init new tracks List<Track> currentRemovedTracks = new List<Track>();{// Deal with unconfirmed tracks, usually tracks with only one beginning framevar dists = CalcIouDistance(nonActiveTracks, remainDetTracks);LinearAssignment(dists, nonActiveTracks.Count, remainDetTracks.Length, 0.7f,out var matchesIdx,out var unmatchUnconfirmedIdx,out var unmatchDetectionIdx);foreach (var matchIdx in matchesIdx){nonActiveTracks[matchIdx[0]].Update(remainDetTracks[matchIdx[1]], _frameId);currentTrackedTracks.Add(nonActiveTracks[matchIdx[0]]);}foreach (var unmatchIdx in unmatchUnconfirmedIdx){var track = nonActiveTracks[unmatchIdx];track.MarkAsRemoved();currentRemovedTracks.Add(track);}// Add new stracksforeach (var unmatchIdx in unmatchDetectionIdx){var track = remainDetTracks[unmatchIdx];if (track.Score < _highThresh)continue;_trackIdCount++;track.Activate(_frameId, _trackIdCount);currentTrackedTracks.Add(track);}}#endregion#region Step 5: Update stateforeach (var lostTrack in _lostTracks){if (_frameId - lostTrack.FrameId > _maxTimeLost){lostTrack.MarkAsRemoved();currentRemovedTracks.Add(lostTrack);}}var trackedTracks = currentTrackedTracks.Union(refindTracks).ToArray();var lostTracks = _lostTracks.Except(trackedTracks).Union(currentLostTracks).Except(_removedTracks).ToArray();_removedTracks = _removedTracks.Union(currentRemovedTracks).ToList();RemoveDuplicateStracks(trackedTracks, lostTracks);#endregionreturn _trackedTracks.Where(track => track.IsActivated).ToArray();}/// <summary>/// /// </summary>/// <param name="aTracks"></param>/// <param name="bTracks"></param>/// <param name="aResults"></param>/// <param name="bResults"></param>void RemoveDuplicateStracks(IList<Track> aTracks, IList<Track> bTracks){_trackedTracks.Clear();_lostTracks.Clear();List<(int, int)> overlappingCombinations;var ious = CalcIouDistance(aTracks, bTracks);if (ious is null)overlappingCombinations = new List<(int, int)>();else{var rows = ious.GetLength(0);var cols = ious.GetLength(1);overlappingCombinations = new List<(int, int)>(rows * cols / 2);for (var i = 0; i < rows; i++)for (var j = 0; j < cols; j++)if (ious[i, j] < 0.15f)overlappingCombinations.Add((i, j));}var aOverlapping = aTracks.Select(x => false).ToArray();var bOverlapping = bTracks.Select(x => false).ToArray();foreach (var (aIdx, bIdx) in overlappingCombinations){var timep = aTracks[aIdx].FrameId - aTracks[aIdx].StartFrameId;var timeq = bTracks[bIdx].FrameId - bTracks[bIdx].StartFrameId;if (timep > timeq)bOverlapping[bIdx] = true;elseaOverlapping[aIdx] = true;}for (var ai = 0; ai < aTracks.Count; ai++)if (!aOverlapping[ai])_trackedTracks.Add(aTracks[ai]);for (var bi = 0; bi < bTracks.Count; bi++)if (!bOverlapping[bi])_lostTracks.Add(bTracks[bi]);}/// <summary>/// /// </summary>/// <param name="costMatrix"></param>/// <param name="costMatrixSize"></param>/// <param name="costMatrixSizeSize"></param>/// <param name="thresh"></param>/// <param name="matches"></param>/// <param name="aUnmatched"></param>/// <param name="bUnmatched"></param>void LinearAssignment(float[,] costMatrix, int costMatrixSize, int costMatrixSizeSize, float thresh, out IList<int[]> matches, out IList<int> aUnmatched, out IList<int> bUnmatched){matches = new List<int[]>();if (costMatrix is null){aUnmatched = Enumerable.Range(0, costMatrixSize).ToArray();bUnmatched = Enumerable.Range(0, costMatrixSizeSize).ToArray();return;}bUnmatched = new List<int>();aUnmatched = new List<int>();var (rowsol, colsol) = Lapjv.Exec(costMatrix, true, thresh);for (var i = 0; i < rowsol.Length; i++){if (rowsol[i] >= 0)matches.Add(new int[] { i, rowsol[i] });elseaUnmatched.Add(i);}for (var i = 0; i < colsol.Length; i++)if (colsol[i] < 0)bUnmatched.Add(i);}/// <summary>/// /// </summary>/// <param name="aRects"></param>/// <param name="bRects"></param>/// <returns></returns>static float[,] CalcIous(IList<RectBox> aRects, IList<RectBox> bRects){if (aRects.Count * bRects.Count == 0) return null;var ious = new float[aRects.Count, bRects.Count];for (var bi = 0; bi < bRects.Count; bi++)for (var ai = 0; ai < aRects.Count; ai++)ious[ai, bi] = bRects[bi].CalcIoU(aRects[ai]);return ious;}/// <summary>/// /// </summary>/// <param name="aTtracks"></param>/// <param name="bTracks"></param>/// <returns></returns>static float[,] CalcIouDistance(IEnumerable<Track> aTtracks, IEnumerable<Track> bTracks){var aRects = aTtracks.Select(x => x.RectBox).ToArray();var bRects = bTracks.Select(x => x.RectBox).ToArray();var ious = CalcIous(aRects, bRects);if (ious is null) return null;var rows = ious.GetLength(0);var cols = ious.GetLength(1);var matrix = new float[rows, cols];for (var i = 0; i < rows; i++)for (var j = 0; j < cols; j++)matrix[i, j] = 1 - ious[i, j];return matrix;}}
}

下載

源碼下載

參考?

https://github.com/devhxj/Yolo8-ByteTrack-CSharp

https://github.com/guojin-yan/TensorRT-CSharp-API

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/20250.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/20250.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/20250.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

微調醫療大模型,與通用大模型效果對比

下面是一份CT描述&#xff1a; “肝臟大小、形態未見明確異常。肝S2見一結節狀低密度影&#xff0c;大小約13x11mm&#xff0c;增強掃描呈明顯漸進性強化&#xff0c;延遲期呈等密度。余肝實質內未見異常密度影或強化灶。肝內大血管及其分支走行未見異常&#xff0c;肝門區層次…

ip地址告訴別人安全嗎?ip地址告訴別人會有什么風險

IP地址告訴別人安全嗎&#xff1f;在數字化時代&#xff0c;IP地址作為網絡連接的關鍵標識符&#xff0c;承載著重要的安全意義。然而&#xff0c;很多人可能并不清楚&#xff0c;輕易地將自己的IP地址告訴他人可能帶來一系列安全風險。那么&#xff0c;IP地址告訴別人會有什么…

文件夾損壞0字節:全面解析、恢復技巧與預防策略

在數字時代&#xff0c;數據的完整性和安全性至關重要。然而&#xff0c;我們時常會遭遇文件夾損壞并顯示為0字節的棘手問題。這種情況一旦發生&#xff0c;用戶可能會面臨數據丟失的風險。本文將詳細探討文件夾損壞0字節的現象&#xff0c;分析其背后的原因&#xff0c;并提供…

Redis-重定向

實驗環境&#xff08;3主3從的Redis-Cluster&#xff09; 一、Redis重定向基礎篇 1、MOVED重定向 Redis Custer 中&#xff0c;客戶端可以向集群中任意節點發送請求。此時當前節點先對 Key 進行 CRC 16 計算&#xff0c;然后按 16384 取模確定 Slot 槽。確定該 Slot 槽所對應的…

為什么使用短鏈系統?

短鏈接&#xff08;Short Link&#xff09;是指將一個原始的長 URL&#xff08;Uniform Resource Locator&#xff09;通過特定的算法或服務轉化為一個更短、易于記憶的 URL。短鏈接通常只包含幾個字符&#xff0c;而原始的長 URL 可能會非常長。 短鏈接的原理非常簡單&#x…

FPGA編程與PLC編程的區別:深入解析與對比

FPGA編程與PLC編程的區別&#xff1a;深入解析與對比 在工業自動化和控制系統領域&#xff0c;FPGA&#xff08;現場可編程門陣列&#xff09;編程和PLC&#xff08;可編程邏輯控制器&#xff09;編程都是關鍵的編程技術&#xff0c;但它們在應用、功能、結構和編程方法上存在…

IEEE編程語言排行榜:深度解析編程語言的四大維度、五大趨勢、六大熱門與七大挑戰

IEEE編程語言排行榜&#xff1a;深度解析編程語言的四大維度、五大趨勢、六大熱門與七大挑戰 在信息技術領域&#xff0c;編程語言排行榜一直是衡量各種編程語言流行度和影響力的重要指標。IEEE&#xff08;電氣電子工程師協會&#xff09;作為全球最具影響力的科技專業組織之…

【Java數據結構】詳解LinkedList與鏈表(二)

目錄 1.????前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; 2.反轉一個單鏈表 3. 找到鏈表的中間節點 4.輸入一個鏈表&#xff0c;輸出該鏈表中倒數第k個結點。 5.合并兩個有序鏈表 6.鏈表分割 7. 判定鏈表的回文結構 8.輸入兩個鏈表&#xff0c;找…

棧與隊列練習題(2024/5/31)

1有效的括號 給定一個只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判斷字符串是否有效。 有效字符串需滿足&#xff1a; 左括號必須用相同類型的右括號閉合。左括號必須以正確的順序閉合。每個右括號都有一個對應的…

云服務和云備份的區別是什么?

隨著云計算的興起&#xff0c;云備份與云服務被越來越多的企業和個人所關注&#xff0c;在云計算中云服務與云備份之間還是有一定的區別的&#xff0c;本文就來介紹一下云服務和云備份之間的區別。 云服務和云備份主要的區別在備份對象、推薦場景和數據一致性等方面。 備份對象…

打印機的ip不同且連不上

打印機的ip不同且連不上 1.問題分析2.修改網段3.驗證網絡 1.問題分析 主要是打印機的網段和電腦不在同一個網段 2.修改網段 3.驗證網絡

Web前端三大主流框:React、Vue 和 Angular

在當今快速發展的 Web 開發領域&#xff0c;選擇合適的前端框架對于項目的成功至關重要。React、Vue 和 Angular 作為三大主流前端框架&#xff0c;憑借其強大的功能和靈活的特性&#xff0c;贏得了眾多開發者的青睞。本文將對這三大框架進行解析&#xff0c;幫助開發者了解它們…

dubbo復習:(12)服務器端的異步和客戶端的異步調用

一、服務器端接口的定義和實現&#xff1a; package cn.edu.tju.service;import java.util.concurrent.CompletableFuture;public interface AsyncService {/*** 同步調用方法*/String invoke(String param);/*** 異步調用方法*/CompletableFuture<String> asyncInvoke(…

C/C++學習筆記 C讀取文本文件

1、簡述 要讀取文本文件&#xff0c;需要按照以下步驟操作&#xff1a; 首先&#xff0c;使用該函數打開文本文件fopen()。其次&#xff0c;使用fgets()或fgetc()函數從文件中讀取文本。第三&#xff0c;使用函數關閉文件fclose()。 2、每次從文件中讀取一個字符 要從文本文…

整理一下win7系統java、python等各個可安裝版本

最近使用win7系統&#xff0c;遇到了很多版本不兼容的問題&#xff0c;把我現在安裝好的可使用的分享給大家 jdk 1.8 maven-3.9.6 centos 7 python 3.7.4 docker DockerToolbox-18.01.0-ce win10是直接一個docker軟件&#xff0c;win7要安裝這三個 datagrip-2020.2.3 d…

2.1Docker安裝MySQL8.0

2.1 Docker安裝MySQL8.0 1.拉取MySQL docker pull mysql:latest如&#xff1a;拉取MySQL8.0.33版本 docker pull mysql:8.0.332. 啟動鏡像 docker run -p 3307:3306 --name mysql8 -e MYSQL_ROOT_PASSWORDHgh75667% -d mysql:8.0.33-p 3307:3306 把mysql默認的3306端口映射…

CentOs-7.5 root密碼忘記了,如何重置密碼?

VWmare軟件版本&#xff1a;VMware Workstation 16 Pro Centos系統版本&#xff1a;CentOS-7.5-x86 64-Minimal-1804 文章目錄 問題描述如何解決&#xff1f; 問題描述 長時間沒有使用Linux系統&#xff0c;root用戶密碼忘記了&#xff0c;登陸不上系統&#xff0c;如下圖所示…

【網絡安全】Web安全基礎 - 第一節:使用軟件及環境介紹

VMware VMware&#xff0c;是全球云基礎架構和移動商務解決方案的佼佼者。 VMware可是一個總部位于美國加州帕洛阿爾托的計算機虛擬化軟件研發與銷售企業呢。簡單來說&#xff0c;它就是通過提供虛擬化解決方案&#xff0c;讓企業在數據中心改造和公有云整合業務上更加得心應…

QImage和QPixmap的區別和使用

一、基本概念和特點 QImage 概念&#xff1a;QImage是Qt庫中用于處理圖像數據的一個類。它提供了直接訪問和操作圖像像素的接口。特點&#xff1a; 可以獨立于屏幕分辨率和設備處理圖像。支持讀取和保存多種圖像格式&#xff0c;如PNG、JPEG、BMP等。可以在沒有圖形界面的情況…

圖論第二天

最近加班時間又多了&#xff0c;隨緣吧&#xff0c;干不動就辭唄。真是想歇幾天了&#xff0c;題不能停&#xff01;&#xff01;今天目前只做了一道題&#xff0c;先用兩種方式把他搞出來。 695. 島嶼的最大面積 class Solution { public:int neighbor[4][2] {1,0,0,-1,-1,…