| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- using OpenCvSharp;
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Drawing;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using CvPoint = OpenCvSharp.Point;
- namespace YoloTest
- {
- internal class Program
- {
- static void Main(string[] args)
- {
- string imagepath = "Model/2025-08-11-09-40-52-345.jpg";
- string ModelPath = "Model/N_best_stop_aug_ckpt.onnx";
- using (var detector = new YoloV6Detector(ModelPath, new[] { "OK", "NG" },true))
- {
- // 1. 使用 System.Drawing 加载图像用于检测
- using (var image = Image.FromFile(imagepath))
- {
- List<Detection> results = new List<Detection>();
- Stopwatch stopwatch = new Stopwatch();
- for (int i = 0; i < 50; i++)
- {
- stopwatch.Restart();
- results = detector.Detect(image);
- stopwatch.Stop();
- Console.WriteLine("运行次数:{0},推理耗时:{1}", i+1 ,stopwatch.ElapsedMilliseconds);
- }
- // 2. 使用 OpenCvSharp 加载图像用于绘制
- using (var mat = Cv2.ImRead(imagepath))
- {
- int imgWidth = mat.Width;
- int imgHeight = mat.Height;
- foreach (var det in results)
- {
- // 【新增】边缘过滤 - 去除紧贴上下边缘的结果
- //float edgeThreshold = imgHeight * 0.05f; // 边缘阈值:图像高度的 5%
- float edgeThreshold = 5; // 边缘阈值:图像高度的 5%
- // 检测框顶部或底部过于靠近边缘则跳过
- if (det.Y < edgeThreshold || (det.Y + det.Height) > (imgHeight - edgeThreshold))
- {
- continue;
- }
- // 坐标转换:根据检测结果是否为归一化坐标进行转换
- float x = det.X;
- float y = det.Y;
- float width = det.Width;
- float height = det.Height;
- // 计算边界框坐标
- int left = (int)x;
- int top = (int)y;
- int right = (int)(x + width);
- int bottom = (int)(y + height);
- // 确保坐标在图像范围内
- left = Math.Max(0, left);
- top = Math.Max(0, top);
- right = Math.Min(imgWidth, right);
- bottom = Math.Min(imgHeight, bottom);
- // 绘制矩形框 (BGR: 绿色)
- Cv2.Rectangle(mat, new CvPoint(left, top), new CvPoint(right, bottom), new Scalar(0, 255, 0), 2);
- // 准备标签文本
- string className = detector._classNames[det.ClassId];
- string label = $"{className}: {det.Confidence:F2}";
- // 计算文本大小
- var textSize = Cv2.GetTextSize(label, HersheyFonts.HersheySimplex, 0.5, 1, out int baseline);
- // 绘制标签背景
- Cv2.Rectangle(mat,
- new CvPoint(left, top - textSize.Height - 5),
- new CvPoint(left + textSize.Width, top),
- new Scalar(0, 255, 0),
- -1);
- // 绘制标签文本
- Cv2.PutText(mat, label, new CvPoint(left, top - 5),
- HersheyFonts.HersheySimplex, 0.5, new Scalar(0, 0, 0), 1);
- }
- Cv2.ImShow("result", ResizeMat(mat));
- Cv2.WaitKey(0);
- // 保存结果图像
- //Cv2.ImWrite("Model/result_2025-08-11-09-55-30-647.jpg", mat);
- }
- }
- }
- }
- // 非极大值抑制 (NMS) - 去除重叠框,保留置信度高的结果
- static List<Detection> ApplyNMS(List<Detection> detections, float iouThreshold = 0.45f)
- {
- if (detections.Count == 0) return detections;
- // 按置信度降序排序
- var sorted = detections.OrderByDescending(d => d.Confidence).ToList();
- var selected = new List<Detection>();
- while (sorted.Count > 0)
- {
- // 选择置信度最高的检测框
- var best = sorted[0];
- selected.Add(best);
- sorted.RemoveAt(0);
- // 移除与当前框 IoU 超过阈值的其他框
- sorted = sorted.Where(d =>
- {
- float iou = CalculateIoU(best, d);
- return iou < iouThreshold;
- }).ToList();
- }
- return selected;
- }
- // 计算两个检测框的 IoU (Intersection over Union)
- static float CalculateIoU(Detection a, Detection b)
- {
- // 计算交集坐标
- float x1 = Math.Max(a.X, b.X);
- float y1 = Math.Max(a.Y, b.Y);
- float x2 = Math.Min(a.X + a.Width, b.X + b.Width);
- float y2 = Math.Min(a.Y + a.Height, b.Y + b.Height);
- // 计算交集面积
- float intersection = Math.Max(0, x2 - x1) * Math.Max(0, y2 - y1);
- // 计算并集面积
- float areaA = a.Width * a.Height;
- float areaB = b.Width * b.Height;
- float union = areaA + areaB - intersection;
- return union > 0 ? intersection / union : 0;
- }
- static Mat ResizeMat(Mat mat)
- {
- Mat resizedImage = new Mat();
- double maxSize = 900;
- double scale = Math.Min(maxSize / mat.Width, maxSize / mat.Height);
- OpenCvSharp.Size scaledSize = new OpenCvSharp.Size(mat.Width * scale, mat.Height * scale);
- Cv2.Resize(mat, resizedImage, scaledSize);
- return resizedImage;
- }
- //public static void CheckGpuUsage()
- //{
- // var providers = SessionOptions.GetAvailableProviders();
- // Console.WriteLine("可用的执行提供程序:");
- // foreach (var provider in providers)
- // {
- // Console.WriteLine($"- {provider}");
- // }
- // // 应该能看到 "DmlExecutionProvider" 或 "OpenVinoExecutionProvider"
- //}
- }
- }
|