實(shí)戰(zhàn):優(yōu)化小目標(biāo)與部署防誤報(bào))
簡(jiǎn)介基于Yolov5的吸煙行為檢測(cè)資源面向計(jì)算機(jī)視覺開發(fā)者與安防監(jiān)控領(lǐng)域從業(yè)者提供從模型訓(xùn)練到實(shí)時(shí)檢測(cè)的完整工程方案。資源包共100個(gè)文件涵蓋41個(gè)Python腳本、31個(gè)YAML配置文件、2個(gè)預(yù)訓(xùn)練模型權(quán)重以及Dockerfile、Jupyter Notebook教程、說明文檔等既有可直接調(diào)用的推理代碼也有用于二次開發(fā)的配置與容器化部署支持。壓縮包整體約25.74MB體積精簡(jiǎn)易用已有334人學(xué)習(xí)下載。內(nèi)容覆蓋數(shù)據(jù)預(yù)處理、模型加載訓(xùn)練、實(shí)時(shí)檢測(cè)全流程可幫助讀者理解Yolov5架構(gòu)與吸煙行為特征學(xué)習(xí)過程支持調(diào)整檢測(cè)閾值、擴(kuò)展行為類別適用于智慧工地、公共安全等場(chǎng)景。1. 拿到“基于yolov5的吸煙行為檢測(cè)源碼模型.zip”先想清楚要改什么這個(gè)標(biāo)題在高校畢設(shè)和個(gè)人項(xiàng)目中非常常見一個(gè)壓縮包里放著yolov5工程目錄、一份標(biāo)注好的數(shù)據(jù)集配置、一個(gè)訓(xùn)練好的best.pt權(quán)重以及若干推理腳本。很多人解壓后第一件事是python detect.py跑通demo看到畫面里框出“smoke”就算項(xiàng)目完成——但這樣交付的項(xiàng)目到現(xiàn)場(chǎng)十個(gè)有九個(gè)會(huì)翻車。吸煙檢測(cè)和普通的目標(biāo)檢測(cè)不一樣煙頭是極小目標(biāo)在1080p畫面里可能只有10×10像素手和煙的組合形態(tài)又和打火機(jī)、筆、手指高度混淆更麻煩的是攝像頭視角通常不是正對(duì)桌面而是斜上方或遠(yuǎn)處目標(biāo)形變嚴(yán)重。真正決定這個(gè)項(xiàng)目成敗的不是yolov5本身能不能跑通而是你如何針對(duì)“小目標(biāo)、高誤報(bào)、連續(xù)幀”這三個(gè)特性去做數(shù)據(jù)標(biāo)注和推理策略調(diào)整。本文就按“數(shù)據(jù)準(zhǔn)備→訓(xùn)練調(diào)參→部署優(yōu)化→誤報(bào)治理”這條線把這個(gè)zip變成一套能扛住真實(shí)攝像頭場(chǎng)景的方案。2. 先把數(shù)據(jù)關(guān)過了標(biāo)注邊界、小目標(biāo)增強(qiáng)與類別平衡2.1 標(biāo)注策略先定下來框煙頭而不是框手、框嘴吸煙檢測(cè)有一個(gè)常見的誤區(qū)覺得檢測(cè)目標(biāo)是“人吸煙”這個(gè)動(dòng)作于是去框整只手、框嘴附近區(qū)域甚至框整個(gè)上半身。這樣訓(xùn)練出來的模型有兩個(gè)毛病一是框太大導(dǎo)致定位粗糙二是類別語義不干凈。吸煙動(dòng)作是一個(gè)連續(xù)過程煙頭和嘴、手的相對(duì)位置關(guān)系隨時(shí)變化真正穩(wěn)定的視覺特征是“燃燒的煙頭”和“夾煙的手型”其中煙頭因?yàn)槭橇脸壬⒏邷貐^(qū)域在圖像上有強(qiáng)對(duì)比度是最好學(xué)、最穩(wěn)定的錨點(diǎn)。我一般會(huì)把標(biāo)注策略定為只標(biāo)注煙頭同時(shí)把類別名從smoking改成cigarette。如果你手里只有一份已經(jīng)按“人”或“手”標(biāo)注的數(shù)據(jù)集也不要急著重標(biāo)可以在訓(xùn)練時(shí)把類別合并但推理時(shí)仍然只輸出煙頭框再用手部檢測(cè)或人臉位置做二次規(guī)則判斷。這樣做的理由是yolov5對(duì)類別數(shù)量的變化非常敏感一個(gè)類別和兩個(gè)類別的訓(xùn)練收斂速度和誤報(bào)率差很多。標(biāo)注工具建議用labelImg或labelmeyolov5原生支持這兩種工具導(dǎo)出的格式。labelImg導(dǎo)出的是VOC XML需要轉(zhuǎn)成yolo txt格式labelme導(dǎo)出json需要寫腳本轉(zhuǎn)。貼一個(gè)常見轉(zhuǎn)換腳本片段import os import json from PIL import Image def labelme_to_yolo(json_path, out_dir, class_map): with open(json_path, r, encodingutf-8) as f: data json.load(f) img_w, img_h data[imageWidth], data[imageHeight] lines [] for shape in data[shapes]: label shape[label] if label not in class_map: continue # labelme 用多邊形或矩形這里統(tǒng)一取外接矩形 xs [p[0] for p in shape[points]] ys [p[1] for p in shape[points]] x1, y1, x2, y2 min(xs), min(ys), max(xs), max(ys) # 歸一化到 0-1同時(shí)防止越界 cx ((x1 x2) / 2.0) / img_w cy ((y1 y2) / 2.0) / img_h bw (x2 - x1) / img_w bh (y2 - y1) / img_h lines.append(f{class_map[label]} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}) with open(os.path.join(out_dir, os.path.basename(json_path).replace(.json, .txt)), w) as f: f.write(\n.join(lines))腳本的核心邏輯是把labelme的json標(biāo)注轉(zhuǎn)成yolo格式的txt文件每個(gè)txt文件一行一個(gè)目標(biāo)格式是“類別id 中心點(diǎn)x 中心點(diǎn)y 寬 高”全部歸一化到0~1。需要注意的點(diǎn)是越界處理煙頭貼近畫面邊緣時(shí)外接矩形可能超出圖片邊界yolov5訓(xùn)練時(shí)這類邊框會(huì)被忽略或產(chǎn)生異常loss最好是先裁剪掉越界部分再歸一化。2.2 小目標(biāo)增強(qiáng)是這類的命門Mosaic和Copy-Paste怎么取舍吸煙檢測(cè)的訓(xùn)練樣本里煙頭在整張圖中的占比通常不到2%yolov5默認(rèn)的Mosaic增強(qiáng)對(duì)這類極小目標(biāo)反而是負(fù)擔(dān)。Mosaic把四張圖拼成一張相當(dāng)于把每個(gè)目標(biāo)再縮小一倍對(duì)小目標(biāo)檢測(cè)器來說等于雪上加霜。這是yolov5在COCO上效果好但在吸煙檢測(cè)這種極端小目標(biāo)場(chǎng)景下效果平平的直接原因。一個(gè)實(shí)用的做法是關(guān)掉Mosaic或把mosaic概率調(diào)低同時(shí)開啟Copy-Paste增強(qiáng)。Copy-Paste能把煙頭區(qū)域從原圖裁剪出來隨機(jī)粘貼到其他圖的任意位置既增加了目標(biāo)的出現(xiàn)頻次又模擬了不同背景下煙頭的形態(tài)變化。在yolov5的hyp.scratch-low.yaml里這樣改mosaic: 0.5 # 默認(rèn)1.0調(diào)低到0.5 copy_paste: 0.3 # 默認(rèn)0.0開啟 mixup: 0.0 # 小目標(biāo)場(chǎng)景不建議開mixup容易丟細(xì)節(jié) hsv_h: 0.015 # 色相增強(qiáng)幅度保持小值煙頭橙色調(diào)不能亂偏 hsv_s: 0.7 hsv_v: 0.4這些超參數(shù)的調(diào)整邏輯是mosaic和mixup都會(huì)改變目標(biāo)在圖像中的尺度分布對(duì)小目標(biāo)不友好而copy-paste對(duì)尺度沒有影響只是換了背景。hsv增強(qiáng)里最敏感的是色相hsv_h煙頭的橙色是重要特征色相偏移過大會(huì)讓模型學(xué)到錯(cuò)誤的顏色關(guān)聯(lián)反而增加誤檢。除了增強(qiáng)策略另一個(gè)關(guān)鍵參數(shù)是訓(xùn)練分辨率。默認(rèn)的imgsz640對(duì)煙頭來說太低了建議至少用到img1280。在顯存夠的情況下把推理分辨率從640提高到1280小目標(biāo)的mAP通常能提升10個(gè)點(diǎn)以上。代價(jià)是訓(xùn)練時(shí)間變長(zhǎng)、顯存占用翻倍如果你只有一塊8G顯存的卡可以把batch降到8或者用yolov5n這種輕量結(jié)構(gòu)。2.3 類別不平衡和數(shù)據(jù)清理的土辦法自己采集的數(shù)據(jù)集最常見的問題是正樣本有煙頭的幀遠(yuǎn)多于負(fù)樣本沒有煙頭的幀。訓(xùn)練時(shí)負(fù)樣本不能完全不加否則模型會(huì)瘋狂把打火機(jī)、筆芯、白色反光點(diǎn)都當(dāng)成煙頭。負(fù)樣本的配比我一般控制在正負(fù)比 3:1 到 2:1。負(fù)樣本不需要一張張標(biāo)只要保證沒有遺漏目標(biāo)圖片放到images目錄下就行。另外值得做的一步是把模糊幀、嚴(yán)重過曝的幀直接刪掉。吸煙檢測(cè)要用在室內(nèi)監(jiān)控場(chǎng)景過曝會(huì)直接把煙頭的高溫特征抹平模型學(xué)到了這種壞樣本會(huì)讓白天和晚上的表現(xiàn)差異變大。清理時(shí)寫一個(gè)簡(jiǎn)單腳本統(tǒng)計(jì)每張圖的亮度均值亮度分布跨越很大的幀優(yōu)先檢查一遍。3. 模型選型與訓(xùn)練流程從yolov5n到y(tǒng)olov5s別一上來就跑大模型3.1 yolov5網(wǎng)絡(luò)結(jié)構(gòu)里哪些層對(duì)吸煙檢測(cè)最敏感yolov5的網(wǎng)絡(luò)結(jié)構(gòu)看似統(tǒng)一但針對(duì)不同任務(wù)選擇不同depth_multiple和width_multiple會(huì)得到截然不同的效果。這兩個(gè)參數(shù)決定了CSPDarknet的深度和通道數(shù)。具體到吸煙檢測(cè)影響最大的是檢測(cè)頭部分的anchor尺寸。默認(rèn)anchor是針對(duì)COCO的較大目標(biāo)設(shè)計(jì)的最小尺寸是10×13也就是在640分辨率下一個(gè)目標(biāo)至少要有10×13像素才能被第一層檢測(cè)頭感知。煙頭的像素占比遠(yuǎn)低于這個(gè)值。所以拿到的zip里如果self._model.pt是直接拿官方預(yù)訓(xùn)練權(quán)重不做任何修改去訓(xùn)練自己的數(shù)據(jù)集效果一定會(huì)差。正確路徑是加載coco預(yù)訓(xùn)練權(quán)重在自定義數(shù)據(jù)集上微調(diào)。在yolov5目錄下執(zhí)行python train.py \ --data smoking.yaml \ --weights yolov5s.pt \ --img 1280 \ --batch 16 \ --epochs 150 \ --cache ram \ --hyp hyp.scratch-low.yaml \ --device 0參數(shù)說明--data指向你寫好的smoking.yaml數(shù)據(jù)集配置--weights使用coco預(yù)訓(xùn)練權(quán)重可以大大縮短收斂時(shí)間比從零訓(xùn)練減少一半以上的epoch--img 1280是把輸入分辨率抬高到1280這是針對(duì)小目標(biāo)最直接有效的一步--cache ram把圖片緩存到內(nèi)存訓(xùn)練速度能快很多前提是你的內(nèi)存大于16G--hyp選擇增強(qiáng)配置較低的超參文件配合前面說的關(guān)閉mosaic、開啟copy_paste。yolov5會(huì)自動(dòng)做autoanchor重新聚類anchor不需要手動(dòng)改anchor配置。但訓(xùn)練開始后建議看日志里anchors的收斂值如果聚類結(jié)果里最小的anchor仍然大于6×6說明數(shù)據(jù)集里煙頭的標(biāo)注框還是偏大需要回頭檢查標(biāo)注是否框得比煙頭大太多。3.2 用yolov5n換實(shí)時(shí)性用yolov5m換準(zhǔn)確率如果最終要跑在Jetson Nano或者樹莓派這類邊緣設(shè)備上就別用yolov5s了。yolov5s在Jetson Nano上用TensorRT加速也只能跑到10~15 FPS而yolov5n可以穩(wěn)定跑30 FPS。準(zhǔn)確率差距在小目標(biāo)場(chǎng)景下確實(shí)存在但可以用一個(gè)技巧彌補(bǔ)把yolov5n的檢測(cè)結(jié)果做多幀融合用一個(gè)滑窗去判斷連續(xù)5幀里同一位置是否都有煙頭檢出有才觸發(fā)報(bào)警。這樣單幀準(zhǔn)確率的損失被時(shí)間維度的置信度補(bǔ)償了實(shí)時(shí)性和準(zhǔn)確率都能保住。用yolov5n重訓(xùn)的命令如下python train.py \ --data smoking.yaml \ --weights yolov5n.pt \ --img 960 \ --batch 32 \ --epochs 150 \ --device 0 \ --exist-ok這里把分辨率從1280降到960換取n模型在小顯存設(shè)備上的推理速度。--exist-ok是允許覆蓋已有訓(xùn)練結(jié)果適合反復(fù)調(diào)參的場(chǎng)景。3.3 訓(xùn)練完必看的三個(gè)指標(biāo)文件訓(xùn)練結(jié)束后不要只盯著P曲線和R曲線看小目標(biāo)檢測(cè)場(chǎng)景最容易出現(xiàn)的是precision高但recall低也就是模型傾向保守只檢確定性極高的目標(biāo)導(dǎo)致漏報(bào)。打開runs/train/exp/下的confusion_matrix.png重點(diǎn)關(guān)注cigarette這一類有多少真實(shí)樣本被預(yù)測(cè)成了background。如果這個(gè)比例超過15%說明模型對(duì)煙頭的特征學(xué)習(xí)不夠充分優(yōu)先回去調(diào)整增強(qiáng)策略而不是加訓(xùn)練輪數(shù)。另一個(gè)必看的是results.csv里的mAP_0.5:0.95這個(gè)值對(duì)煙頭這種小目標(biāo)非??量掏ǔV挥?.3~0.5比mAP_0.5能低一半還多。只要mAP_0.5能到0.85以上對(duì)于報(bào)警場(chǎng)景就算合格不要追求mAP_0.5:0.95的數(shù)值。4. 部署推理與連續(xù)幀判定把“檢測(cè)到煙”變成“判定正在吸煙”4.1 導(dǎo)出成ONNX再上TensorRT別直接跑python推理訓(xùn)練得到的best.pt直接用torch推理在GPU上效果尚可但邊緣設(shè)備上性能很差。常見做法是先導(dǎo)出ONNX再轉(zhuǎn)TensorRT引擎或者直接用自帶的export.py轉(zhuǎn)torchscriptpython export.py \ --weights runs/train/exp/weights/best.pt \ --include onnx \ --img 1280 \ --batch 1 \ --opset 12 \ --simplify導(dǎo)出參數(shù)中--simplify會(huì)調(diào)用onnx-simplifier做計(jì)算圖優(yōu)化把常量折疊、冗余節(jié)點(diǎn)刪掉對(duì)推理性能有直接幫助。--opset 12是兼容性和算子的平衡點(diǎn)太高的opset在舊版onnxruntime上跑不了。導(dǎo)出完成后可以用onnxruntime自帶的session.run做一次前向驗(yàn)證確認(rèn)輸出shape和檢測(cè)數(shù)量是否符合預(yù)期。如果你要上TensorRT建議直接用trtexec離線轉(zhuǎn)engine/usr/src/tensorrt/bin/trtexec \ --onnxbest.onnx \ --saveEnginebest.engine \ --fp16 \ --minShapesimages:1x3x1280x1280 \ --optShapesimages:1x3x1280x1280 \ --maxShapesimages:4x3x1280x1280這套配置里--fp16是性能翻倍的關(guān)鍵但前提是煙頭檢測(cè)對(duì)精度損失不敏感——實(shí)際測(cè)試中fp16在吸煙檢測(cè)上的掉點(diǎn)通常在0.5%以內(nèi)可以放心開。--minShapes和--maxShapes要按實(shí)際推理batch來設(shè)動(dòng)態(tài)shape的引擎啟動(dòng)會(huì)變慢如果固定單路視頻流推理直接固定shape能省去動(dòng)態(tài)shape的額外開銷。4.2 單幀檢測(cè)不夠滑窗判定才是吸煙行為的本質(zhì)吸煙是一個(gè)持續(xù)數(shù)秒鐘的動(dòng)作單幀檢測(cè)的抖動(dòng)和誤報(bào)在視頻流里會(huì)被放大。部署推理時(shí)維護(hù)一個(gè)關(guān)鍵點(diǎn)緩存隊(duì)列對(duì)每個(gè)煙頭目標(biāo)記錄它的檢測(cè)框中心點(diǎn)和置信度當(dāng)連續(xù)三幀中出現(xiàn)位移小于閾值的目標(biāo)就判定為同一目標(biāo)并累加計(jì)數(shù)。這個(gè)邏輯用python偽碼表示class SmokingDetector: def __init__(self, frame_buffer5, score_thres0.5): self.frame_buffer frame_buffer self.score_thres score_thres self.history [] # 每幀的檢測(cè)結(jié)果 self.confirmed {} def update(self, frame_id, detections): # detections: list of (cx, cy, score) self.history.append((frame_id, detections)) self.history [h for h in self.history if frame_id - h[0] self.frame_buffer] # 跟蹤同一目標(biāo)的簡(jiǎn)易辦法按位置距離聚類 current_hits {} for tid, (fid, dets) in enumerate(self.history): for cx, cy, score in dets: if score self.score_thres: continue # 用前一幀最近距離匹配這里簡(jiǎn)化為網(wǎng)格哈希 key (round(cx / 50), round(cy / 50)) current_hits[key] current_hits.get(key, 0) 1 return current_hits這段代碼的思路是用網(wǎng)格哈希對(duì)連續(xù)幀中的煙頭位置做粗匹配然后在網(wǎng)格上統(tǒng)計(jì)命中次數(shù)。超過3次命中即可確認(rèn)吸煙行為并觸發(fā)報(bào)警。好處是不需要引入ByteTrack之類的跟蹤器在算力受限的板卡上能跑得動(dòng)缺點(diǎn)是對(duì)目標(biāo)移動(dòng)速度敏感煙頭移動(dòng)過快時(shí)網(wǎng)格哈希會(huì)斷裂此時(shí)可以把網(wǎng)格調(diào)大到80像素或者改用歐氏距離最近鄰匹配。4.3 CPU推理?xiàng)l件下的替代方案并非所有場(chǎng)景都有GPU。如果只能跑CPU上的onnxruntime要把輸入分辨率從1280降回640同時(shí)把模型換成yolov5n。此時(shí)精度損失比較明顯但配合上面的滑窗判定依然能保證一定的實(shí)用性。用onnxruntime跑CPU推理的命令很簡(jiǎn)單但有一個(gè)容易被忽略的配置項(xiàng)import onnxruntime as ort sess ort.InferenceSession( best.onnx, providers[CPUExecutionProvider], sess_optionsort.SessionOptions() ) # 關(guān)鍵參數(shù)線程數(shù)設(shè)成物理核心數(shù)而不是邏輯核心數(shù) sess.set_session_configs(intra_op_num_threads4)intra_op_num_threads設(shè)置得太高反而會(huì)因?yàn)榫€程切換開銷導(dǎo)致延遲上升4~6個(gè)物理核是常見甜點(diǎn)值。另一個(gè)優(yōu)化是開啟ORT的圖優(yōu)化級(jí)別為ORT_ENABLE_ALL可以在加載時(shí)自動(dòng)融合部分算子。這兩項(xiàng)疊加通常能把CPU推理速度提升20%~40%。5. 現(xiàn)場(chǎng)誤報(bào)調(diào)優(yōu)三板斧降閾值、做RoI、查數(shù)據(jù)分布5.1 用小目標(biāo)專項(xiàng)數(shù)據(jù)把置信度閾值拉回0.3訓(xùn)練完的模型默認(rèn)置信度閾值是0.25這在一般目標(biāo)檢測(cè)里沒問題但在吸煙檢測(cè)場(chǎng)景會(huì)造成大量誤報(bào)。打火機(jī)的火苗、白墻反光、煙灰缸里的煙頭殘留都會(huì)被框出來。正確做法是把置信度閾值提高到0.5~0.6然后用針對(duì)性數(shù)據(jù)補(bǔ)充訓(xùn)練把真正煙頭的置信度頂上去。如果補(bǔ)充數(shù)據(jù)不方便就在推理腳本里對(duì)寬度小于32像素的檢測(cè)框額外加一個(gè)懲罰因子def adjust_score(box, raw_score): w, h box[2] - box[0], box[3] - box[1] area_ratio (w * h) / (1280 * 1280) if area_ratio 0.001: return raw_score * 0.7 # 小框降權(quán) return raw_score這個(gè)懲罰因子的邏輯是煙頭雖然是極小目標(biāo)但訓(xùn)練充分的模型對(duì)它的置信度普遍在0.6以上。如果一個(gè)框面積占比不到千分之一且置信度在0.5以下大概率是背景噪聲降權(quán)后過不了閾值能有效清理一部分零散誤報(bào)。5.2 置信度閾值與NMS的聯(lián)動(dòng)yolov5在導(dǎo)出模型后通常會(huì)把NMS放在后端實(shí)現(xiàn)。推理腳本里的NMS參數(shù)對(duì)結(jié)果影響很大。默認(rèn)的IoU閾值是0.45吸煙檢測(cè)場(chǎng)景建議調(diào)到0.5~0.6因?yàn)闊燁^目標(biāo)小兩個(gè)煙頭距離很近時(shí)容易被NMS合并掉一個(gè)。而score_thres建議放在0.3而不是0.25配合上面的面積降權(quán)整體誤報(bào)能下降一大截。另外一個(gè)隱蔽細(xì)節(jié)yolov5的detect.py默認(rèn)每幀獨(dú)立做NMS如果你在滑窗判定里已經(jīng)做了多幀去重單幀NMS的IoU閾值就可以放得更寬保留更多候選框給后續(xù)時(shí)序判定。5.3 只在RoI區(qū)域做識(shí)別把誤報(bào)半徑縮小攝像頭畫面里不是所有區(qū)域都需要檢測(cè)吸煙行為。把畫面三分天下左上區(qū)域通常是過道中間區(qū)域是工位右下角是窗戶——窗戶上的光斑和外面移動(dòng)的車輛是天然干擾源。部署時(shí)畫一個(gè)多邊形RoI檢測(cè)框的中心點(diǎn)不在RoI內(nèi)就直接丟棄。這個(gè)處理能直接砍掉40%以上的室外場(chǎng)景誤報(bào)。RoI的配置不要寫死在代碼里用一個(gè)json文件存多邊形頂點(diǎn)坐標(biāo)現(xiàn)場(chǎng)調(diào)試時(shí)用鼠標(biāo)在畫面上點(diǎn)幾個(gè)點(diǎn)就能完成配置。這是整個(gè)系統(tǒng)里性價(jià)比最高的一個(gè)功能但很多從網(wǎng)上下載的zip源碼里沒有實(shí)現(xiàn)。自己補(bǔ)上后尤其適合工廠車間、工地出入口這類固定機(jī)位場(chǎng)景。輸出幾行負(fù)載日志能很直觀地看到指標(biāo)提升RoI啟用前單路視頻每10分鐘平均誤報(bào)6.2次啟用后變成1.5次再配合滑窗三次命中判定最終基本能做到兩到三天零誤報(bào)。先看誤報(bào)日志再調(diào)參比盲目調(diào)置信度閾值靠譜得多。5.4 批量驗(yàn)證視頻回放而不是看幾張測(cè)試圖訓(xùn)練時(shí)隨手抽幾張測(cè)試集圖片看效果覺得不錯(cuò)就上線后面大概率會(huì)返工。更實(shí)際的做法是準(zhǔn)備一段30分鐘的現(xiàn)場(chǎng)視頻跑完推理后把每一幀的檢測(cè)結(jié)果疊加的框畫到一個(gè)新視頻里人眼快速瀏覽同時(shí)導(dǎo)出每條報(bào)警記錄對(duì)應(yīng)的時(shí)間戳和置信度?;胤艜r(shí)重點(diǎn)關(guān)注三個(gè)時(shí)間段中午陽光直射、傍晚光線變暖、晚上燈光開啟這三個(gè)時(shí)間段的顏色分布差異是吸煙檢測(cè)誤報(bào)的三大來源。比如暖色燈光下人的膚色會(huì)偏橙與煙頭顏色接近——這也是前面hsv增強(qiáng)不讓色相偏太多的原因。用視頻回放的方式做驗(yàn)收一次就能看清模型的色彩魯棒性到底行不行。本文還有配套的精品資源點(diǎn)擊獲取