搭建實戰(zhàn)指南)
做船舶檢測這個項目其實起因挺樸素的——某天接到一個水運管理方向的需求對方希望用視覺手段自動識別航道內(nèi)過往船只的類別給調(diào)度、監(jiān)管和統(tǒng)計提供輔助。當(dāng)時市面上能直接摳來的通用目標(biāo)檢測方案不少但真正落到“船舶分類識別檢測”這個具體場景邊界條件比想象中復(fù)雜得多。這篇文章我打算把基于YOLOv8完整搭建一套船舶分類識別檢測系統(tǒng)的過程捋清楚包括數(shù)據(jù)集怎么準(zhǔn)備、模型怎么訓(xùn)練、UI界面怎么接、部署階段踩了哪些坑。想復(fù)現(xiàn)同款項目、或者準(zhǔn)備從零做圖像識別應(yīng)用的同學(xué)這套流程可以當(dāng)參考。1. 船舶識別檢測任務(wù)從需求到技術(shù)選型1.1 船舶檢測到底解決什么問題船舶識別不是一個新問題但它和通用的行人、車輛檢測有明顯差異。水面的背景是動態(tài)的受光照、波浪、霧霾影響極大船只本身又包含很多種形態(tài)從集裝箱貨輪到小型漁船長度從幾米到幾百米都有。傳統(tǒng)方案靠人工盯監(jiān)控屏費眼且容易漏尤其在夜間多路視頻的場景下人力完全跟不上。當(dāng)時梳理下來需求方要的核心能力有三塊一是區(qū)分畫面里有沒有船二是給船打上類別標(biāo)簽比如貨船、漁船、客船、帆船、拖船三是盡量給出置信度方便后續(xù)系統(tǒng)根據(jù)可信程度做人工復(fù)核。這三塊需求直接決定了項目的技術(shù)路線必須用目標(biāo)檢測模型而且檢測和分類要一步到位不能先檢測再單獨分類那樣兩套模型串聯(lián)會引入額外延遲和誤差累積。1.2 為什么最終選擇YOLOv8目標(biāo)檢測的技術(shù)路線其實有好幾種經(jīng)典的兩階段有Faster R-CNN系列單階段有YOLO系、SSD、還有基于Transformer的DETR之類。兩階段精度高但慢DETR收斂慢且對硬件要求偏高在工業(yè)落地場景里大家更看重的是“接近實時的推理速度”和“能直接在普通顯卡甚至CPU上跑”。YOLO系在這塊的優(yōu)勢一直很突出而選擇YOLOv8而不是繼續(xù)用V5主要看中三點第一YOLOv8是無錨框檢測解耦了分類頭和回歸頭對形狀差異很大的目標(biāo)比如細(xì)長型船只更友好省去了調(diào)錨框尺寸的環(huán)節(jié)。第二它自帶C2f結(jié)構(gòu)梯度流更豐富小目標(biāo)特征提取能力有提升這對遠(yuǎn)處小船的檢測很關(guān)鍵。第三是生態(tài)成熟Ultralytics的倉庫把訓(xùn)練、驗證、導(dǎo)出封裝得相當(dāng)順手從拿到環(huán)境到跑通第一次訓(xùn)練周期非常短。除了模型本身我也把數(shù)據(jù)集來源、標(biāo)注工具、部署方式一起納入選型判斷。如果選純Transformer方案數(shù)據(jù)集規(guī)模需要非常大才能體現(xiàn)優(yōu)勢而船舶類的公開數(shù)據(jù)不多前期還得自采自標(biāo)YOLOv8對中小規(guī)模數(shù)據(jù)集更友好迭代起來也快。1.3 整體架構(gòu)規(guī)劃系統(tǒng)的整體架構(gòu)我一開始就按閉環(huán)來設(shè)計包含數(shù)據(jù)層、訓(xùn)練層、推理服務(wù)層和展示層。數(shù)據(jù)層負(fù)責(zé)圖片和視頻整理、標(biāo)注、劃分?jǐn)?shù)據(jù)集訓(xùn)練層用YOLOv8執(zhí)行模型訓(xùn)練和驗證推理服務(wù)層負(fù)責(zé)加載權(quán)重、執(zhí)行檢測、做后處理和格式轉(zhuǎn)換展示層就是用戶看得見摸得著的UI界面可以用桌面程序也可以用Web頁面。這套架構(gòu)的優(yōu)點是每一層都能獨立替換。比如訓(xùn)練層以后想換更輕量的模型或者推理層想加一個跟蹤模塊都不會牽一發(fā)而動全身。UI界面我最終選擇了桌面端方案因為現(xiàn)場值班人員更習(xí)慣本地軟件不依賴瀏覽器和服務(wù)器資源部署也簡單。2. 數(shù)據(jù)準(zhǔn)備的完整鏈路采集、清洗、標(biāo)注與增強2.1 數(shù)據(jù)集來源與構(gòu)成模型能不能用60%以上取決于數(shù)據(jù)質(zhì)量。船舶識別的公開數(shù)據(jù)集確實存在但類別分布和真實場景有差距往往偏重某一類船或者分辨率太單一。所以我采取了“公開數(shù)據(jù)預(yù)熱 自采數(shù)據(jù)校準(zhǔn)”的組合策略。公開部分我篩選了以水域目標(biāo)檢測為核心的幾類數(shù)據(jù)集主要用來讓模型先見到足夠多的大樣貌變化。自采部分則更貼合實際部署場景在河邊、港口、跨河大橋等位置架設(shè)相機采集不同時間段、不同天氣、不同距離下的船舶畫面連續(xù)記錄一周形成素材庫。這個過程看起來枯燥但非常必要因為自采數(shù)據(jù)能覆蓋部署現(xiàn)場的光線角度、水面波紋、船只涂裝這些“現(xiàn)場特征”。數(shù)據(jù)總量大約整理了八千多張圖片按8:1:1劃分訓(xùn)練集、驗證集、測試集。反復(fù)提醒自己的一點是劃分時必須保證同一艘船在不同幀里的畫面不能同時出現(xiàn)在訓(xùn)練集和驗證集否則驗證指標(biāo)會虛高。2.2 類別定義與樣本平衡類別定義直接決定了系統(tǒng)的實用性。太多類別會讓樣本數(shù)量被稀釋太少又達不到“分類識別”的需求。我最終保留了六類集裝箱貨船、散貨船、客船、漁船、帆船、拖船。這六類基本覆蓋了內(nèi)河和近海常見船型也各有辨識特征比如集裝箱船甲板整齊、漁船上層建筑偏尾部且常帶吊臂。樣本平衡是繞不開的坑。拍回來的素材里貨船數(shù)量明顯多于帆船因為貨船航速慢、在畫面里停留時間長。如果直接用原始比例訓(xùn)練模型對帆船和拖船的召回率會很難看。處理辦法是數(shù)據(jù)加權(quán)對于少樣本類別在訓(xùn)練時提高其loss權(quán)重同時用上下翻轉(zhuǎn)、旋轉(zhuǎn)、尺度變化進行針對性擴充。實際操作中我還在訓(xùn)練輪次中途做了類別分布統(tǒng)計確認(rèn)少數(shù)類參與訓(xùn)練的頻率沒有低到離譜。2.3 標(biāo)注規(guī)范的細(xì)節(jié)標(biāo)注質(zhì)量直接決定模型上限。這個項目里我明確了幾條標(biāo)注紀(jì)律遮擋超過50%的目標(biāo)不標(biāo)目標(biāo)小于32x32像素且肉眼難以判斷類別的寧可不標(biāo)緊挨著的兩艘船尤其是并靠的漁船和駁船框邊必須緊貼船體輪廓不能為了省事拉一個大框把兩艘船框進去。標(biāo)注格式用的是YOLO的txt格式每行是“類別id 中心點x 中心點y 寬度 高度”所有坐標(biāo)都?xì)w一化到0到1。這個格式看起來簡單但有個隱蔽問題如果圖片尺寸變了歸一化坐標(biāo)不用改可一旦在標(biāo)注后對圖片做了裁剪坐標(biāo)體系就全亂了。所以我的流程是先統(tǒng)一把所有圖片resize到同尺寸再做標(biāo)注避免后續(xù)轉(zhuǎn)換出錯。標(biāo)注工具我選了一款開源的圖形化標(biāo)注軟件這類工具大同小異關(guān)鍵在于支持快捷鍵連續(xù)標(biāo)注能大幅提升標(biāo)圖效率。八千多張圖單人標(biāo)完大概用了兩周。如果想壓縮時間可以用大型模型先出一版粗糙標(biāo)注人工再修正但涉及類別定義比較細(xì)致的場景我不建議完全依賴自動標(biāo)注。2.4 數(shù)據(jù)增強策略數(shù)據(jù)增強不能亂加。船舶場景和通用物體不同水面有方向性波紋和倒影的存在導(dǎo)致過度旋轉(zhuǎn)增強會產(chǎn)生不真實樣本。我實測下來水平翻轉(zhuǎn)是最安全的因為它不破壞船身結(jié)構(gòu)、只是鏡像符合水面場景的實際情況。再往下是輕度隨機旋轉(zhuǎn)控制在正負(fù)15度以內(nèi)。超過這個范圍船身傾斜得太厲害會讓模型學(xué)到“斜著的船”這種假規(guī)律。HSV色域增強也有用主要是應(yīng)對清晨和傍晚偏暖色、陰天偏灰的情況實際設(shè)置成H偏移較小、S和V偏移中等即可。馬賽克增強能提高小目標(biāo)檢測效果因為四張圖拼接出一張大圖相當(dāng)于變相縮小了目標(biāo)尺寸模型被迫去學(xué)更精細(xì)的特征。但馬賽克增強在訓(xùn)練后期要逐漸關(guān)掉否則模型容易對拼接邊界產(chǎn)生依賴我在最后50個epoch把增強強度降到了原來的30%。3. YOLOv8模型訓(xùn)練配置文件、參數(shù)調(diào)優(yōu)與訓(xùn)練監(jiān)控3.1 模型版本的選擇YOLOv8有n、s、m、l、x五個規(guī)格分別對應(yīng)從輕量到超大的參數(shù)量。選擇哪個規(guī)格不能只看精度排行更要看部署環(huán)境的算力。項目最終運行在一臺配備中等性能顯卡的工控機上同時要保證UI界面操作流暢所以一開始就不考慮l和x。我在n和s之間做了對比n版本推理速度極快但小目標(biāo)召回偏弱s版本精度提升明顯、速度損失可接受。最終訓(xùn)練選的是YOLOv8s后續(xù)推理時把batch重新置為1實際單幀耗時大約在12到18毫秒完全能滿足實時需求。規(guī)格選定之后我用官方預(yù)訓(xùn)練權(quán)重作為初始權(quán)重。預(yù)訓(xùn)練模型在COCO數(shù)據(jù)集上見過大量通用物體遷移到船舶場景能省很多訓(xùn)練時間尤其是船和“箱子”“車輛”這類形狀相似的物體遷移特征可以直接復(fù)用。如果隊伍里沒有大算力顯卡用預(yù)訓(xùn)練權(quán)重微調(diào)是性價比最高的方案。3.2 訓(xùn)練參數(shù)逐項解讀訓(xùn)練參數(shù)的設(shè)置這里很多數(shù)值是靠測試得到的不建議無腦照搬。我的核心配置如下輸入分辨率640x640。這個尺寸兼顧了小目標(biāo)檢測和顯存占用。再往上加到960精度有提升但推理耗時上漲明顯對實時系統(tǒng)不劃算。epoch設(shè)置為200。前100輪loss下降快后100輪主要用來收斂細(xì)節(jié)。到第170輪左右驗證集的mAP開始周期性震蕩說明學(xué)習(xí)率需要衰減。batch size設(shè)定為16。太大會導(dǎo)致單卡顯存溢出太小則梯度不穩(wěn)定。如果顯存不夠優(yōu)先減batch并同步降低學(xué)習(xí)率。初始學(xué)習(xí)率0.01使用余弦退火調(diào)度最小的學(xué)習(xí)率設(shè)為初始值的十分之一。余弦退火的好處是讓loss在訓(xùn)練后期平緩逼近不容易在極小值附近反復(fù)橫跳。權(quán)重衰減設(shè)為0.0005用于抑制過擬合。樣本有幾萬張模型參數(shù)量幾千萬不加約束訓(xùn)練后期很容易在訓(xùn)練集上刷分、驗證集上翻車。類別權(quán)重我在少樣本類上上調(diào)到了基準(zhǔn)的1.5倍。這個值不是越大越好太大會導(dǎo)致模型為了強湊少數(shù)類而誤判多數(shù)類。訓(xùn)練啟動的命令其實很簡單yolo detect train dataship.yaml modelyolov8s.pt epochs200 imgsz640 batch16 lr00.01 cos_lrTrue weight_decay0.0005訓(xùn)練過程中可以隨時中斷Ultralytics會保存最近一次的權(quán)重文件恢復(fù)訓(xùn)練時直接指定最新的pt文件即可。這個機制在調(diào)整參數(shù)后重新續(xù)跑時救了不少次。3.3 訓(xùn)練過程監(jiān)控與中斷恢復(fù)訓(xùn)練監(jiān)控最重要的一項是分辨“欠擬合”和“過擬合”的信號。我每20個epoch手動看一眼驗證集上的混淆矩陣而不是只盯著loss曲線。loss曲線下降到一個平臺不代表模型真的學(xué)會了有可能只是訓(xùn)練集的記憶游戲。有一次訓(xùn)練到第120個epoch時訓(xùn)練loss還在下降驗證集mAP反而掉了一個點這就是典型過擬合信號我果斷停止了訓(xùn)練回滾到第100輪的權(quán)重。監(jiān)控工具上我用了Ultralytics自帶的訓(xùn)練日志和TensorBoard兩種方式并行。TensorBoard里主要看train/loss、val/loss、metrics/precision、metrics/recall四條曲線。如果precision和recall在訓(xùn)練后期出現(xiàn)此消彼長的剪刀差通常是置信度閾值沒校準(zhǔn)或者正負(fù)樣本不平衡需要回到數(shù)據(jù)層面找原因。另外一個值得記錄的細(xì)節(jié)是最好把驗證集中預(yù)測錯誤的圖片單獨存到一個文件夾每輪訓(xùn)練結(jié)束后看一眼錯誤樣本的變化趨勢。剛開始錯誤集中在“把波浪反光當(dāng)船”中后期基本消失訓(xùn)練到末尾時錯誤樣本主要是“近距離兩船并靠互相遮擋”這個問題靠調(diào)參無法根治最終通過后處理NMS邏輯做了緩解。3.4 指標(biāo)評估與壞例分析模型訓(xùn)練完我只看四個指標(biāo)Precision、Recall、mAP50、mAP50-95。其中mAP50-95比mAP50更嚴(yán)格它統(tǒng)計了不同IoU閾值下的平均精度能反映出框位置的準(zhǔn)確性。船舶檢測場景里框位置抖動會影響后續(xù)對船舶航向的估算所以mAP50-95一定不能太低。最終我的驗證結(jié)果是mAP50大約93%mAP50-95大約77%對于六分類的中等規(guī)模數(shù)據(jù)集算是正常偏上水平。壞例分析階段我重點看了三類錯誤。一是把航標(biāo)、浮筒、礁石誤判成小船這類錯誤往往因為標(biāo)注數(shù)據(jù)里缺少“負(fù)樣本”進行約束。解決方法是在背景圖片里隨機加入部分高相似干擾物并標(biāo)為背景。二是把遠(yuǎn)距離貨船和客船混淆因為遠(yuǎn)處像素太少兩類船的紋理細(xì)節(jié)全部丟失只能靠輪廓猜測。解決方向是增加“遠(yuǎn)距離高分辨率成對數(shù)據(jù)”讓模型看見同一條船在不同距離下對應(yīng)的特征差異。三是夜間燈光干擾有些船的甲板燈在低照度下顯得異常明亮和岸邊霓虹燈混雜導(dǎo)致誤檢這要靠數(shù)據(jù)擴充和圖像預(yù)處理聯(lián)合去解決。4. 從模型權(quán)重到可用的UI系統(tǒng)推理鏈路與界面設(shè)計4.1 技術(shù)棧選擇桌面端還是Web端模型訓(xùn)練好只是第一步交付物必須是一個操作界面友好的系統(tǒng)。技術(shù)路線我在Flask Web端和PySide6桌面端之間猶豫過。Web端的好處是多人訪問方便服務(wù)部署在一臺機器上值班室和辦公室都能看缺點是視頻流回傳延遲、瀏覽器兼容性調(diào)整、以及并發(fā)訪問時的資源管理都需要額外工作量??紤]到實際使用環(huán)境通常是值班室里的固定工控機桌面端更直接所以我選了PySide6。PySide6是Qt的Python綁定信號槽機制對多線程界面控制特別合適。用它寫一個檢測面板左側(cè)放視頻畫面右側(cè)放參數(shù)面板和結(jié)果列表底欄顯示FPS和檢測計數(shù)樣式調(diào)整自由度高。和OpenCV的HighGUI相比PySide6做出來的東西起碼像個正經(jīng)軟件而不是調(diào)試窗口。4.2 核心功能模塊設(shè)計UI的功能模塊我按照使用流程拆成了四塊輸入模塊、檢測模塊、結(jié)果展示模塊、數(shù)據(jù)管理模塊。輸入模塊支持三種來源單張圖片、視頻文件、實時攝像頭信號。視頻文件用OpenCV逐幀讀取攝像頭信號通過設(shè)備的索引或者RTSP流地址接入。檢測模塊封裝了一個Detector類負(fù)責(zé)加載模型、執(zhí)行推理、后處理并向外提供每幀的檢測列表。結(jié)果展示模塊負(fù)責(zé)在畫面上繪制邊界框、類別標(biāo)簽、置信度并在右側(cè)表格里同步更新記錄。數(shù)據(jù)管理模塊支持把檢測結(jié)果導(dǎo)出為CSV或者帶標(biāo)注的視頻文件方便留檔。檢測邏輯的代碼結(jié)構(gòu)需要提前規(guī)劃不能在界面回調(diào)里直接寫模型推理。我的Detector類大致長這樣from ultralytics import YOLO class ShipDetector: def __init__(self, weights_path, conf_thres0.25, iou_thres0.45): self.model YOLO(weights_path) self.conf_thres conf_thres self.iou_thres iou_thres def detect_frame(self, frame): results self.model.predict( sourceframe, confself.conf_thres, iouself.iou_thres, verboseFalse, devicecuda:0 ) detections [] for box in results[0].boxes: detections.append({ cls: results[0].names[int(box.cls)], conf: float(box.conf), box: [float(v) for v in box.xyxy[0]] }) return detections這樣界面層只需要把讀到的幀交給detect_frame拿回列表后繪制即可。模型推理和界面繪制完全解耦后面想換成ONNX或者TensorRT的推理后端只需要改Detector內(nèi)部實現(xiàn)界面代碼不動。4.3 實時視頻流與線程模型UI卡頓是這類應(yīng)用最容易翻車的地方。如果直接在界面主線程里做視頻讀取和模型推理畫面必然一卡一卡甚至觸發(fā)Qt的“無響應(yīng)”警告。解決辦法是把視頻讀取和模型推理放到兩個QThread里界面主線程只負(fù)責(zé)接收“已經(jīng)繪制好的幀”并顯示。我的線程結(jié)構(gòu)是CaptureThread負(fù)責(zé)從攝像頭或視頻文件取幀通過信號發(fā)給DetectThreadDetectThread執(zhí)行模型推理并把推理結(jié)果連同原始幀一起發(fā)回主線程主線程收到后在Qt的QLabel上繪制邊界框并刷新結(jié)果表格。這里要注意的是OpenCV的VideoCapture對象不能跨線程傳遞它必須在CaptureThread內(nèi)部創(chuàng)建并循環(huán)讀取。還有一個細(xì)節(jié)是隊列容量。如果檢測速度跟不上視頻幀率中間隊列會無限堆積舊幀導(dǎo)致延遲越來越大。我用了有界隊列容量設(shè)為5滿了就丟最舊的幀。實際體驗中犧牲一小部分幀率換來的實時性比攢一堆延遲幀更有價值。4.4 推理加速與模型導(dǎo)出實時視頻流跑起來之后我進行了兩輪加速優(yōu)化。第一輪是把模型從PyTorch權(quán)重導(dǎo)出成ONNX然后使用ONNX Runtime做推理。ONNX Runtime在保持精度的前提下比原生PyTorch的推理快20%到40%這是因為它做了算子融合和內(nèi)存復(fù)用。導(dǎo)出命令非常簡單yolo export modelruns/train/exp/weights/best.pt formatonnx opset12導(dǎo)出后注意檢查輸出節(jié)點YOLOv8的ONNX模型輸出的形狀是(1, 84, 8400)84的前四位是cx、cy、w、h加上80個COCO類別得分。因為我們是六分類模型會輸出(1, 10, 8400)所以寫后處理時要根據(jù)實際類別數(shù)調(diào)整解析邏輯。第二輪優(yōu)化是把ONNX進一步轉(zhuǎn)成TensorRT的engine文件在NVIDIA顯卡上跑能快更多但這個環(huán)節(jié)依賴CUDA和TensorRT版本環(huán)境配置麻煩只推薦在正式部署時做。5. 實戰(zhàn)中踩過的坑與補救方案5.1 小目標(biāo)漏檢一個長尾問題項目剛跑通時畫面里的大船檢測效果很棒但稍遠(yuǎn)一點的船經(jīng)常漏掉。這個問題不是“模型不夠準(zhǔn)”而是數(shù)據(jù)里小目標(biāo)樣本太少了。我統(tǒng)計了訓(xùn)練集的目標(biāo)框尺寸分布發(fā)現(xiàn)小于64x64像素的目標(biāo)占比不到15%。模型在訓(xùn)練時大概率沒見過多少小目標(biāo)自然學(xué)不到對應(yīng)特征。補救措施從兩端入手。數(shù)據(jù)端我把遠(yuǎn)處的船只區(qū)域單獨裁剪出來放大后并入訓(xùn)練集相當(dāng)于給小目標(biāo)“多拍了特寫”同時把大圖中的目標(biāo)降采樣作為小目標(biāo)樣本。模型端訓(xùn)練時開啟多尺度訓(xùn)練輸入尺寸在480到960之間隨機波動讓模型適應(yīng)不同尺度。經(jīng)過一輪迭代測試集上小目標(biāo)召回率提高了近20個點。這個坑本身不可怕怕的是不看數(shù)據(jù)分布盲目調(diào)參。5.2 近距離多船互相遮擋港口里船舶并靠是常態(tài)檢測結(jié)果經(jīng)常出現(xiàn)一個框把兩條船框住或者兩條船的置信度都偏低。YOLOv8的后處理NMS設(shè)計默認(rèn)是抑制同一區(qū)域內(nèi)的重疊框但兩船重疊時真實語義上是兩個目標(biāo)nms反而會殺掉一個正確框。我的處理方案是降低IoU閾值從默認(rèn)的0.45調(diào)低到0.3讓重疊區(qū)域的多個候選框更容易同時保留。另一個輔助做法是給結(jié)果列表增加“是否遮擋”的標(biāo)記當(dāng)某個框的置信度在0.4以下且和另一個高置信度框大比例重疊時系統(tǒng)自動提示人工復(fù)核。這個問題我認(rèn)為沒有完美解法最終得靠部署策略容忍一定誤檢再由人工兜底。5.3 夜間與惡劣天氣的表現(xiàn)一開始訓(xùn)練數(shù)據(jù)都是白天晴朗天氣部署測試時夜里畫面一上檢測率直接掉了一大截。原因很直白模型沒見過夜間的特征分布。夜間船只在探照燈下是高對比度輪廓背景水面完全黑色這和白天暗背景下的小目標(biāo)檢測完全不是一回事。解決方式分兩步。第一晚間專門采集了一部分真實畫面加入訓(xùn)練包括靠燈光的、月光下的、完全無光靠紅外補光的。第二UI界面上增加了圖像預(yù)處理選項比如夜間模式自動做直方圖均衡化和輕度降噪讓畫面細(xì)節(jié)更明顯。這兩步都上了以后夜間檢測率才恢復(fù)到白天的八成左右。這個案例給我的教訓(xùn)是數(shù)據(jù)采集階段就要把“運行環(huán)境的極端情況”當(dāng)成一等公民來設(shè)計而不是事后補課。5.4 類別不平衡導(dǎo)致的誤判前面提到過帆船樣本少所以訓(xùn)練時給了額外權(quán)重。但權(quán)重加過頭模型又變得過度敏感把一些帶白色帆形結(jié)構(gòu)的小艇也誤判成帆船。這類問題調(diào)試起來很煩因為它在整體指標(biāo)上幾乎看不出變化只有在查看錯誤圖片時才會暴露。我最后的處理技巧是把誤判成帆船的圖片單獨搜集起來作為“難例”放進訓(xùn)練集并在標(biāo)注時讓模型看到這些目標(biāo)其實是其他類別。難例挖掘在訓(xùn)練這類長尾分布數(shù)據(jù)的時候非常管用。每訓(xùn)練完一輪就把驗證集上的錯誤樣本回灌到訓(xùn)練集進行下一輪微調(diào)這種做法比單純增加權(quán)重更有效地糾正模型行為。6. 項目落地后的擴展方向與個人體會6.1 從檢測到跟蹤為船只軌跡分析做準(zhǔn)備單純檢測每一幀里的船只能在邏輯上回答“這一幀里有沒有船”。想進一步做航跡分析、船舶計數(shù)、區(qū)域闖入預(yù)警就需要在檢測模塊之上疊加目標(biāo)跟蹤?,F(xiàn)在比較成熟的做法是ByteTrack或DeepSORT。ByteTrack的優(yōu)勢是簡單高效對短期遮擋容忍度好很適合部署在實時系統(tǒng)里。我在推理鏈路里預(yù)留了Tracker接口檢測結(jié)果會先經(jīng)過跟蹤器給每個目標(biāo)分配一個穩(wěn)定ID再送到UI展示。這樣同一艘船在跨幀時不會因為短暫的檢測抖動而丟失身份。做這個擴展的初衷是客戶真正關(guān)心的是“這艘船從哪里來、往哪里去”而不僅僅是“這艘船是什么”。6.2 模型服務(wù)化與多路視頻接入現(xiàn)場不只有一路攝像頭往往有四五路甚至十幾路。桌面端單機模式處理一路視頻沒問題多路接入就涉及算力分配和畫面拼接。一種可行的方向是把模型封裝成HTTP服務(wù)或者用消息隊列管理推理任務(wù)各個視頻通道把幀推送到服務(wù)中心服務(wù)中心統(tǒng)一調(diào)配GPU資源返回結(jié)果后再分發(fā)給前端。我建議不要一次性追求過于復(fù)雜的服務(wù)架構(gòu)先按“一路一進程”的方式部署用GPU顯存占用情況和單卡推理延遲決定最多能并行跑幾路。等系統(tǒng)穩(wěn)定了再考慮引入批處理推理把多路視頻幀合并成batch一次推理吞吐量提升非??捎^。6.3 寫到最后的一些體會這個項目從需求梳理到系統(tǒng)交付前前后后反復(fù)迭代了差不多兩個月。最大的體會是模型訓(xùn)練在項目里占的時間其實沒有想象中那么多真正耗時的是數(shù)據(jù)采集、數(shù)據(jù)標(biāo)注、界面聯(lián)調(diào)和現(xiàn)場部署。YOLOv8把訓(xùn)練門檻壓得很低但把“能用”變成“好用”靠的還是圍繞場景做的工程工作。如果讓我給準(zhǔn)備做類似項目的人三句話第一句是先花一周把數(shù)據(jù)分布摸清楚比先跑十版模型有用得多第二句是UI和推理一定要解耦否則后面加功能會改到懷疑人生第三句是預(yù)留難例挖掘的機制因為模型上線之后最讓你頭疼的問題一定來自那些你沒想過的情況。這套流程沉淀下來以后換一個檢測對象再做一遍會發(fā)現(xiàn)大部分環(huán)節(jié)都能復(fù)用無非是數(shù)據(jù)變了、類別變了、界面文案變了方法論是通用的。