【算法介紹】
基於YOLOv11的45種交通標誌檢測與識別系統,是專為智能交通與自動駕駛領域設計的深度學習解決方案。該系統利用YOLOv11目標檢測算法的最新優勢,實現對45類常見交通標誌的高效、精準識別,包括限速牌、停車標誌、禁止通行等。
系統核心採用YOLOv11模型,其網絡結構通過C3k2塊、SPPF模塊及C2PSA注意力機制的優化,顯著提升了特徵提取能力與空間注意力,尤其在複雜場景下對小目標和重疊目標的檢測精度顯著提升。在數據層面,系統基於TT100K等公開數據集進行訓練,結合旋轉、縮放、翻轉等數據增強技術,確保模型在多場景、多光照條件下的泛化能力。
系統架構包含三大模塊:圖像輸入、攝像頭實時檢測和視頻文件讀取;檢測與識別模塊通過YOLOv11實現交通標誌的快速定位與分類;結果輸出模塊在圖像上繪製檢測框並標註類別信息。
該系統可廣泛應用於車載輔助駕駛、交通監控及智能導航系統,通過提升道路標誌識別準確率,有效降低交通事故風險,推動智能交通技術的落地應用。
【效果展示】
【訓練數據集介紹】 數據集格式:YOLO格式(僅僅包含jpg圖片以及對應的yolo格式txt文件,已劃分好訓練驗證測試集) 圖片數量(jpg文件個數):9720 標註數量(xml文件個數):9720 標註數量(txt文件個數):9720 標註類別數:45 標註類別名稱(注意yolo格式類別順序不和這個對應,而以提供data.yaml類別順序為準):["i2","i2r","i4","i4l","i5","il60","il80","il100","ip","p3","p5","p6","p10","p11","p12","p13","p19","p23","p26","p27","pg","ph4","ph4.5","ph5","pl5","pl20","pl30","pl40","pl50","pl60","pl70","pl80","pl100","pl120","pm20","pm30","pm55","pn","pne","pr40","w13","w32","w55","w57","w59"] 每個類別標註的框數: i2 框數 = 471 i2r 框數 = 429 i4 框數 = 812 i4l 框數 = 335 i5 框數 = 1734 il60 框數 = 132 il80 框數 = 488 il100 框數 = 296 ip 框數 = 354 p3 框數 = 374 p5 框數 = 1580 p6 框數 = 189 p10 框數 = 379 p11 框數 = 128 p12 框數 = 296 p13 框數 = 839 p19 框數 = 134 p23 框數 = 173 p26 框數 = 421 p27 框數 = 116 pg 框數 = 157 ph4 框數 = 121 ph4.5 框數 = 186 ph5 框數 = 121 pl5 框數 = 670 pl20 框數 = 298 pl30 框數 = 164 pl40 框數 = 639 pl50 框數 = 1409 pl60 框數 = 537 pl70 框數 = 1071 pl80 框數 = 834 pl100 框數 = 148 pl120 框數 = 901 pm20 框數 = 156 pm30 框數 = 106 pm55 框數 = 139 pn 框數 = 3172 pne 框數 = 2383 pr40 框數 = 201 w13 框數 = 130 w32 框數 = 123 w55 框數 = 179 w57 框數 = 418 w59 框數 = 231 總框數:24174 使用標註工具:labelImg 標註規則:對類別進行畫矩形框 重要説明:暫無 特別聲明:本數據集不對訓練的模型或者權重文件精度作任何保證,數據集只提供準確且合理標注
圖片預覽:
【訓練信息】
|
參數
|
值
|
|
訓練集圖片數
|
6793
|
|
驗證集圖片數
|
1931
|
|
訓練map
|
64.3%
|
|
訓練精度(Precision)
|
68.4%
|
|
訓練召回率(Recall)
|
58.5%
|
【驗證集精度統計】
|
Class
|
Images
|
Instances
|
P
|
R
|
mAP50
|
mAP50-95
|
|
all
|
1931
|
4797
|
0.684
|
0.585
|
0.643
|
0.459
|
|
i2
|
87
|
87
|
0.72
|
0.649
|
0.756
|
0.472
|
|
i2r
|
91
|
91
|
0.781
|
0.681
|
0.754
|
0.513
|
|
i4
|
154
|
164
|
0.833
|
0.67
|
0.788
|
0.493
|
|
i4l
|
73
|
74
|
0.82
|
0.676
|
0.774
|
0.537
|
|
i5
|
325
|
346
|
0.91
|
0.761
|
0.879
|
0.558
|
|
il60
|
69
|
91
|
0.819
|
0.894
|
0.919
|
0.7
|
|
il80
|
53
|
59
|
0.707
|
0.859
|
0.872
|
0.663
|
|
il100
|
28
|
28
|
0.831
|
0.703
|
0.88
|
0.664
|
|
ip
|
60
|
70
|
0.731
|
0.543
|
0.65
|
0.318
|
|
p3
|
30
|
30
|
0.82
|
0.6
|
0.697
|
0.522
|
|
p5
|
76
|
79
|
0.765
|
0.646
|
0.703
|
0.523
|
|
p6
|
23
|
23
|
0.563
|
0.392
|
0.513
|
0.447
|
|
p10
|
69
|
71
|
0.579
|
0.577
|
0.574
|
0.44
|
|
p11
|
313
|
315
|
0.749
|
0.622
|
0.713
|
0.459
|
|
p12
|
36
|
36
|
0.489
|
0.389
|
0.331
|
0.255
|
|
p13
|
52
|
82
|
0.664
|
0.598
|
0.634
|
0.379
|
|
p19
|
24
|
24
|
0.539
|
0.487
|
0.508
|
0.409
|
|
p23
|
60
|
61
|
0.734
|
0.574
|
0.668
|
0.493
|
|
p26
|
163
|
172
|
0.685
|
0.616
|
0.692
|
0.499
|
|
p27
|
29
|
29
|
0.425
|
0.379
|
0.368
|
0.282
|
|
pg
|
29
|
29
|
0.954
|
0.621
|
0.756
|
0.523
|
|
ph4
|
22
|
23
|
0.67
|
0.529
|
0.584
|
0.454
|
|
ph4.5
|
31
|
35
|
0.694
|
0.713
|
0.693
|
0.542
|
|
ph5
|
21
|
24
|
0.439
|
0.208
|
0.294
|
0.198
|
|
pl5
|
75
|
110
|
0.657
|
0.473
|
0.533
|
0.336
|
|
pl20
|
31
|
33
|
0.598
|
0.0904
|
0.202
|
0.138
|
|
pl30
|
122
|
124
|
0.606
|
0.5
|
0.55
|
0.413
|
|
pl40
|
277
|
286
|
0.69
|
0.476
|
0.611
|
0.421
|
|
pl50
|
209
|
210
|
0.579
|
0.471
|
0.527
|
0.377
|
|
pl60
|
170
|
174
|
0.526
|
0.575
|
0.564
|
0.441
|
|
pl70
|
28
|
28
|
0.696
|
0.573
|
0.597
|
0.478
|
|
pl80
|
158
|
165
|
0.713
|
0.661
|
0.713
|
0.52
|
|
pl100
|
76
|
131
|
0.813
|
0.797
|
0.883
|
0.689
|
|
pl120
|
47
|
59
|
0.679
|
0.79
|
0.781
|
0.607
|
|
pm20
|
26
|
26
|
0.629
|
0.538
|
0.66
|
0.498
|
|
pm30
|
17
|
17
|
0.251
|
0.412
|
0.252
|
0.217
|
|
pm55
|
31
|
32
|
0.662
|
0.675
|
0.72
|
0.583
|
|
pn
|
603
|
633
|
0.901
|
0.736
|
0.829
|
0.526
|
|
pne
|
429
|
471
|
0.92
|
0.779
|
0.876
|
0.537
|
|
pr40
|
37
|
37
|
0.82
|
0.892
|
0.945
|
0.785
|
|
w13
|
27
|
27
|
0.455
|
0.333
|
0.354
|
0.242
|
|
w32
|
23
|
23
|
0.678
|
0.261
|
0.349
|
0.175
|
|
w55
|
43
|
43
|
0.531
|
0.512
|
0.513
|
0.364
|
|
w57
|
77
|
82
|
0.648
|
0.718
|
0.737
|
0.514
|
|
w59
|
43
|
43
|
0.803
|
0.663
|
0.742
|
0.455
|
【測試環境】
windows10 x64系統 VS2019 netframework4.7.2 opencvsharp4.9.0 onnxruntime1.22.0
注意使用CPU推理,沒有使用cuda推理因此不需要電腦具有nvidia顯卡,無需安裝安裝cuda+dunn
【界面設計】
using DeploySharp.Data;
using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace FIRC
{
public partial class Form1 : Form
{
public bool videoStart = false;//視頻停止標誌
string weightsPath = Application.StartupPath + "\\weights";//模型目錄
YoloDetector detetor = new YoloDetector();//推理引擎
public Form1()
{
InitializeComponent();
CheckForIllegalCrossThreadCalls = false;//線程更新控件不報錯
}
private void LoadWeightsFromDir()
{
var di = new DirectoryInfo(weightsPath);
foreach(var fi in di.GetFiles("*.onnx"))
{
comboBox1.Items.Add(fi.Name);
}
if(comboBox1.Items.Count>0)
{
comboBox1.SelectedIndex = 0;
}
else
{
tssl_show.Text = "未找到模型,請關閉程序,放入模型到weights文件夾!";
tsb_pic.Enabled = false;
tsb_video.Enabled = false;
tsb_camera.Enabled = false;
}
}
private void Form1_Load(object sender, EventArgs e)
{
LoadWeightsFromDir();//從目錄加載模型
}
public string GetResultString(DetResult[] result)
{
Dictionary<string, int> resultDict = new Dictionary<string, int>();
for (int i = 0; i < result.Length; i++)
{
if(resultDict.ContainsKey( result[i].Category) )
{
resultDict[result[i].Category]++;
}
else
{
resultDict[result[i].Category] =1;
}
}
var resultStr = "";
foreach(var item in resultDict)
{
resultStr += string.Format("{0}:{1}\r\n",item.Key,item.Value);
}
return resultStr;
}
private void tsb_pic_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "*.*|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png";
if (ofd.ShowDialog() != DialogResult.OK) return;
tssl_show.Text = "正在檢測中...";
Task.Run(() => {
var sw = new Stopwatch();
sw.Start();
Mat image = Cv2.ImRead(ofd.FileName);
detetor.SetParams(Convert.ToSingle(numericUpDown1.Value), Convert.ToSingle(numericUpDown2.Value));
var results=detetor.Inference(image);
var resultImage = detetor.DrawImage(image, results);
sw.Stop();
pb_show.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(resultImage);
tb_res.Text = GetResultString(results);
tssl_show.Text = "檢測已完成!總計耗時"+sw.Elapsed.TotalSeconds+"秒";
});
}
public void VideoProcess(string videoPath)
{
Task.Run(() => {
detetor.SetParams(Convert.ToSingle(numericUpDown1.Value), Convert.ToSingle(numericUpDown2.Value));
VideoCapture capture = new VideoCapture(videoPath);
if (!capture.IsOpened())
{
tssl_show.Text="視頻打開失敗!";
return;
}
Mat frame = new Mat();
var sw = new Stopwatch();
int fps = 0;
while (videoStart)
{
capture.Read(frame);
if (frame.Empty())
{
Console.WriteLine("data is empty!");
break;
}
sw.Start();
var results = detetor.Inference(frame);
var resultImg = detetor.DrawImage(frame,results);
sw.Stop();
fps = Convert.ToInt32(1 / sw.Elapsed.TotalSeconds);
sw.Reset();
Cv2.PutText(resultImg, "FPS=" + fps, new OpenCvSharp.Point(30, 30), HersheyFonts.HersheyComplex, 1.0, new Scalar(255, 0, 0), 3);
//顯示結果
pb_show.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(resultImg);
tb_res.Text = GetResultString(results);
Thread.Sleep(5);
}
capture.Release();
pb_show.Image = null;
tssl_show.Text = "視頻已停止!";
tsb_video.Text = "選擇視頻";
});
}
public void CameraProcess(int cameraIndex=0)
{
Task.Run(() => {
detetor.SetParams(Convert.ToSingle(numericUpDown1.Value), Convert.ToSingle(numericUpDown2.Value));
VideoCapture capture = new VideoCapture(cameraIndex);
if (!capture.IsOpened())
{
tssl_show.Text = "攝像頭打開失敗!";
return;
}
Mat frame = new Mat();
var sw = new Stopwatch();
int fps = 0;
while (videoStart)
{
capture.Read(frame);
if (frame.Empty())
{
Console.WriteLine("data is empty!");
break;
}
sw.Start();
var results = detetor.Inference(frame);
var resultImg = detetor.DrawImage(frame, results);
sw.Stop();
fps = Convert.ToInt32(1 / sw.Elapsed.TotalSeconds);
sw.Reset();
Cv2.PutText(resultImg, "FPS=" + fps, new OpenCvSharp.Point(30, 30), HersheyFonts.HersheyComplex, 1.0, new Scalar(255, 0, 0), 3);
//顯示結果
pb_show.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(resultImg);
tb_res.Text = GetResultString(results);
Thread.Sleep(5);
}
capture.Release();
pb_show.Image = null;
tssl_show.Text = "攝像頭已停止!";
tsb_camera.Text = "打開攝像頭";
});
}
private void tsb_video_Click(object sender, EventArgs e)
{
if(tsb_video.Text=="選擇視頻")
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "視頻文件(*.*)|*.mp4;*.avi";
if (ofd.ShowDialog() != DialogResult.OK) return;
videoStart = true;
VideoProcess(ofd.FileName);
tsb_video.Text = "停止";
tssl_show.Text = "視頻正在檢測中...";
}
else
{
videoStart = false;
}
}
private void tsb_camera_Click(object sender, EventArgs e)
{
if (tsb_camera.Text == "打開攝像頭")
{
videoStart = true;
CameraProcess(0);
tsb_camera.Text = "停止";
tssl_show.Text = "攝像頭正在檢測中...";
}
else
{
videoStart = false;
}
}
private void tsb_exit_Click(object sender, EventArgs e)
{
videoStart = false;
this.Close();
}
private void trackBar1_Scroll(object sender, EventArgs e)
{
numericUpDown1.Value = Convert.ToDecimal(trackBar1.Value / 100.0f);
}
private void trackBar2_Scroll(object sender, EventArgs e)
{
numericUpDown2.Value = Convert.ToDecimal(trackBar2.Value / 100.0f);
}
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
trackBar1.Value = (int)(Convert.ToSingle(numericUpDown1.Value) * 100);
}
private void numericUpDown2_ValueChanged(object sender, EventArgs e)
{
trackBar2.Value = (int)(Convert.ToSingle(numericUpDown2.Value) * 100);
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
tssl_show.Text="加載模型:"+comboBox1.Text;
detetor.LoadWeights(weightsPath+"\\"+comboBox1.Text);
tssl_show.Text = "模型加載已完成!";
}
}
}
【常用評估參數介紹】
在目標檢測任務中,評估模型的性能是至關重要的。你提到的幾個術語是評估模型性能的常用指標。下面是對這些術語的詳細解釋:
- Class :
- 這通常指的是模型被設計用來檢測的目標類別。例如,一個模型可能被訓練來檢測車輛、行人或動物等不同類別的對象。
- Images :
- 表示驗證集中的圖片數量。驗證集是用來評估模型性能的數據集,與訓練集分開,以確保評估結果的公正性。
- Instances :
- 在所有圖片中目標對象的總數。這包括了所有類別對象的總和,例如,如果驗證集包含100張圖片,每張圖片平均有5個目標對象,則Instances為500。
- P(精確度Precision) :
- 精確度是模型預測為正樣本的實例中,真正為正樣本的比例。計算公式為:Precision = TP / (TP + FP),其中TP表示真正例(True Positives),FP表示假正例(False Positives)。
- R(召回率Recall) :
- 召回率是所有真正的正樣本中被模型正確預測為正樣本的比例。計算公式為:Recall = TP / (TP + FN),其中FN表示假負例(False Negatives)。
- mAP50 :
- 表示在IoU(交併比)閾值為0.5時的平均精度(mean Average Precision)。IoU是衡量預測框和真實框重疊程度的指標。mAP是一個綜合指標,考慮了精確度和召回率,用於評估模型在不同召回率水平上的性能。在IoU=0.5時,如果預測框與真實框的重疊程度達到或超過50%,則認為該預測是正確的。
- mAP50-95 :
- 表示在IoU從0.5到0.95(間隔0.05)的範圍內,模型的平均精度。這是一個更嚴格的評估標準,要求預測框與真實框的重疊程度更高。在目標檢測任務中,更高的IoU閾值意味着模型需要更準確地定位目標對象。mAP50-95的計算考慮了從寬鬆到嚴格的多個IoU閾值,因此能夠更全面地評估模型的性能。
這些指標共同構成了評估目標檢測模型性能的重要框架。通過比較不同模型在這些指標上的表現,可以判斷哪個模型在實際應用中可能更有效。
【使用步驟】
使用步驟: (1)首先根據官方框架ultralytics安裝教程安裝好yolov11環境,並根據官方export命令將自己pt模型轉成onnx模型,然後去github倉庫futureflsl/firc-csharp-projects找到源碼 (2)使用vs2019打開sln項目,選擇x64 release並且修改一些必要的參數,比如輸入shape等,點擊運行即可查看最後效果
特別注意如果運行報錯了,請參考我的博文進行重新引用我源碼的DLL:[C#]opencvsharp報錯System.Memory,Version=4.0.1.2,Culture=neutral,PublicKeyToken=cc7b13fcd2ddd51“版本高於所引_未能加載文件或程序集“system.memory, version=4.0.1.2, culture-CSDN博客
【提供文件】
C#源碼
yolo11n.onnx模型(提供pytorch模型)
訓練的map,P,R曲線圖(在weights\results.png)
測試圖片(在test_img文件夾下面)
特別注意這裏提供訓練數據集