據(jù)集的構(gòu)建與YOLO目標檢測訓(xùn)練實戰(zhàn))
簡介工程機械識別數(shù)據(jù)集針對目標檢測任務(wù)構(gòu)建面向深度學(xué)習(xí)者與算法工程師解決施工場景中挖掘機、裝載機、自卸卡車、移動起重機、壓路機、推土機、平地機等七類設(shè)備的自動識別問題適合YOLO系列、Faster RCNN、SSD等模型訓(xùn)練與驗證。資源共2000個文件以txt標簽文件為主內(nèi)含一份yaml類別配置文件壓縮包大小約361.74MB配套圖片與txt、xml格式標注且已劃分好訓(xùn)練集、驗證集和測試集可直接接入YOLOv5至YOLOv10等主流框架使用。數(shù)據(jù)包含6338張真實場景圖片既可用于模型效果對比也可用于算法調(diào)參與部署落地。資源還附帶指定類別信息的yaml配置省去手工編寫配置與格式轉(zhuǎn)換的時間。目前已有308人學(xué)習(xí)適合有目標檢測基礎(chǔ)并希望使用現(xiàn)成工程機械數(shù)據(jù)快速開展實驗的開發(fā)者。1. 工程機械識別數(shù)據(jù)集在施工安全場景里的位置工地的視頻監(jiān)控里挖掘機、渣土車和塔吊通常不是畫面主角機位架在圍擋高處幾十米外的設(shè)備在1080p幀里只有三四十像素見方揚塵、夜間紅外噪點和鋼絲繩遮擋還會進一步吃掉輪廓。此時把目標檢測模型從COCO換到專用權(quán)重上漲點不如先把訓(xùn)練數(shù)據(jù)做對。工程機械識別數(shù)據(jù)集要做的就是補上這個空缺把施工場景里的挖掘機、裝載機、壓路機等設(shè)備框出來、命好名、整理成目標檢測框架能直接消費的標注格式。它適合做智慧工地監(jiān)管、施工安全監(jiān)測、無人機巡檢和礦山無人化的算法團隊。這些人碰到的第一道坎往往不是網(wǎng)絡(luò)結(jié)構(gòu)而是數(shù)據(jù)從哪來、類別怎么定、標注按什么規(guī)范做才不返工。2. 工程機械類別規(guī)劃與圖像采集策略2.1 類別體系怎么定按機種還是按作業(yè)狀態(tài)類別是數(shù)據(jù)集的骨架也是后面一切標注成本的上限。直接照搬工程機械分類標準會把類別數(shù)撐到十幾個檢測難度和標注成本都會失控。常見做法是只保留工地高頻出現(xiàn)的機種再按作業(yè)狀態(tài)細分。下表是一套容易落地的六類劃分類別標簽名典型形態(tài)履帶式挖掘機excavator履帶底盤、長工作臂、駕駛室在履帶一側(cè)輪式裝載機loader前端鏟斗、鉸接車身、底盤為輪胎推土機bulldozer前方寬鏟刀、履帶底盤壓路機roller前后大鋼輪、無長臂結(jié)構(gòu)汽車起重機crane_truck伸縮臂、行駛時有支腿收攏自卸車dump_truck后方液壓貨斗、車架較高選類別的核心判斷是應(yīng)用場景。只做設(shè)備禁區(qū)報警六類足夠要區(qū)分挖掘機改裝破碎錘和標準挖斗就需要加“破碎錘狀態(tài)”這個維度但代價是同類設(shè)備不同工況之間必須單獨補樣本。反過來如果強行把履帶式和輪式挖掘機分成兩類工地俯視線里兩者正面輪廓幾乎一樣檢測器很難分開標注一致性也會被打穿。以我接觸過的目標檢測項目類別粒度寧可粗一點先把穩(wěn)定可分的機種做扎實再用第二級分類器去細分工況。2.2 采集渠道監(jiān)控機位、無人機航拍與互聯(lián)網(wǎng)圖像工程機械識別數(shù)據(jù)集和通用目標檢測數(shù)據(jù)集最大的差別在視角分布。COCO里的挖掘機多是平視特寫而工地部署的攝像頭一般在圍擋高處往下看目標同時帶俯仰角和小尺度兩種特性。采集時要覆蓋三個渠道固定機位監(jiān)控畫面用來對齊真實部署場景無人機航拍畫面俯視角更高能補足遠距離小目標樣本互聯(lián)網(wǎng)圖片則用來補充平視角和不同涂裝的顏色多樣性但只作為輔助不能讓這類構(gòu)圖占比太高否則模型對俯視場景的適應(yīng)性會變差。如果有精力公開的施工安全數(shù)據(jù)集也可以作為類別分布和視角規(guī)劃的參考但直接復(fù)用時要注意拍攝設(shè)備和機位差異。每個類別的多樣性不能只按張數(shù)算要按場景數(shù)算。我一般會在采集表里加幾列約束每個類別至少來自100個不同施工場景同一場景內(nèi)連續(xù)幀抽幀間隔不少于2秒避免訓(xùn)練集被高度相似的相鄰幀刷屏目標短邊盡量覆蓋16像素到512像素的區(qū)間因為工程機械在監(jiān)控里經(jīng)常是典型的小目標全是近景大目標會讓模型對遠景設(shè)備失明。夜間的紅外模式、雨天反光、揚塵濃度高這三個狀態(tài)單獨建文件夾記錄后面分析模型掉點原因時能直接對照。2.3 標注規(guī)范與最小目標過濾標注規(guī)范要提前寫成一頁紙再開工否則多人協(xié)作時會出現(xiàn)“同一個模糊目標這個人標那個人不標”的反復(fù)返工。常見做法是目標被遮擋超過70%不標兩輛設(shè)備緊貼時邊框允許輕微重疊但不能互相吞并陰影不納入檢測框目標短邊小于閾值時過濾。這里給一個按短邊閾值過濾 XML 標注的腳本適合剛轉(zhuǎn)完 VOC 格式、還沒清洗標注的階段import xml.etree.ElementTree as ET def filter_small_objects(xml_path: str, min_side: int 20) - None: tree ET.parse(xml_path) root tree.getroot() for obj in root.findall(object): box obj.find(bndbox) x1 float(box.find(xmin).text) y1 float(box.find(ymin).text) x2 float(box.find(xmax).text) y2 float(box.find(ymax).text) if min(x2 - x1, y2 - y1) min_side: root.remove(obj) tree.write(xml_path, encodingutf-8)min_side 怎么定要看部署相機的分辨率。如果1080p畫面里目標最短邊經(jīng)常小于20像素且業(yè)務(wù)還必須要識別那正確方向是把原始幀切塊放大而不是把這些框直接丟掉只有在業(yè)務(wù)只關(guān)心中近距離報警時過濾小框才能幫模型收斂得干凈。過濾前后分別統(tǒng)計一次每張圖片的標注數(shù)量防止某個場景被整體誤刪。注意規(guī)范里要寫明是否區(qū)分“停靠”和“作業(yè)中”兩種狀態(tài)。工程機械作業(yè)時機械臂形態(tài)變化劇烈如果只標??繝顟B(tài)訓(xùn)練完會對作業(yè)姿態(tài)大量漏檢。3. 從標注文件到Y(jié)OLO訓(xùn)練集的格式轉(zhuǎn)換標注工具最常見的輸出是 VOC XML 和 COCO JSON而 yolov5、yolov8 原生訓(xùn)練要吃 YOLO txt 格式。格式轉(zhuǎn)換看起來是體力活但坐標系的坑會讓前面所有標注工作報廢這一章把轉(zhuǎn)換邏輯和數(shù)據(jù)劃分一起講清楚。3.1 標注格式對比VOC XML、COCO JSON 與 YOLO txt格式坐標表示常見來源典型注意點VOC XML絕對像素 x1,y1,x2,y2LabelImg類別名在name節(jié)點可能帶中文COCO JSON絕對像素 x,y,w,hRoboflow、CVATannotations 里可能有 segments 字段轉(zhuǎn)換時忽略YOLO txt歸一化 cx,cy,w,hyolov5/yolov8類別 id 從 0 開始一行一個目標VOC 和 COCO 的差別不只是字段名COCO 的 bbox 是左上角和寬高YOLO 要求的是中心點和寬高而且全部要除以圖像寬高做歸一化。圖像尺寸在 XML 里由 size 節(jié)點提供COCO JSON 則在 images 數(shù)組里拿錯尺寸會把標注映射到錯誤位置。有云端標注經(jīng)驗的可以對比 COCO 2017 數(shù)據(jù)集結(jié)構(gòu)的組織方式本質(zhì)上都是把逐張圖片的標注匯總成一個大的 JSON 字典。3.2 Python 腳本VOC 轉(zhuǎn) YOLO txt 并完成數(shù)據(jù)集劃分下面是工程里能直接改用的轉(zhuǎn)換腳本。它先讀 XML把標簽映射成類別 id再輸出與圖片同名的 txt 文件最后按視頻片段劃分 train/val。import random import xml.etree.ElementTree as ET from pathlib import Path CLASSES [excavator, loader, bulldozer, roller, crane_truck, dump_truck] def voc_xml_to_yolo_txt(xml_path: str, label_dir: str) - None: tree ET.parse(xml_path) root tree.getroot() size root.find(size) img_w int(size.find(width).text) img_h int(size.find(height).text) lines [] for obj in root.findall(object): name obj.find(name).text.strip() if name not in CLASSES: continue box obj.find(bndbox) x1 float(box.find(xmin).text) y1 float(box.find(ymin).text) x2 float(box.find(xmax).text) y2 float(box.find(ymax).text) cx ((x1 x2) / 2) / img_w cy ((y1 y2) / 2) / img_h bw (x2 - x1) / img_w bh (y2 - y1) / img_h lines.append(f{CLASSES.index(name)} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}) Path(label_dir).mkdir(parentsTrue, exist_okTrue) out_path Path(label_dir) / (Path(xml_path).stem .txt) out_path.write_text(\n.join(lines), encodingutf-8) xml_files sorted(Path(annotations).glob(*.xml)) for xml_file in xml_files: voc_xml_to_yolo_txt(str(xml_file), labels)代碼邏輯分三段先解析 size 字段拿到圖寬高再把每個 object 的絕對坐標換算成歸一化的中心寬高最后批量寫出 txt。換算時注意算完寬高后要保持浮點精度保留6位小數(shù)足夠。txt 文件名稱必須和圖片名稱完全一致目錄再分成 labels/train 和 labels/val。數(shù)據(jù)劃分比轉(zhuǎn)格式更容易被忽視。如果視頻數(shù)據(jù)是按幀抽的直接對 xml 文件做隨機 shuffle 會把同一臺挖掘機的相鄰幀同時分到訓(xùn)練集和驗證集模型相當(dāng)于見過目標后再考一次val 的 mAP 虛高上線必翻車。正確做法是先按視頻片段 ID 分組完整片段落入 train 或 val再用固定隨機種子切一次 80/20# 文件名形如 site01_clip03_000123.jpg取前兩段作為片段ID video_ids sorted({_.join(f.stem.split(_)[:2]) for f in xml_files}) random.seed(42) random.shuffle(video_ids) train_count int(len(video_ids) * 0.8) train_videos set(video_ids[:train_count]) val_videos set(video_ids[train_count:]) for xml_file in xml_files: vid _.join(xml_file.stem.split(_)[:2]) split train if vid in train_videos else val voc_xml_to_yolo_txt(str(xml_file), flabels/{split})按片段劃分的價值在于驗證集更接近真實部署——部署時模型面對的永遠是新場景、新工地不可能和訓(xùn)練視頻有連續(xù)幀。劃分完成后統(tǒng)計一下兩邊每類目標的框數(shù)量如果裝載機在 val 里只有幾十個框評估指標沒意義應(yīng)該在采集階段補樣本。3.3 目錄結(jié)構(gòu)與 data.yaml目錄結(jié)構(gòu)dataset/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── data.yamldata.yamltrain: dataset/images/train val: dataset/images/val nc: 6 names: 0: excavator 1: loader 2: bulldozer 3: roller 4: crane_truck 5: dump_truckdata.yaml 里的 names 順序必須和轉(zhuǎn)換腳本里的 CLASSES 一致名稱錯位會在訓(xùn)練時出現(xiàn)“標簽是第一類但模型學(xué)成第二類”的問題。路徑建議寫相對 dataset 根目錄的形式訓(xùn)練命令在根目錄執(zhí)行避免換機器后絕對路徑失效。另外不要用中文做類別名或文件名yaml 解析和多框架兼容性都會出問題。4. 工程機械識別模型訓(xùn)練與小目標優(yōu)化4.1 訓(xùn)練環(huán)境與顯存需求yolov8 訓(xùn)練自己的數(shù)據(jù)集需要用到 GPU 嗎訓(xùn)練階段強烈建議 GPU純 CPU 訓(xùn)練一個幾百張圖的工程機械數(shù)據(jù)集要幾小時迭代實驗根本跑不動推理階段 CPU 可以頂住但工地如果有多路視頻流還是建議 GPU 做批量推理。顯存需求由模型規(guī)模、輸入分辨率和 batch 共同決定工程機械數(shù)據(jù)經(jīng)常需要開高分辨率這里給一組參考值配置顯存占用參考適合場景yolov8s imgsz640 batch16約8GB快速驗證類別少yolov8m imgsz640 batch16約12GB中大規(guī)模數(shù)據(jù)集yolov8s imgsz1280 batch8約14GB小目標多的場景yolov8x imgsz1280 batch8約24GB以上追求上限訓(xùn)練慢分辨率從640提到1280后輸入面積變成四倍顯存開銷按面積倍數(shù)上漲而小目標 AP 的提升往往抵消不了訓(xùn)練時間的增加。初版訓(xùn)練建議從640開始看清混淆矩陣后再決定要不要升分辨率。4.2 訓(xùn)練參數(shù)imgsz、epochs、anchors 與多尺度啟動命令yolo detect train \ modelyolov8s.pt \ datadata.yaml \ imgsz640 \ batch16 \ epochs200 \ patience30 \ scale0.5 \ hsv_h0.015 \ hsv_s0.7 \ hsv_v0.4參數(shù)說明model 用預(yù)訓(xùn)練權(quán)重而不是隨機初始化工程機械在 COCO 里類別少但底層紋理和邊緣特征仍然有效imgsz640 是起步值epochs 給 200 輪配 patience30 做早停數(shù)據(jù)集小的時候模型很快收斂早停能避免過擬合到某個場景的涂裝顏色。scale0.5 是縮放增強范圍工地監(jiān)控中目標尺寸跨度大這個值不建議關(guān)。hsv_h、hsv_s、hsv_v 控制色調(diào)、飽和度和明度抖動施工場景白天黑夜對比強烈適度抖動能提升光照魯棒性。yolov5 訓(xùn)練自己的數(shù)據(jù)集也是同一套流程差別只在命令行參數(shù)名比如 yolov5 用--img 640 --epochs 200訓(xùn)練邏輯沒有本質(zhì)區(qū)別。再提醒一個錨框問題yolov5 和 yolov8 在訓(xùn)練時會自動從標注里重新聚類 anchors自建數(shù)據(jù)集的框比例和 COCO 差得很遠這一步保留自動計算就行不要手動沿用 COCO 的預(yù)設(shè)錨框。數(shù)據(jù)集規(guī)模越偏這個影響越明顯尤其是塔吊這種長寬比極端的目標。4.3 小目標檢測、遮擋和類別不均衡的處理策略工程機械識別數(shù)據(jù)集里最影響落地的是小目標檢測。一個畫面里 16 像素的挖掘機檢測器和人眼一樣只能看到一小團紋理完全靠提高輸入分辨率性價比太低。常見的處理路徑有三條。第一是圖像切片把 1080p 原始圖像切成有重疊的 patchpatch 尺寸常用640步長用320到512重疊部分保證跨 patch 的目標至少在一個 patch 里完整。切片后目標短邊等效放大小目標 AP 會直接提升推理時也要走同樣的切片流程否則訓(xùn)練和部署不一致。第二是 copy-paste 增強把標注好的挖掘機區(qū)域摳出來隨機貼到?jīng)]有設(shè)備的背景上背景來自同一批采集數(shù)據(jù)即可。這對小目標數(shù)量提升非常明顯但要注意把設(shè)備貼在天空或圍擋頂部這類不可能出現(xiàn)的區(qū)域否則模型會學(xué)出錯誤的上下文依賴。第三是類別加權(quán)裝載機、壓路機這類數(shù)量少的類別可以按 1:2 或 1:3 的采樣權(quán)重過采樣不要為了均衡把挖掘機的樣本砍掉一半數(shù)據(jù)集的多樣性本來靠多數(shù)類撐起來的。遮擋問題不要只依賴自然樣本。工地里鋼絲繩、圍擋和來往人員會頻繁遮擋設(shè)備標注時把被遮擋但可見部分按實際邊界框標出來訓(xùn)練時用隨機遮擋增強手法制造更多遮擋上下文。如果驗證集里某個類別的 recall 明顯低于其他類先看這類標注框數(shù)量占比再看夜間和雨天樣本占比不要一上來就換損失函數(shù)。5. 從 mAP 到上線的迭代技巧5.1 正確讀評價指標mAP0.5 與 mAP0.5:0.95工程機械識別屬于目標檢測評價體系沿用目標檢測評價指標的通用配置。提交實驗時最好同時看 mAP0.5 和 mAP0.5:0.95 兩個值mAP0.5 衡量寬松條件下的檢測能力和業(yè)務(wù)里“框住大概位置”的報警需求接近mAP0.5:0.95 更苛刻能反映出框位置的精度對后期做設(shè)備測距和軌跡跟蹤的人更關(guān)鍵。單看總 mAP 會掩蓋很多問題自建數(shù)據(jù)集一定要按類別看 AP。工程機械場景里挖掘機和自卸車樣本多、AP 自然高壓路機樣本少、AP 通常被拉低。小目標 AP 低于大目標 AP 是正?,F(xiàn)象但如果小目標 AP 只有大目標的一半還不到優(yōu)先檢查切片流程而不是堆模型參數(shù)量。5.2 硬樣本挖掘與主動學(xué)習(xí)閉環(huán)第一版模型訓(xùn)練完成后把訓(xùn)練集里漏檢和誤檢的樣本撈出來回填標注迭代一輪效果往往比直接加深網(wǎng)絡(luò)更明顯。具體操作是用訓(xùn)練好的模型對未標注的原始視頻幀做推理設(shè)置低置信度閾值0.3把得分在0.3到0.7之間的檢測框?qū)С龀纱_認列表交給標注員只確認這些區(qū)域。這些硬樣本集中在揚塵遮擋、夜間紅外和極端小目標這幾個難點擊中幾輪之后數(shù)據(jù)集質(zhì)量比均勻補數(shù)據(jù)提升更快。我還會把誤檢最高的背景類別單獨截出來做負樣本集比如圍擋上的施工銘牌被誤檢成設(shè)備這類負樣本對降低誤報率的作用是純標注正樣本替代不了的。5.3 部署時的滑動窗口推理與結(jié)果合并高分辨率圖像部署時可以沿用訓(xùn)練時的切片策略窗口預(yù)測的坐標是局部的合并時要加上窗口在原圖中的偏移量def sliding_window_infer(model, image, patch_size640, stride512): h, w image.shape[:2] detections [] for y in range(0, h, stride): for x in range(0, w, stride): patch image[y:y patch_size, x:x patch_size] results model(patch, conf0.25, imgsz640) for box in results[0].boxes: x1, y1, x2, y2 box.xyxy[0].tolist() detections.append([x x1, y y1, x x2, y y2, float(box.conf[0]), int(box.cls[0])]) return detections這個簡單實現(xiàn)會返回所有候選框但同一個目標在重疊窗口里會出現(xiàn)兩次最后必須做一次 NMS 合并否則設(shè)備計數(shù)和軌跡跟蹤都會翻倍。本地小項目可以用 cv2.dnn.NMSBoxes服務(wù)端用 torchvision.ops.nms。窗口切片和 NMS 合并完把每輪推理結(jié)果回寫進待標注隊列后續(xù)訓(xùn)練只圍繞這些漏檢和誤檢框補樣本數(shù)據(jù)集的增長就會始終集中在當(dāng)前模型最薄弱的部分。本文還有配套的精品資源點擊獲取