简介:一份面向目标检测与抽烟检测场景的数据集介绍指南,适用于公共场所监控或室内监控场景下训练抽烟识别模型的开发者。数据集包含1000张真实与合成结合的高质量图片,覆盖街景抽烟、写字楼抽烟、办公室抽烟、楼道抽烟以及遮挡行人、严重遮挡行人抽烟等多种情况,场景层次丰富。包体为单个PDF文件,大小8.92MB,内含数据集基本情况介绍、缩略图、labelimg标注效果示意图及百度网盘获取方式;由于原图数据量较大,实际图片数据通过网盘交付。已有761人浏览学习。该数据集采用labelimg标注软件制作,提供VOC(xml)、COCO(json)、YOLO(txt)三种常见格式标签,可直接用于YOLO等算法训练;同时附赠YOLO11一键训练脚本,支持GPU(GPUs)、CPU、Mac(M芯片)三平台,并附带博主训练结果日志供参考,可帮助快速完成环境搭建与模型效果验证,适合作为监控场景抽烟检测项目的数据补充与训练入门资料。
1. 抽烟检测数据集:1000张图到底能不能训出一个可上线的YOLO11模型
做目标检测的同行应该都有过这种经历:接到一个“识别现场有没有人抽烟”的需求,第一反应不是先挑模型,而是先翻遍全网找数据集;找到的数据集要么是国外场景、要么标注乱七八糟,真正能从零开始跑通整个流程的少之又少。抽烟检测这个任务看起来只是单类别目标检测,比COCO的80类简单得多,但它有个天然难点——很多标注把“烟”和“人”分开标,导致模型学到的是“有手部区域就有烟”,而真正厂区、园区监控里的抽烟行为往往只有一两秒、目标很小,模型精度很容易虚高。
我最近在处理一个相似需求时用到的方案,就是以“抽烟检测数据集”为核心,配合1000张图、VOC/COCO/YOLO三种格式标签,再用YOLO11在GPU(GPUs)/CPU/Mac三平台上做一键训练。这个组合的好处是:数据集小但格式全,适合快速验证思路;YOLO11自带ultralytics库,训练脚本可以一套代码三平台跑。这篇文章就把整个落地路径拆开讲:三种标签格式怎么换算、YOLO11训练脚本怎么按平台调参、以及哪些坑是新手最容易踩的,目标是让你拿到类似数据集后一天内跑通训练并拿到能用的权重。
2. 三种标注格式的换算逻辑:VOC/COCO/YOLO到底在换什么
2.1 VOC是“人话版”标注,先看懂它的XML结构
VOC格式的核心是每个图片对应一个同名XML文件,里面用<object>标签框出每个目标。看一个典型结构:
<annotation> <folder>images</folder> <filename>smoking_001.jpg</filename> <size> <width>640</width> <height>480</height> <depth>3</depth> </size> <object> <name>smoking</name> <bndbox> <xmin>120</xmin> <ymin>200</ymin> <xmax>260</xmax> <ymax>340</ymax> </bndbox> </object> </annotation>这里有个容易被忽略的点:<filename>只存文件名,不存路径,而<folder>是图片所在文件夹名。很多人做格式转换时直接把XML和图片放在同一个目录下就完事,但YOLO训练脚本读取数据时是按images和labels两个目录分开找的,如果XML里的filename和实际文件名对不上,转换出来的标注就会张冠李戴。我一般会在转换脚本里加一道校验:遍历XML时同时检查对应图片是否存在,如果不存在直接跳过并打印警告,而不是等到训练时报image not found才回头查。
VOC格式的数据集目录通常长这样:
dataset/ ├── annotations/ # 存放所有xml ├── images/ # 存放所有jpg └── ImageSets/ └── Main/ # 存放train.txt, val.txtImageSets/Main下的txt文件是关键,每行是一个不带扩展名的文件名,用来划分训练集和验证集。做转换的人只盯着XML解析,却忘了先把训练集和验证集划分好,结果就是整个数据集被YOLO一股脑全训了,val指标变成了“开卷考试”,精度虚高。
2.2 COCO格式是“数据库式”标注,一个JSON管所有图
COCO格式把所有标注塞进一个JSON文件,用images、annotations、categories三个数组来组织数据。它和VOC最大的区别是:VOC的每个类别名直接在XML里写死,而COCO的类别是用id关联的,categories里id: 1对应name: "smoking",annotations里的category_id引用的就是这个id。
这段是COCO JSON的核心字段:
{ "images": [{"id": 1, "file_name": "smoking_001.jpg", "width": 640, "height": 480}], "annotations": [{ "id": 1, "image_id": 1, "category_id": 1, "bbox": [120, 200, 140, 140], "area": 19600, "iscrowd": 0 }], "categories": [{"id": 1, "name": "smoking", "supercategory": "none"}] }注意COCO的bbox是[x, y, width, height],不是VOC格式里的[xmin, ymin, xmax, ymax]。包括网上很多“COCO转YOLO”的脚本,如果没做这一步换算,训练出来的边界框会整体偏移,mAP直接掉到不能看。
还有一个iscrowd字段,多数人会把所有标注都填0。但如果你是从真实监控视频里截帧标注的,遇到一群人挤在一起抽烟的场景,iscrowd字段的正确处理会直接影响训练时是否把该标注当作“忽略区域”处理。在数据量只有1000张的情况下,这种细节比模型结构本身更影响最终效果。
2.3 YOLO格式是“归一化坐标”,txt文件里只有数字
YOLO格式是最“裸”的:每张图对应一个txt文件,文件每行代表一个目标,格式是class_index x_center y_center width height,所有数值都归一化到0到1之间,坐标要除以图片宽高,宽高要除以图片宽高。
一个抽烟检测的YOLO标注文件内容示例:
0 0.4375 0.5208 0.2188 0.2917 0 0.7188 0.6458 0.2031 0.2292这里0是类别索引(如果只有“抽烟”一个类别,索引就是0),0.4375是x中心点除以640后的值,0.5208是y中心点除以480后的值。如果图上只有一个目标,txt里就只有一行。
很多人会问:那我下载的数据集只有一种格式,怎么用YOLO训练?答案是直接做格式换算。我常用的做法是:先把VOC的XML解析成Python dict,再从dict同时生成COCO JSON和YOLO txt。这样一份原始数据,转换出两种衍生格式,以后换框架都不用重新找数据集。换算脚本的核心逻辑,其实就是四行坐标换算公式:
# 关键是边界框的坐标体系换算,voc转yolo x_center = (xmin + xmax) / 2.0 / img_width y_center = (ymin + ymax) / 2.0 / img_height bbox_width = (xmax - xmin) / img_width bbox_height = (ymax - ymin) / img_height这套公式看起来简单,但有三个隐含前提:图片读取要用cv2或者PIL拿到真实的宽高而不是从XML里读<size>;如果XML里的<size>和实际图片尺寸不一致,以实际图片为准;除以的是宽和高要分开除,不能写成一个变量。
2.4 三种格式的映射关系速查表
| 含义 | VOC (XML) | COCO (JSON) | YOLO (txt) |
|---|---|---|---|
| 类别名称 | <name>smoking</name> | categories[].name | 无(用索引对应names文件) |
| 类别索引 | 无(直接用名称) | category_id | 每行第1个数 |
| 边界框坐标 | xmin, ymin, xmax, ymax | [x, y, width, height] | x_center, y_center, width, height |
| 坐标值域 | 像素绝对值 | 像素绝对值 | 0~1归一化 |
| 每张图标注文件 | 一个XML | 所有图共用一个JSON | 一个同名txt |
实际工程里最省事的做法是先从VOC出发,因为XML是人类可读的结构,出了错一眼能看出来;而COCO JSON嵌套层级深,解析时容易手抖漏字段;YOLO txt过于精简,出错后你根本不知道那个0.4375到底是哪个目标的坐标。
3. 跑通YOLO11一键训练:GPU/CPU/Mac三平台的命令差异
3.1 ultralytics库的安装与环境检查
YOLO11的训练脚本基于ultralytics库,这个库已经封装好了数据加载、模型定义、训练循环、验证评估的所有代码,所以你不需要自己写训练循环。有人听到“一键训练脚本”会怀疑是不是故弄玄虚,其实ultralytics的设计理念就是这样——一条yolo train命令搞定。
先做环境检查,三平台的命令基本一致,只是GPU设备名不同:
# 检查python版本,3.8-3.11均可 python --version # 安装ultralytics,注意会连带安装torch pip install ultralytics # 检查torch是否能看到GPU(Linux/Windows适用) python -c "import torch; print(torch.cuda.is_available())" # Mac用户检查MPS(Apple Silicon专用) python -c "import torch; print(torch.backends.mps.is_available())"这里有个实际经验:如果你是0基础纯小白,装ultralytics最常翻车的地方是torch版本和CUDA版本不匹配。常见现象是import torch没问题,torch.cuda.is_available()返回False,但nvidia-smi明明能看到GPU。原因是torch的CUDA编译版本和显卡驱动版本不一致,解决方式是去PyTorch官网选对应CUDA版本的安装命令重新装torch,不要用pip install torch默认的CPU版本。
Mac用户则要注意:只有Apple Silicon(M1/M2/M3系列)的Mac才支持MPS加速,Intel芯片的Mac只能走CPU。如果你用的是老款Intel Mac,torch.backends.mps.is_available()会返回False,别慌,直接用CPU模式训练就行,1000张图的数据量CPU照样能跑完,只是时间会多花几倍。
3.2 数据集的YOLO目录结构:这部分决定了脚本能不能一键跑起来
训练脚本能“一键”跑的前提,是数据集已经按YOLO目录规范整理好了。常见的目录结构是这样的,注意图片和标签要分开放:
smoking_dataset/ ├── images/ │ ├── train/ # 训练集图片 │ └── val/ # 验证集图片 ├── labels/ │ ├── train/ # 训练集txt标签(与图片同名) │ └── val/ # 验证集txt标签 └── data.yaml # 数据集配置这个结构里最容易被忽视的是data.yaml文件。它用来告诉YOLO训练脚本:类别名字是什么、类别数量是多少、训练集和验证集图片的路径在哪里。如果这个文件写错,后面的训练命令再怎么“一键”都会失败。
我的data.yaml长这样:
# 抽烟检测数据集配置 path: /Users/yourname/smoking_dataset # 数据集根目录,建议写绝对路径 train: images/train # 相对path的路径 val: images/val # 相对path的路径 # 类别定义,只有一个类别 nc: 1 names: 0: smoking有一个非常隐蔽的坑:path字段如果用相对路径,脚本会以当前工作目录为基准找数据集。而你从网上下载的数据集往往放在Downloads文件夹或直接解压在桌面,不同机器解压位置不一样,导致训练时一直报错找不到图片。我一般会强制要求写绝对路径,并在训练脚本里先打印dataset_dir的值,确认数据集路径被正确识别后再开始训练。
3.3 三平台训练命令的差异点:device参数是唯一需要改的地方
ultralytics的设计让“一键训练脚本”变得比较简单——你只需要改两个参数:model(用哪个预训练权重)和device(用哪个设备跑)。下面是三平台的训练命令对比:
# GPU(GPUs)平台:Linux/Windows NVIDIA显卡 yolo train model=yolo11s.pt data=data.yaml epochs=100 imgsz=640 batch=16 device=0 # CPU平台:没有独立显卡的服务器或老电脑 yolo train model=yolo11s.pt data=data.yaml epochs=100 imgsz=640 batch=8 device=cpu # Mac平台:Apple Silicon用mps,Intel Mac用cpu yolo train model=yolo11s.pt data=data.yaml epochs=100 imgsz=640 batch=8 device=mps参数说明:
model=yolo11s.pt:指定预训练权重,s是small版本,尺寸适中、速度和精度平衡,适合1000张这种小数据集;如果显存吃紧可以换yolo11n.pt(nano版)。epochs=100:训练轮数。1000张图建议100轮起步,因为数据量小,模型容易快速收敛到过拟合状态,100轮加上早停机制比较稳。batch=16:每批次图片数。GPU显存足够就设16或32;CPU和Mac建议设8,批次太大会把内存吃满,触发OOM。device:唯一有平台差异的参数。多卡GPU时支持device=0,1,CPU就是cpu,Mac的Apple Silicon用mps。
这里有一个很实用的调参经验:数据量只有1000张时,imgsz=640就够了,不需要调成1280。更高分辨率确实对小目标(比如远处烟头)有增益,但训练时间会大幅拉长,而且抽烟检测里面的目标(烟头、手部区域)在监控画面里通常不是极小的目标,640输入下YOLO11的检测能力已经够用。
如果你的训练脚本是自己写的而不是用ultralytics命令行,那么核心训练代码也就这么几行:
from ultralytics import YOLO # 加载预训练模型,yolo11s比yolo11n精度高,比yolo11m速度快 model = YOLO("yolo11s.pt") # 开始训练 model.train( data="data.yaml", # 数据集配置 epochs=100, # 训练轮数 imgsz=640, # 输入分辨率 batch=16, # 批次大小 device="0" # 0表示第一张GPU卡;cpu或mps同理 )训练完成后,runs/detect/train目录下会生成weights/best.pt和weights/last.pt。best.pt是在验证集上精度最高的权重文件,部署时优先用这个;last.pt是最后一轮保存的权重,一般只用来断点续训。
3.4 跨平台迁移时的三个必查项
有人说“我CPU上训出来的模型能不能放到GPU机器上推理?”答案是可以的,因为best.pt保存的是模型结构加权重参数,不绑定训练设备。但有个例外情况:如果你在Mac上训练时用了MPS,保存的权重拿到Windows GPU机器上加载,偶尔会遇到torch.load报错,原因是PyTorch版本差异导致的序列化兼容性问题,解决方式是加一行:
import torch model = torch.load("best.pt", map_location="cpu")另外两个必查项是:第一,data.yaml里的路径如果在另一台机器上不存在,用yolo predict做推理时会报错,所以模型落地部署时建议直接传图片路径或摄像头ID,不要让推理代码依赖训练时的数据集配置;第二,如果三台机器的ultralytics版本不一致(比如一台是8.x,一台是9.x),建议统一在用pip install -U ultralytics升级到同一版本,不然会出现某种KeyError报错,网上搜半天也找不到原因,最后发现只是版本不一致。
4. 标签与训练实操避坑:格式转换和启动训练时的四个常见故障
4.1 类别索引从1开始导致mAP为0
现象:训练正常启动,loss不断下降,但验证集的mAP一直是0,而且预测结果框的位置完全不对。
原因:从VOC或COCO格式转YOLO时,把COCO里的category_id直接当成了YOLO的类别索引。COCO的类别id习惯从1开始,而YOLO的类别索引必须从0开始。如果你只有“smoking”一个类别且category_id为1,转换后的YOLO txt每行开头都是1,但YOLO的nc=1只允许索引0,训练时所有标注全部越界。
解决:转换时做一个索引映射,例如category_id - 1。多类别场景下要做一个字典,把原始类别名映射到0到nc-1的连续索引,而不是直接沿用COCO的id。
# 类别映射表,防止索引错位 category_map = {"smoking": 0} # 如果有多类继续加: "phone": 1 # 转换逻辑示例 yolo_line = f"{category_map[obj_name]} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}"4.2 空标注文件和纯黑图导致loss变成NaN
现象:训练到一半loss突然变成nan,然后训练直接崩溃或者验证集精度归零。
原因:数据集中存在没有标注的图片(空txt文件),或者个别图片本身是纯黑/纯白图。纯色图在数据增强时(尤其是色彩抖动和随机裁剪后)可能计算出色度分量为0的情况,导致损失函数计算出现除零,最终输出NaN。
解决:在训练前加一个数据清洗脚本,扫描所有标签文件,把空文件和对应图片移出数据集目录,同时检查图片的像素方差:
import cv2 import numpy as np img = cv2.imread(image_path) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) variance = np.var(gray) if variance < 10: # 方差过小说明是纯色/暗图,剔除 print(f"Low variance image: {image_path}")4.3 数据集划分不随机导致验证集全是相似场景
现象:训练时val_loss比train_loss低很多,看似模型很好,但一到现场检测就频繁漏检。
原因:数据集划分时用了简单的train_test_split没有做随机打乱,或者按文件名顺序切割前800做训练、后200做验证。如果这1000张图中前800张来自白天场景、后200张来自夜间场景,那么验证集包含的全是模型没见过的夜间风格图片,或者反过来训练集和验证集分布差异过大,导致模型泛化能力极差。
解决:划分时必须做随机打乱,而且要按图片源做分组——如果1000张图里有多个场景(不同监控点位、不同光照条件),建议同一个场景的图片只能同时出现在训练集或验证集中,不能同一场景的图两边都出现;否则模型只是“背下了”这个场景的画面,换场景就失灵。
4.4 训练脚本在Mac上卡死但CPU占用率只有30%
现象:yolo train在Mac上启动后,界面卡住没有任何输出,打开活动监视器看到Python进程只占了一小部分CPU。
原因:ultralytics在Mac上默认读取设备时优先尝试CUDA,导致它在不支持CUDA的Mac上反复尝试初始化设备驱动,等待超时后才回退到CPU或MPS。
解决:直接在训练命令里显式指定device=mps或device=cpu,不给它自动检测的机会;同时把workers=0,避免multiprocessing在Mac上因为spawn机制卡死。这也是“一键训练脚本”里最容易踩的Mac专属坑,Windows和Linux上很少遇到。
5. 用1000张训练集调出可用模型:从训练到验证的完整脚本
5.1 训练脚本的完整形态与关键参数
把前面几个部分的要点合并,我给你一个可以直接拿去用的训练脚本模板,它兼容GPU/CPU/Mac,核心就体现在device这个参数上:
# train_smoking.py from ultralytics import YOLO # 1. 加载模型 model = YOLO("yolo11s.pt") # 2. 开始训练 results = model.train( data="data.yaml", # 类别配置 epochs=200, # 数据量小,给足轮数 patience=30, # 30轮没提升就早停,防止过拟合 imgsz=640, batch=16, # 按显存调整,CPU建议8 device="0", # "0"=第一张GPU, "cpu"=CPU, "mps"=Mac workers=4, # Mac上改成0 optimizer="auto", # 让ultralytics自动选优化器 seed=42, # 固定随机种子,保证可复现 project="runs/smoking",# 输出目录 name="exp1", # 本次实验名 exist_ok=True, # 覆盖同名目录,否则会报错 )参数说明里有两个容易被忽略的:patience和seed。patience=30是早停机制,训练了70轮发现val精度不再上涨,脚本会自动停止并保留最优权重,这比硬跑200轮省电也省时间,尤其对CPU和Mac用户来说,能少跑一个小时是一小时。seed=42则是固定随机种子,保证每次训练的数据增强、随机初始化都一致,这样你做对比实验时(比如对比yolo11n和yolo11s)才有说服力。
训练完成后你会看到runs/smoking/exp1/weights/best.pt这个文件,记住它的路径,后面验证和推理都要用到它。
5.2 验证脚本:训练完第一件事不是看loss,而是看单张图效果
训练结束后的验证分成三个层级,建议按顺序做:
第一层是看ultralytics自带的验证指标:
yolo val model=runs/smoking/exp1/weights/best.pt data=data.yaml这个命令会对所有验证集图片做推理,然后计算mAP50、mAP50-95、precision、recall这些指标。对抽烟检测这个单类任务来说,主要看mAP50,这个值在0.9以上基本够用,mAP50-95在0.7以上就比较理想,如果mAP50只有0.8以下,先不要调模型结构,回头检查一下你的标注质量(有没有漏标、错标)和数据集划分是否随机。
第二层是抽检一批真实图片,用训练好的权重做可视化预测,肉眼判断效果:
yolo predict model=runs/smoking/exp1/weights/best.pt source=data/images/val save=Truesource可以指向一个文件夹,save=True会把预测结果图保存到runs/detect/predict。这一步的目的是看模型的实际表现:有没有把雪茄、电子烟误检成普通香烟,有没有在强背光环境下漏检,有没有把手指误检成烟头。1000张图的模型这些问题都存在,关键是要知道哪些问题在你的数据分布下出现了。
第三层是验证脚本对单张图输出检测结果的信息量。我用的是这样的方式:
from ultralytics import YOLO model = YOLO("runs/smoking/exp1/weights/best.pt") results = model.predict("test_images/lobby_01.jpg", conf=0.5, device="0") # 打印检测结果 for r in results: for box in r.boxes: cls_id = int(box.cls[0]) conf = float(box.conf[0]) xyxy = box.xyxy[0].tolist() print(f"class={model.names[cls_id]}, confidence={conf:.2f}, box={xyxy}")这段代码比直接看指标更贴近实际需求:它展示如何遍历检测结果并拿到每个目标的类别、置信度和边界框坐标,之后接业务逻辑(比如发告警、抓截图)就是在这个输出上做文章。
5.3 从1000张数据到落地部署的前后两步
数据只有1000张时的落地策略和通用目标检测不太一样。核心原则是:不要追求一次到位的高精度,先把模型放进现场跑起来,收集误报漏报的数据,形成第二批标注数据再做增量训练。
我一般会建议按这个节奏推进:第一批模型只追求mAP50达到0.8以上且没有严重的系统性误检(比如把所有白色物体检测成烟),然后在小范围试点场景部署;现场返回的误报截图每周清洗一次,挑出20到50张典型bad case,用同一个标注规范补充标注,混入原训练集重新训练一轮。第二轮训练通常就是20到30分钟,迭代三到五轮后模型基本能适应现场的光线、摄像头的角度、人的走动方式。
增量训练的做法也很简单,不需要从头训练,基于已有的best.pt继续train就行:
yolo train model=runs/smoking/exp1/weights/best.pt data=data.yaml epochs=50注意这时候data.yaml要更新——补充的新图片要放到images/train里,对应的标注文件放到labels/train里,然后重跑一遍训练。epochs=50表示在此基础上再训练50轮,而不需要重新加载COCO预训练权重。这个方法对数据量小、业务场景固定的抽烟检测来说非常有效,比换更大模型收益更大。
6. 边界框后处理与推理加速:抽烟检测模型落地前的最后一道工序
模型训练完,权重文件也验证过了,接下来的工作是把模型用起来。很多人觉得训练完就结束了,结果在推理阶段发现速度不够快、结果不够准。我自己跑这类项目得到的经验是:模型落地前要处理两件事——边界框的后处理策略和推理脚本的封装方式。
先讲边界框后处理。YOLO11的默认输出已经带了NMS(非极大值抑制),所以框的重叠问题不太需要操心。但在抽烟检测场景里,有个特殊问题:同一帧里可能同时出现人嘴边的烟和手里的烟,模型会输出两个高度重叠的框,一个落在人脸附近,另一个落在于手附近。如果你直接拿原始输出做统计,会出现“一个人被算成两次抽烟”的误判。我一般会在后处理里加一个简单规则:两个检测框的IoU超过0.6且类别相同,就合并为一个框,confidence取两者中的最大值。
def merge_overlapping_boxes(boxes, iou_threshold=0.6): """ boxes: list of [x1, y1, x2, y2, conf] 合并重叠抽烟检测框,防止同一目标被多次计数 """ boxes.sort(key=lambda x: x[4], reverse=True) merged = [] while boxes: best = boxes.pop(0) keep = [] for box in boxes: # 计算IoU x1 = max(best[0], box[0]) y1 = max(best[1], box[1]) x2 = min(best[2], box[2]) y2 = min(best[3], box[3]) inter = max(0, x2 - x1) * max(0, y2 - y1) area_best = (best[2] - best[0]) * (best[3] - best[1]) area_box = (box[2] - box[0]) * (box[3] - box[1]) iou = inter / (area_best + area_box - inter + 1e-6) if iou < iou_threshold: keep.append(box) merged.append(best) boxes = keep return merged这个后处理逻辑相当于是给模型加了一道“业务逻辑阀门”,训练阶段完全不用管,推理阶段加上它才能让输出结果跟业务预期对齐。还有一种情况是同一个目标在相邻多帧里反复出现,那是跟踪算法(ByteTrack之类)的范畴,这里不展开,但你至少要知道光靠单帧检测做抽烟行为统计会严重虚高。
再讲推理加速。如果你要把模型部署到CPU机器上做实时推理(比如厂区出入口的闸机一体机),YOLO11s在CPU上跑640分辨率差不多10到20 FPS,勉强够用,但如果你想在树莓派上跑,就建议做两件事:导出为ONNX格式并开启动态批处理。
from ultralytics import YOLO model = YOLO("runs/smoking/exp1/weights/best.pt") model.export(format="onnx", imgsz=640, dynamic=True)导出的ONNX模型可以用onnxruntime做推理,不需要再装PyTorch,而且推理速度会有明显提升。如果你用的是GPU部署,还可以导出为tensorrt格式,在大分辨率视频流上的吞吐量能再翻倍。这块内容比较深,但方法是明确的:先用export命令导出一个中间格式,再用对应推理引擎加载,均不需要重写模型结构代码。
说说我的收官习惯:每次训完抽烟检测模型,我不会直接交付,而是先在现场视频上连续跑3个小时,统计每帧的检测框数量和置信度分布。如果置信度普遍在0.7以上但数量忽高忽低,多半是重叠框没合并;如果置信度集中在0.3到0.5之间,说明模型学到的特征不够稳,这时候回头补标注比调阈值有效得多。这也是我在多个项目里被反复验证的一条经验,希望帮到你后续的实际部署少走点弯路。
本文还有配套的精品资源,点击获取