
簡介本資源是一套面向智能交通與車載視覺應用開發者的安全帶檢測實戰方案聚焦駕駛行為規范監管場景適用于YOLO系列算法v5至v26的模型訓練、部署與效果驗證。壓縮包共2000個文件含1976個VOC格式XML標注文件、22個Markdown說明文檔及配置文件總大小293.17MB其中5055張高清圖像已按train/val/test劃分并提供data.yaml及YOLO格式標簽開箱即用于多版本YOLO訓練。資源配套完整使用教程、模型評價指標曲線圖及settings.json等工程化配置顯著降低部署門檻。目前已有41人學習下載適合計算機視覺初學者掌握目標檢測數據集構建流程也便于研究人員快速復現安全帶識別任務并拓展至疲勞駕駛、分心行為等衍生方向。1. 為什么要做安全帶檢測一個看起來很“小”卻讓人頭疼的視覺任務我一開始接到這個需求時心里想的是“就檢測一條帶子能有多難”。真正動手做了才知道安全帶檢測在整個駕駛監控類項目里算得上是最容易翻車的任務之一。因為安全帶在畫面里占比小、形態細長、顏色和車內飾接近再加上陽光直射、夜間逆光、深色衣物遮擋等亂七八糟的情況傳統視覺方案比如邊緣檢測幾何判斷基本一到真實場景就崩了。這個項目最終的形態是用YOLO26訓練了一個專門識別“駕駛位安全帶是否正確佩戴”的模型外面套了一層PyQt寫的桌面程序支持從攝像頭或視頻文件實時讀取畫面對畫面里駕駛員上半身區域做檢測如果判定為“未系安全帶”界面立刻給出告警提示。同時項目里帶了整理好的數據集和訓練完成的模型權重拿到的機器只要把依賴裝好跑起來就能直接做演示或者二次開發。這個項目的價值說白了就是兩件事第一用目標檢測模型替代傳統圖像處理把一個曾經極度依賴環境和角度的小目標識別問題變成了一個可以應付復雜場景的標準化檢測流程第二把模型從訓練到部署的完整鏈路串了起來從PyTorch訓練到PyQt推理到PyInstaller封裝exe每一步都有能跑的代碼和對應的坑。所以這篇文章適合兩類人一類是想做駕駛行為監控相關項目的開發者想知道安全帶檢測到底該怎么落地另一類是手里有YOLO模型但是不太清楚怎么和桌面界面結合、怎么打包給別人用的人。我先把項目的整體技術棧擺出來檢測框架YOLO26用的官方權重結構做了少量針對細長目標的改進開發語言Python 3.10界面框架PyQt5推理后端PyTorchCPU/GPU都兼容后續可換ONNX數據集來源公開駕駛行為數據集 自采補充樣本交付物訓練代碼、數據處理腳本、PyQt界面源碼、訓練好的.pt權重、樣例視頻這套組合不是隨便定的。后面我會逐個講清楚選型理由和實際操作中遇到的問題。2. YOLO26為什么適合這個項目結構認知和選型復盤先說說YOLO26。很多人一聽到YOLO最新版第一反應是“哦又出了一個版本精度應該更高”實際上YOLO26的核心賣點不只是精度而是它把整個訓練流程變得更適合工程化調優。它吸收了之前多個版本的優點在特征提取部分繼續沿用CSP結構的思路但把更深層的特征融合做得更干凈。我畫一下我理解的YOLO26核心結構不展開代碼就說它對本項目的三個關鍵優勢2.1 對細長小目標的特征保留能力安全帶在畫面里經常只占幾十個像素寬度長度倒是有幾百像素傳統檢測器容易把它當成背景紋理。YOLO26在backbone部分對高分辨率特征層的下采樣次數做了更靈活的配置也就是說模型可以保留更多淺層高分辨率信息給檢測頭。這對安全帶這種“細長條”目標非常友好。我在實驗里對比過同樣的數據集YOLOv8的mAP50大概在0.912左右YOLO26能跑到0.946提升主要就來自安全帶這一類。2.2 動態標簽分配更適配類別不平衡實際的安全帶檢測本質上是一個“正樣本極少”的任務——多數畫面里駕駛員都好好系著安全帶真正違規的畫面占比低。如果你拿一個類別極其不平衡的數據集去訓練模型很容易“偷懶”把所有框都預測成“已系”。YOLO26的標簽分配策略會根據預測結果動態調整正樣本匹配相當于它會在訓練過程中主動去挖掘那些難分的未系安全帶樣本。這一點我在訓練初期體會特別明顯前20個epoch的時候“未系安全帶”這個類別的recall一直起不來動態分配策略介入后到第60個epoch左右就明顯拉平了。2.3 訓練成本和部署靈活性YOLO26的模型體量相比YOLOv8沒有明顯變大但收斂速度快了不少。我用一張RTX 3060跑batch size 16640分辨率大概2個小時能跑完100個epoch。而且它的推理代碼和舊版YOLO一脈相承導出ONNX、TensorRT都非常順這意味著后續如果要把模型塞進嵌入式設備比如Jetson Nano或者RK3588不需要重寫推理邏輯。當然YOLO26也有它的毛病。最明顯的一點是官方的一些改進模塊比如說部分注意力機制在邊緣設備上的加速效果不如預期量化到INT8后精度掉得比YOLOv8更明顯。如果打算做嵌入式部署我的建議是先用FP16跑通再考慮要不要量化。這一點我在第6章會再展開講。3. 數據集的構建安全帶檢測真正的大頭工作量說句實在話模型訓練反而是這個項目里最“輕松”的部分真正耗時的是數據。安全帶檢測的數據集不像COCO那種通用目標檢測數據集直接download下來就能用它有幾個特殊情況必須自己處理。3.1 數據來源劃分我用到的數據大致分三塊公開駕駛行為數據集比如一些開源的車內駕駛員監控數據集里面包含了駕駛員面部、手部、安全帶狀態的標注。這類數據質量參差不齊有的標注框給的是整個上半身有的是給安全帶區域用之前必須統一。自采視頻抽幀找了一段真實車內視角的視頻包括白天、傍晚、夜間、逆光、戴深色衣服、系了但系錯位置等場景按每3秒一幀抽出來再人工篩選。數據增強擴充對已有的圖片做HSV擾動、隨機遮擋、水平翻轉注意安全帶位置左右對稱可以翻、mosaic拼接。我的最終數據集是8400張圖片其中“已系安全帶”5200張“未系安全帶”2100張“系錯位置”比如系在腋下1100張。后兩類是真正的難點因為系錯位置和未系的視覺差異其實很微妙。3.2 標注細節三種狀態的決定標注這一步最關鍵的是先確定類別定義。我最初想做的是二分類——要么系了、要么沒系但后來發現實際場景里經常出現“系了但是完全沒起到保護作用”的情況比如安全帶從腋下穿過或者系在肚子上。只用二分類模型這類樣本會被模型當成“已系”導致漏報。所以我把類別擴成了三類safetybelt_worn正確佩戴safetybelt_notworn完全未系safetybelt_misplaced系錯位置三個類別在后續告警策略里的權重不一樣。misplaced的置信度就算到0.5我也會彈告警worn則必須到0.6以上才判定為正常。這樣做的原因是漏報的代價遠大于誤報。標注工具我用的是LabelImg格式直接導出YOLO的txt。這里有一個坑LabelImg默認導出的框坐標是歸一化的但有些舊版本會把坐標寫成百分比格式如果你的訓練腳本按像素坐標解析就會出問題。我建議拿到任何公開數據集之后先寫個小腳本統一格式別直接拿去訓練。3.3 訓練集和驗證集劃分的講究安全帶檢測還有一個容易忽略的問題同一段視頻里相鄰兩幀的畫面幾乎一樣如果隨機劃分訓練集和驗證集模型可能在驗證集上表現虛高因為它“見過”幾乎一樣的畫面。我一開始就是隨機劃分驗證集mAP50跑到了0.96興奮得不行后來換成了按視頻文件劃分同一個視頻的所有幀只能出現在一個集合里mAP降到0.93。這才是真實水平。所以做視頻類檢測項目劃分數據時一定要按“視頻ID”分組而不是按幀。4. 模型訓練全流程參數、Loss曲線和中間踩過的坑4.1 訓練環境配置我的環境是Ubuntu 20.04 CUDA 11.8 cuDNN 8.6PyTorch 2.1.0顯卡RTX 3060 12G如果你用的是Windows環境配置也差不多但要注意YOLO26的一部分CUDA算子需要編譯Windows下VS的C生成工具必須裝好否則會在pip install的時候直接報錯。這個坑我幫朋友排過兩次都是VS沒裝全。我用的是conda創建虛擬環境Python版本3.10。這里提醒一下不要用Python 3.12有些舊版的PyTorch和torchvision不支持編譯會很痛苦。4.2 訓練參數選擇超參數我直接給出最終能用的版本不一定最優但穩定model: yolov26s.yaml data: safetybelt.yaml epochs: 100 batch: 16 imgsz: 640 optimizer: AdamW lr0: 0.001 lrf: 0.01 momentum: 0.937 weight_decay: 0.0005 warmup_epochs: 3 mosaic: 1.0幾個要解釋的點為什么用AdamW而不用SGD安全帶這個任務的類別差異不大特征也偏細節AdamW在收斂速度上的優勢更明顯。SGD也不是不行但需要更多epoch才能達到同等精度。batch size 16在12G顯存上剛好卡住如果你顯存不夠建議降到8同時把imgsz從640降到512先跑通流程再提分辨率。mosaic增強我保留了但把它從默認的1.0調成了和隨機仿射一起用。安全帶是細長物體mosaic拼接時如果目標被切到邊緣標注框容易出問題所以我加了一個限制被截斷超過50%的目標直接丟棄。4.3 訓練過程中的關鍵信號訓練到第20個epoch左右我發現一個問題訓練集loss在降但驗證集的box_loss在震蕩。典型的過擬合前兆。當時我懷疑是數據不夠但后來排查發現是標注數據里有幾十張圖的安全帶框標注得太大了——框的一半落在了座椅上。這類臟標注對模型的干擾比想象中大得多。把臟樣本挑出來重新標注之后驗證loss立刻平滑了。挑臟標注有一個省力的辦法訓練完第一個模型后用模型去預測訓練集把confidence高但和標簽的IoU低于0.3的樣本全部導出檢查。這些大概率是錯標或者漏標。我的最終訓練結果類別PrecisionRecallmAP50mAP50-95safetybelt_worn0.9530.9470.9780.833safetybelt_notworn0.9140.8760.9310.742safetybelt_misplaced0.8820.8240.9010.695整體mAP50-95在0.75左右夠用。misplaced這個類別天然難因為它的視覺特征太依賴上下文——同樣一條帶子的走向有人系對了有人系錯了差異可能只有十幾度角度。后續如果想繼續提升可以從兩個方向走一是專門針對misplaced收集更多數據二是把檢測頭改成旋轉目標檢測的思路因為安全帶本質是一個有朝向的細長矩形水平框的信息利用率不高。這個改進目前還在試。4.4 Confusion Matrix分析訓練完之后一定要看confusion matrix。我這次發現的主要問題是notworn被誤判成worn的數量不少但真正影響體驗的是misplaced被誤判成worn。這會直接導致系統對“系錯位置”無動于衷。解決辦法我前面說了降低misplaced的告警閾值同時在后處理邏輯里對worn類別增加了置信度要求。5. PyQt界面開發從模型到可視化告警的工程細節模型訓好了不做成界面就對不起前面做的工作。PyQt這部分看起來是“錦上添花”但真正做進去會發現它承擔了一個關鍵職責把模型推理和用戶交互解耦讓不懂算法的人也能直接使用這個系統。5.1 界面模塊劃分我的界面結構分成三塊視頻輸入區支持本地視頻文件和USB攝像頭實時流。檢測結果展示區顯示原始畫面、檢測框、類別標簽、置信度。告警區記錄未系安全帶的截圖和發生時間支持手動導出。這三塊在PyQt里對應三個QWidget用QSplitter做布局底部的QListWidget顯示歷史告警記錄。整體結構不復雜但寫起來要注意的東西不少。5.2 多線程處理千萬不能在UI線程里跑模型這是我第一次用PyQt做視覺應用時踩過最大的坑。一開始我圖省事直接在QTimer的timeout回調里調用model.predict()結果畫面卡得沒法看拖拽窗口都費勁。原因很簡單模型推理是CPU/GPU密集操作會阻塞Qt的事件循環整個界面就假死了。正確的做法是用QThread 信號槽。工作線程負責從VideoCapture讀幀、跑模型推理、把結果打包成QImage發射信號主線程只負責接收信號并更新UI。這里有一個細節QImage的構造一定要拷貝數據因為OpenCV的Mat指向的內部buffer可能會被下一幀覆蓋如果你直接傳Mat的data指針構造QImage顯示出來的畫面就是花屏或閃爍的。我的推理線程核心邏輯大概是這樣的class DetectThread(QThread): update_frame pyqtSignal(QImage, list) def run(self): cap cv2.VideoCapture(self.video_path) while not self.isInterruptionRequested(): ret, frame cap.read() if not ret: break results self.model(frame, verboseFalse) annotated results[0].plot() rgb cv2.cvtColor(annotated, cv2.COLOR_BGR2RGB) h, w, ch rgb.shape bytes_per_line ch * w qimg QImage(rgb.data, w, h, bytes_per_line, QImage.Format_RGB888).copy() self.update_frame.emit(qimg, results) if cv2.waitKey(1) 0xFF ord(q): break那個.copy()是關鍵不加就是靈異花屏。5.3 告警策略的實現有了檢測結果怎么決定要不要告警我這里的邏輯并不復雜設定一個興趣區域ROI只檢測畫面里駕駛員上半身那塊區域通常是畫面的左下四分之一到中間。對每一幀統計該ROI內的所有檢測框取置信度最高的那個類別作為當前幀狀態。如果連續5幀都判定為未系或系錯才觸發告警截圖。告警后進入30秒靜默期防止同一段違規被反復彈窗刷屏。連續5幀這個設計很關鍵。直接單幀判定會導致偶爾的誤檢變成告警太煩人。用“連續多幀確認”可以濾掉大部分偶發噪聲代價是響應延遲一秒鐘左右在駕駛監控場景下完全可接受。5.4 PyQt里的模型加載優化模型加載也有講究。如果你用PyTorch直接torch.load(best.pt)每次啟動大概要3~5秒這對一個桌面工具來說有點慢但能忍。但如果你用的是CPU推理而且機器性能一般我建議在初始化時把模型轉換成半精度FP16或者導出ONNX再加載。ONNX在CPU上的推理速度能快一倍左右。不過ONNX的有一些問題動態尺寸支持不如PyTorch原生方便如果你需要在運行過程中切換不同分辨率輸入ONNX會重新做graph優化反而更慢。所以我的方案是默認用PyTorch原生推理同時寫了一個導出腳本給需要部署到低配機器上的用戶做ONNX轉換。6. 模型部署與打包從Python腳本到獨立exe的實戰記錄開發完界面之后一個繞不過去的需求出現了——你不能讓用戶裝一個Python環境再跑你的代碼吧尤其是駕駛安全監控這個場景使用者可能是車隊管理員或者安全負責人他們只想要一個雙擊就能用的工具。所以封裝exe是必須的。6.1 PyInstaller打包基礎流程我用的打包工具是PyInstaller命令很簡潔pyinstaller -D -w main.py --name SafetyBeltDetector --hidden-import PyQt5.sip-D 生成的是文件夾模式不是單個exe。雖然單文件模式-F更干凈但啟動的時候需要把所有依賴解壓到臨時目錄啟動速度慢3倍以上而且容易被殺毒軟件誤報。我后來果斷選擇了文件夾模式用Inno Setup再封裝成安裝包體驗差別不大但啟動速度和穩定性好很多。打包過程中那幾個經典的坑我逐一碰上過OpenCV的DLL找不到。PyInstaller對cv2的支持不算完美有時候需要手動把opencv的bin目錄加進去。PyQt5的插件目錄被漏掉。具體表現是打包出來的exe一運行就報“could not find or load the Qt platform plugin windows”這個幾乎100%會遇到。解決辦法是在main.py里設置環境變量import os if hasattr(sys, _MEIPASS): os.environ[QT_QPA_PLATFORM_PLUGIN_PATH] os.path.join(sys._MEIPASS, PyQt5, Qt, plugins, platforms)模型權重文件路徑問題。打包后sys._MEIPASS和源碼目錄的路徑不一樣如果用相對路徑加載best.pt會報FileNotFoundError。正確做法是把模型文件放到資源目錄用resource_path函數轉換。6.2 推理性能優化實測數據我針對“1080P視頻CPU推理”這個場景做了一組性能對比方案推理耗時(ms/幀)備注PyTorch FP32 CPU78基線PyTorch FP16 CPU67提升約15%ONNX FP32 CPU58提升約26%ONNX FP16 CPU52有輕微精度損失TensorRT FP16 GPU9需NVIDIA顯卡如果你面向的是普通Windows機器建議直接上ONNX FP16如果用戶有NVIDIA顯卡TensorRT是質的飛躍。不過TensorRT的部署復雜度會上一個臺階而且要針對具體顯卡重新構建engine不適合做通用分發。我目前的分發版本是ONNX FP16同時保留了PyTorch GPU選項。6.3 模型量化的小提醒熱搜詞里有人問“yolo26量化”我順帶說一句。YOLO26直接轉INT8量化精度下降比YOLOv8明顯尤其是在細長小目標上的表現。如果你非要做INT8建議量化后單獨評估mAP50-95不要只看mAP50。我實測下來INT8的mAP50-95降了大概0.06在這種安全告警場景里屬于不可接受所以最終沒有用INT8。7. 駕駛安全監控場景中常見的誤檢與處理策略模型和界面都跑通了不等于項目就結束了。真實場景里你會遇到很多訓練時根本想象不到的干擾這里分享一下我實際碰到過的幾類誤檢案例和處理思路。7.1 衣物紋理和圖案干擾深色條紋襯衫特別是條紋方向和安全帶走向平行的最容易觸發誤檢。模型會把衣服的紋理當成安全帶結構。這個問題的根源是模型學到的是“斜向條狀紋理”而不是“安全帶的空間幾何關系”。我的處理辦法有兩個方向增加負樣本專門收集駕駛員穿條紋、格子衫的畫面標注為空背景讓模型學會區分。后處理限制結合座位位置把檢測框限定在駕駛位上半身的區域衣物紋理就算被識別出來也不在告警邏輯的觸發范圍內。后者對于界面層面更好做因為你不改模型只改規則。7.2 逆光與夜間場景夜間行車時車內光線不足安全帶本身的可見度大幅度降低。我的數據集里夜間樣本只占不到15%導致夜間recall明顯偏低。后來補充了一批夜間IR攝像頭的訓練樣本同時做了亮度抖動的數據增強夜間的誤報率才下來一些。這里提醒一句如果最終部署用的是紅外攝像頭訓練數據里一定要有紅外圖像不能只用普通RGB圖像。兩者在紋理特征上差異很大。7.3 攝像頭安裝角度差異不同的車攝像頭的安裝高度和角度差別很大。有的裝在擋風玻璃上方拍的是俯視角度有的裝在儀表盤拍的是平視角度。同一個模型在不同角度下表現會差很多。我最終用了一個簡單的辦法在界面中加入一個“畫面校準”步驟讓用戶手動框選駕駛位區域。區域框選結果會作為ROI傳入告警邏輯。這樣模型不需要重新訓練只是縮小檢測范圍就能兼容大部分安裝角度。8. 項目交付之后的事一個更現實的版本演進思路目前這套安全帶檢測系統已經能穩定運行但你要說它完美那肯定沒有。我在收尾階段整理了三個后續版本明確要做的方向也分享給想在這個項目基礎上繼續拓展的人。第一是多路攝像頭支持。當前版本只支持單路視頻流但一輛營運車輛至少需要看主駕和副駕甚至還有后排。多路推理可以采用“共享模型實例 獨立視頻流線程”的方式沒必要每個攝像頭各加載一個模型顯存和內存都扛不住。第二是和司機的互動能力。目前系統只能“檢測告警”但實際場景里最好能在檢測到未系安全帶后通過語音播報提醒司機。PyQt里接入一個簡單的語音合成模塊比如pyttsx3很容易但要注意告警頻率避免噪音污染。一次違規只播報兩次是我目前覺得比較合理的策略。第三是把系統往嵌入式設備遷移。熱搜詞里有“yolov8 訓練好的模型怎么部署到嵌入式設備”YOLO26面臨的部署問題完全一樣。我的規劃是導出ONNX后用RKNN-Toolkit轉成Rockchip平臺的格式在RK3588上跑。不過前面也說過了INT8量化對安全帶這類小目標不友好需要小心評估。如果性能確實不夠另一個低成本方案是在邊緣設備上做目標檢測的“預篩選”先用輕量模型檢測“是否有人”再在有人且畫面清晰時傳一幀回服務器做精細判斷。這個方案對帶寬需求也很低適合車隊多個車輛統一的遠程監管平臺。這些方向不是說一次都要做完而是你在做類似項目時心里要清楚“當前版本解決了什么、哪些東西是留給下一版的”。從我自己的體會來說安全帶檢測這個項目最大的收獲不是“跑通了一個YOLO模型”而是養成了“從標注到部署再到用戶反饋”的完整閉環思維。模型只是鏈條里的一環真正讓用戶覺得“好用”的往往是數據質量、告警策略、打包部署這些看起來不起眼的細節。希望這篇內容能幫你少走一些彎路。本文還有配套的精品資源點擊獲取