☰
YOLOv5鸟类检测实战:从数据清洗到模型部署
2026/9/28 22:01:59 网站建设 项目流程

简介:一套面向YOLOv5鸟类检测任务的数据集压缩包,提取自PASCAL VOCtrainval2012标准集,仅保留单一bird类别,适合需要训练实时目标检测模型的计算机视觉研究者和开发者,也适用于目标检测课程设计、算法对比及工程落地前的验证阶段。包体文件共2434个,包括812个txt标签、811个xml标注与811张jpg原图,压缩后大小约为90.55MB;txt文件记录边界框坐标和类别标识,xml文件遵循VOC规范描述更完整的目标位置、面积与相对关系,两类标签均能为YOLOv5提供可靠的监督信息,可直接用于模型训练和效果验证。已有2126人学习下载,这套数据来源于公开基准并经过单一类别筛选,免去了自行采集和标注鸟类的耗时工作,也降低了获取高质量训练数据的门槛。借助这套标注数据,还可以围绕数据增强、超参数调整、backbone替换及精度对比等方向开展实验,既能帮助初学者熟悉目标检测流程,也能作为研究者在鸟类识别方向微调和优化的基础数据集。

1. 鸟类检测为什么直接拿 yolov5 就能跑,数据集决定成败的一半

拿到一份「bird 鸟类检测数据集.rar」,很多人第一反应是赶紧解压、开训,结果半天就卡在环境上,或者训练出来 mAP 只有零点几。做鸟类目标检测和做 COCO 那种通用检测不太一样:鸟类目标尺度跨度大、背景复杂、同类不同亚种外观差异极小,所以数据集质量和标注一致性往往比模型结构更影响最终效果。yolov5 是当前把「单阶段检测 + 工程化易用性」平衡得最好的项目之一,它自带数据增强、多尺度训练、自动锚框和丰富的推理导出工具,对刚接触检测或者想快速验证数据集价值的人非常友好。这篇笔记我会沿着「拿到数据包 → 清洗整理 → 转成可用格式 → 训练调参 → 部署验证」这条线,把每一步的关键参数和踩坑记录讲清楚,适合想用现有鸟类数据集做识别系统、毕业设计或小规模巡检项目的读者。

2. 跑通 yolov5 鸟类检测的本地环境:conda 配置与源码版本的常见做法

2.1 用 conda 建环境时,Python 版本和 torch/cuda 的匹配规则

yolov5 的依赖不算复杂,但翻车最多的地方就是 torch 版本和 CUDA 版本对不上,导致 GPU 不可用、训练速度慢十几倍。常见做法是先装 NVIDIA 驱动,再装 CUDA toolkit,但实际训练只依赖 PyTorch 自带的 CUDA runtime,所以系统里装不装 CUDA toolkit 并不是必须的。你只需要确认nvidia-smi能正常输出显存信息,然后根据驱动版本安装对应支持的 PyTorch 即可。

conda create -n bird python=3.9 -y conda activate bird # 先确认驱动支持的 CUDA 版本,比如 12.1,再装对应 torch pip install torch==2.1.2 torchvision==0.16.2 --index-url https://download.pytorch.org/whl/cu121

这段命令的前提是你已经用nvidia-smi查过驱动支持的 CUDA 版本。torch==2.1.2对应torchvision==0.16.2,这个组合在 Python 3.9 下非常稳定,也是 yolov5 官方 requirements 里兼容性较好的版本区间。如果显卡比较老,比如 GTX 10 系列,建议改用cu118而不是cu121,否则部分算子会报「no kernel image available」的错误,这是很多新手第一次跑训练时最容易碰到的黑匣子问题。CPU 环境就把--index-url整段去掉,但训练速度会慢到让人怀疑人生,不推荐用来训鸟类检测。

装完 torch 后,再装 yolov5 的其余依赖。一般流程是克隆源码后执行pip install -r requirements.txt,但这里有个坑:requirements.txt 里会再次安装 torch 和 torchvision,可能会覆盖你刚才装好的 CUDA 版本。我习惯先用grep把这两行注释掉,再安装其他依赖,这样能保证 torch 版本不被破坏。

git clone https://github.com/ultralytics/yolov5.git cd yolov5 sed -i 's/^torch.*/# torch skipped/' requirements.txt sed -i 's/^torchvision.*/# torchvision skipped/' requirements.txt pip install -r requirements.txt

sed注释掉 torch 相关行是关键一步。官方 requirements 中的 torch 版本会跟随当时的默认配置走,如果它装了 CPU 版或者更高版本,可能与你已有的环境冲突。剩下的依赖主要是 numpy、opencv-python、matplotlib、pyyaml、tqdm 这些,版本要求宽松,直接装完即可。装完后运行python -c "import torch; print(torch.cuda.is_available())",输出True就代表 GPU 可用,这是后续一切训练的前提。

2.2 拉取 yolov5 源码后,先跑通一张图的推理基线

环境配好后的第一件事不是急着处理数据集,而是先用自带权重跑一次推理,确认整个链路是通的。yolov5 的detect.py会自动下载 COCO 预训练权重,国内网络环境下可能需要多试几次,或者手动把权重文件放到weights/目录下再运行。第一次跑通的最小命令如下:

python detect.py --weights yolov5s.pt --source data/images/bus.jpg --conf-thres 0.5

这条命令会用 yolov5s 模型对示例图片做推理,结果默认保存在runs/detect/exp目录。--conf-thres 0.5表示置信度阈值,低于 0.5 的预测框会被过滤掉。如果能正常输出带框的图片,说明环境、源码、权重三步都已经就绪。这时候你还可以用--img 640设置输入尺寸,yolov5 默认会做 letterbox 缩放,不会因为图片宽高比例不同而变形。

有一个容易被忽略的点:detect.py默认会自动下载权重,但如果你的网络环境无法直接访问 GitHub,可以换成用 pip 安装的ultralytics包来下载,或者去官方 release 页手动下载。手动下载后要注意权重文件必须放在 yolov5 源码根目录或者任意可访问路径,并用--weights指定完整路径,否则会报FileNotFoundError。跑通这一步后,你已经有了一条可靠的基线,后面不管是转换数据集还是调参,都可以随时跑一张图来确认修改没有破坏整体流程。

2.3 为什么建议固定 yolov5 版本而不是无脑用最新

很多人会直接git clone最新代码,但 yolov5 的 master 分支经常更新,有些改动会导致训练结果和文档描述不一致。常见做法是切到一个稳定的 release 版本,比如v6.2,因为这个版本对应的大多数教程、超参数讨论和第三方工具都是可用的,踩坑经验也最丰富。

git checkout v6.2

切换版本后,requirements.txt可能会有细微变化,重新执行一次安装即可。固定版本的好处在于:你在网上搜到的大多数参数讨论、训练命令和数据格式说明,都以这个版本为基础。如果直接用 master,很可能遇到 API 变动,比如detect.py的参数改名、配置文件结构变化,这些都会让你在排查问题时浪费大量时间。另外,值得留意的是 yolov5 本身有较强的数据集自适应能力,它在训练时会自动计算锚框,但前提是你的数据和标注格式正确,这就引出了下一章要说的内容。

3. 解压 bird 鸟类检测数据集后,先做这三件事再谈训练

3.1 解压后第一件事:检查目录结构与标签格式,防止数据和代码各说各话

拿到「bird 鸟类检测数据集.rar」这样的压缩包,第一步不是急着看图片,而是先看解压后的目录长什么样。常见的数据集结构有几种:VOC 风格的Annotations/存放 xml 标注、JPEGImages/存放图片;COCO 风格的单一 json 文件加图片文件夹;也有直接给你 YOLO 格式 txt 标注的。不同格式对应 yolov5 的不同处理方式,搞混了会直接报「No labels found」。我一般会先执行一个命令把目录树拉出来看:

find . -maxdepth 3 -type d | head -20 find . -name "*.xml" | head -5 find . -name "*.txt" | head -5 find . -name "*.json" | head -5

这个命令会列出三层以内的子目录,以及 xml、txt、json 三种标注文件的数量分布。看到结果后你就能判断这份数据集是哪一种格式或混用格式。如果三种格式都有,不要慌,很多数据集的标注文件确实是冗余存储的,只需要选一种作为训练格式。判断标准很简单:看images目录下的图片文件是否都能在标注目录里找到对应文件,以及标注文件数量是否接近图片数量。如果差距超过 5%,说明存在漏标注的样本,需要做进一步清洗。这一步花十分钟,能省掉后面排查训练时「一个 label 都没有」问题的几个小时。

3.2 第二件事:过滤损坏图片与标注不完整的样本,用脚本批量完成

鸟类检测数据集最大的特点是什么?很多图片是野外拍摄的,会有运动模糊、遮挡、景深虚化,甚至一些图片本身是损坏的。yolov5 在训练时如果遇到无法解码的图片,默认会报错跳过,但报错信息很隐晦,不会直接告诉你是哪张图的问题。所以动手训练前,用一段脚本把损坏图片和空标注样本筛掉是最保险的。

import os from PIL import Image img_dir = "bird_dataset/images" label_dir = "bird_dataset/labels" # 假设已有txt标注目录 for name in os.listdir(img_dir): path = os.path.join(img_dir, name) try: with Image.open(path) as im: im.verify() except Exception: print(f"损坏图片: {name}") continue base = os.path.splitext(name)[0] label_path = os.path.join(label_dir, base + ".txt") if not os.path.exists(label_path) or os.path.getsize(label_path) == 0: print(f"标注缺失或为空: {name}")

这段脚本的逻辑很简单:Image.verify()会检测文件是否可以被 PIL 正确解析,解析不了的就是损坏图片;同时检查同名 txt 标注文件是否存在且非空。输出结果可以重定向到日志文件,然后手动或批量删除。注意这里PIL能打开的图片和 OpenCV 能读取的图片并不完全一致,个别情况下 PIL 验证通过但 cv2 读出来是空矩阵,稳妥的做法是两种库都过一遍,但大部分场景下只做 PIL 检查就够了。

这个步骤有个容易被忽视的细节:标注为空的 txt 文件(0 字节文件)和完全不存在是两回事。yolov5 对这两种情况都会跳过图片,但训练日志里不会明说,只会显示「Scanning labels... 0 labels found」之类的话。如果你发现训练时前面扫描过程特别快,而且 loss 一直是 NaN,多半就是数据集里大量空标注导致的问题。

3.3 第三件事:按 train/val 比例划分数集并写对 data.yaml,类名顺序有讲究

yolov5 训练不认数据集自带的原始目录结构,它只认你给的data.yaml文件。这个文件里要指定train、val的图片路径,以及nc(类别数)和names(类别名称列表)。很多数据集的压缩包里已经包含了划分好的 train/val 目录,但更多的包只给你一个JPEGImages和Annotations,需要自己划分。

train: bird_dataset/train.txt val: bird_dataset/val.txt nc: 5 names: ["sparrow", "magpie", "crow", "pigeon", "swallow"]

这里的train.txt和val.txt是图片路径列表文件,每行一个绝对路径或相对于项目根目录的路径。常见做法是先用脚本生成这两个 txt,再在data.yaml里引用它们。划分类别名时要注意顺序:如果数据集自带一份classes.txt或labels.txt,必须以那个文件为基准。因为训练时模型输出的类别索引是根据names列表的顺序定死的,如果顺序和标注文件里的类别 ID 不对应,训练出来的模型会「张冠李戴」,识别框位置正确但类别全错,这种问题特别隐蔽,靠看 mAP 根本发现不了,必须抽几张图可视化验证才能警觉。

生成 train/val 路径列表时,我一般直接用 Python 做 8:2 划分加随机种子,保证每次跑实验的可复现性。操作步骤如下:先把所有图片文件名读出来,random.shuffle打乱,前 80% 写入train.txt,后 20% 写入val.txt,每个路径用绝对路径。注意图片文件后缀可能是.jpg或.jpeg,在生成列表时不要写死后缀,直接拼接完整文件名最稳妥。

4. 把 VOC/COCO 格式标注转换成 yolov5 的 txt:转换脚本与四个边界坑

4.1 三种标注格式的本质差异:归一化坐标、类别索引和坐标系

yolov5 的标注格式是每行一个目标,格式为class x_center y_center width height,其中四个坐标值都是相对于图片宽高的归一化数值,范围 0~1。而 VOC 格式的 xml 里记录的是xmin、ymin、xmax、ymax的绝对像素坐标;COCO 格式的 json 里记录的是bbox的[x, y, width, height]绝对像素值。三种格式之间的转换核心就是坐标系的变换和归一化,没有任何玄学,但要细心处理边界。

格式坐标表示存储位置yolov5 转换要点
VOC xmlxmin, ymin, xmax, ymax 绝对像素一个目标一个 xml 文件需要自行读文件名与图片尺寸匹配
COCO json[x, y, width, height] 绝对像素单一 json 文件、按 image_id 索引需要处理图片 id 与标注 id 的映射
YOLO txtclass, cx, cy, w, h 归一化一个图片对应一个 txt本身就是训练所需格式,无需转换

转换过程中最常见的问题是拿不到图片的真实宽高。VOC 的 xml 里通常带有size字段,包含width和height,但有些数据集提供者会把这部分删掉。如果读取不到原始宽高就无法计算归一化坐标,我一般用 PIL 读图片的shape属性来补充。这里有一个易错点:txt 转换时用到的归一化是除以图片宽度和高度,而不是除以 640 或任何训练尺寸,很多人误把模型输入尺寸套进来,导致标注框缩小或偏移,训练时 loss 下降但检测框位置不对。

4.2 一个可以改着用的 VOC 转 YOLO 脚本,英文注释保证少踩坑

下面这个脚本是我常用的转换模板,把 VOC 的 xml 标注转换到 YOLO txt,兼容多类别场景。使用前需要修改xml_dir、save_dir、class_list三个变量的值。这段代码可以直接复制后按自己的数据集修改,关键逻辑我加了英文注释,方便跨系统使用时保持编码一致。

import os import xml.etree.ElementTree as ET xml_dir = "bird_dataset/Annotations" save_dir = "bird_dataset/labels" class_list = ["sparrow", "magpie", "crow", "pigeon", "swallow"] os.makedirs(save_dir, exist_ok=True) for xml_file in os.listdir(xml_dir): if not xml_file.endswith(".xml"): continue tree = ET.parse(os.path.join(xml_dir, xml_file)) root = tree.getroot() # get image size from xml size = root.find("size") width = int(size.find("width").text) height = int(size.find("height").text) lines = [] for obj in root.iter("object"): cls = obj.find("name").text if cls not in class_list: continue cls_id = class_list.index(cls) bbox = obj.find("bndbox") xmin = int(float(bbox.find("xmin").text)) ymin = int(float(bbox.find("ymin").text)) xmax = int(float(bbox.find("xmax").text)) ymax = int(float(bbox.find("ymax").text)) # clamp to image boundary xmin = max(0, xmin) ymin = max(0, ymin) xmax = min(width, xmax) ymax = min(height, ymax) if xmax <= xmin or ymax <= ymin: continue # convert to yolo format x_center = (xmin + xmax) / 2.0 / width y_center = (ymin + ymax) / 2.0 / height w = (xmax - xmin) / width h = (ymax - ymin) / height lines.append(f"{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}") base = os.path.splitext(xml_file)[0] save_path = os.path.join(save_dir, base + ".txt") with open(save_path, "w") as f: f.write("\n".join(lines))

脚本的逻辑分四步:先解析 xml 找图片尺寸,再做类别名到 ID 的映射,然后遍历每个目标把绝对坐标转成归一化中心点加宽高,最后写成 txt。三个参数要注意:第一,class_list的顺序必须和最终训练时data.yaml里的names顺序保持一致,一旦不一致会出现「框对、类错」的问题;第二,width和height一定要从 xml 里读,而不是从文件名或文件夹猜测,因为 JPEG 图片可能存在 EXIF 旋转信息,实际解码尺寸可能和 xml 记录的原始尺寸不同;第三,坐标 clamp 一定要做,部分数据集的标注框会超出图片边界几个像素,不处理会让归一化后的数值大于 1,训练时 yolo 计算损失会异常。

4.3 四个边界坑:坐标越界、多标签混用、类名映射错位、图片尺寸缓存

转换脚本跑完后,你可能会发现训练效果非常差,或者干脆没有检测框。根据实际经验,以下四个坑出现频率最高。第一个坑是坐标越界:标注框的右下角坐标大于图片的宽高,导致归一化后 w/h 超过 1。我用上述脚本中的min和max做 clamp 解决。但要注意,如果一张图里某个目标缩小到只剩一个点(w 和 h 都接近 0),yolov5 训练时会把它视为无效标签,所以脚本里加了xmax <= xmin的判断直接跳过,避免空标注文件导致整张图被废弃。

第二个坑是数据集里混用多套标注体系。很多鸟类数据集合集中 xml、json、txt 都提供,但内容并不完全一致:某个目标在 xml 里标注了,json 里却没有。解决方法是只选一套作为训练标注来源,不要混着用。这个坑的表现很隐蔽,训练日志不会报错,但 mAP 会异常偏低且涨不动。

第三个坑是类名映射错位,也是翻车概率最高的问题。有些数据集的 xml 里类名是「bird」,标签文件 txt 里是「1」,而data.yaml里 names 的第一项是「bird」。看起来顺序一致,但如果数据集里的类别索引是「1」开头而不是「0」开头,模型会默认少一类。转换脚本用class_list.index(cls)按名称映射 ID,代码本身没错,但前提是你已经确定了类别集合且没有遗漏。我在处理大压缩包时经常遇到 xml 里有一两个样本的类名是拼写错误的变体,比如sparrow写成sparrow1,这会导致该样本被过滤掉,而不是报错。所以转换完成后一定要统计一下每个类别的样本数量,看是否存在异常少的类。

第四个坑是图片尺寸缓存问题。如果你用 PIL 读取图片尺寸做转换,而标注的 xml 里也写了尺寸,两者可能在个别样本上不一致,尤其是经过缩放或裁剪的图片。这种冲突会导致归一化坐标偏差。稳妥的做法是以训练时实际使用的图片尺寸为准,也就是直接调用 cv2 读取图片的shape,而不是依赖 xml 里的size字段。代价是多读一遍图片,时间增加一些,但对最终的标注准确率很值。转换完成后,还要做一次反向验证:随机抽几张图,把 txt 里的坐标转回绝对像素画框,人眼确认框是否贴合目标。这一步耗费十分钟,但能避免大量隐性错误进入训练流程。

5. yolov5 鸟类检测训练的必调参数、可视化验证与避坑记录

5.1 训练命令与超参数解释:img、batch、epochs、hyp 这几个最常用

数据准备好后,训练命令本身并不复杂,但参数怎么设需要理解。常用的训练命令模板如下:

python train.py --data bird.yaml --weights yolov5s.pt --img 640 --batch 16 --epochs 100 --cache

--weights yolov5s.pt表示基于 COCO 预训练权重做迁移学习,这是鸟类检测的标准做法。如果你从零训练,需要改成--weights "",但除非数据量超过几万张,否则不建议从头训,因为 COCO 预训练模型已经学会了通用的边缘纹理特征,鸟类检测的收益远大于迁移成本。--cache参数会把图片加载到内存中,显存够的情况下能显著加快训练速度,但内存如果小于 32GB 建议不要开,否则容易 OOM。

--img 640是训练输入尺寸。如果你发现数据集中鸟类目标普遍很小,比如在树梢上的鸟只有几十个像素,可以把--img 896或--img 1280调大,小目标召回率会有明显提升,但训练时间也会相应增加。由于鸟类数据集往往包含大量远距离拍摄的小目标,大部分情况下从--img 640起步、后续根据 mAP 曲线再调整是更稳妥的路径。批量大小--batch的选择受显存限制,一般 16 或 32 都算常见。如果你只有 8GB 显存,可以降到 8,配合梯度累积效果也不会太差。

5.2 小样本数据集的超参数调整:用 hyp 文件控制增强强度,防止过拟合

鸟类检测数据集的规模往往不大,上千张或者几千张居多。此时最容易出现的就是过拟合——训练损失很低,验证集 mAP 却上不去。yolov5 通过--hyp参数指定增强策略配置文件,默认的data/hyps/hyp.scratch-low.yaml增强强度较低,适合数据量大的场景;而hyp.scratch-high.yaml增强了色彩扰动和缩放旋转,更适合小数据集。直接切换配置就能让 mAP 提升几个点。另一个常用手段是开启--multi-scale,让模型在训练时随机使用不同分辨率,相当于免费的数据增强。

对于特别小的数据集,我一般会额外修改 hyp 文件中的hsv_h、hsv_s、hsv_v三个值,控制色调、饱和度、明度的扰动范围。鸟类在不同光线和背景下外观会有较大变化,增强参数往高调有助于模型学到更鲁棒的特征。但要注意,增强过猛会导致训练 loss 不降,这是一对矛盾,需要在日志里观察增强后的图片是否仍然保留了鸟类的关键特征。如果换用hyp.scratch-high.yaml后 mAP 反而下降,多半是增强太强把关键纹理破坏了,需要降低degrees和fliplr参数而不是全盘放弃。

5.3 鸟类检测训练中的四个高频踩坑记录:现象、原因、解决办法

第一个坑是「loss 一直降但 mAP 不动」。现象是训练曲线正常下降,但验证集 mAP 始终在 0.3 附近徘徊。原因是数据集中存在大量标注框错位或漏标,模型学到了错误的回归目标。解决方法是回到第四章的转换脚本,可视化一批标注框,检查是否存在框的宽高比严重失真。鸟类数据集的标注往往来自不同标注人员,框的紧致程度差异很大,这种情况需要在训练前做标注过滤或手工修正,不能靠调参解决。

第二个坑是「类别间样本极不平衡」。现象是常见鸟类如麻雀、鸽子样本多,稀有鸟类样本只有几十张,模型对稀有类完全检测不到。原因是交叉熵损失被多数类主导。解决方法是按类别统计样本数,对明显过少的类别做过采样。常见的做法是把稀有类对应的图片在训练集中复制几份,或者使用--class-weight参数对损失做加权。但需要注意加权过大会导致模型对高频类产生误检,所以权重值一般不超过 5。

第三个坑是「显存不足直接 OOM」。现象是训练开始后很快报CUDA out of memory。原因是 batch size 或图片尺寸过大,也可能是缓存了太多数据。解决方法是先把 batch 降到 8 或 4,再把--workers降到 4,最后再考虑把--img降到 480。如果显存只有 6GB,可以考虑用--device 0 --sync-bn关闭同步批归一化,同时把--batch设为 8。还有个小技巧:训练日志中显存占用高峰出现在每个 epoch 刚开始时,所以观察显存不要只看初期几秒,要等到一个 epoch 跑完再判断。

第四个坑是「识别结果几乎全是背景区域误检」。现象是推理时置信度不低的框往往落在树枝、树干或天空区域。原因是数据集的负样本不足,模型没有见过足够多的背景区域。很多鸟类数据集只裁剪了包含鸟的图片,整个训练集里没有纯背景图。解决方法是收集一批不含鸟类的野外场景图,把它们作为负样本和原训练集混在一起,每 5 张正样本配 1 张负样本,重新训练后误检率能明显下降。我在实际项目中做过对比,加入负样本后 mAP-50 提升了六个点左右,这个操作常常被新人忽略。

5.4 训练后验证:混淆矩阵、PR 曲线与可视化预测结果

训练结束不代表工作完成,验证环节才是判断模型是否真的够用的关键。yolov5 训练完会自动在runs/train/exp/目录下生成confusion_matrix.png、PR_curve.png、F1_curve.png等文件。我一般先看混淆矩阵,重点检查稀缺类别之间是否存在大量互混淆。鸟类中相似物种本来就容易误判,比如乌鸦和喜鹊、麻雀和鹀,如果混淆矩阵显示两个类互相误判率高,说明特征区分度不够,需要补充对应类别的训练数据,而不是继续增加迭代次数。

接着用一批训练时没见过的图片做推理验证:

python detect.py --weights runs/train/exp/weights/best.pt --source your_test_images/ --conf-thres 0.25 --save-txt

--conf-thres 0.25是一个相对宽松的阈值,适合先看整体检测效果;如果误检多就调到 0.4,如果漏检多就降到 0.15。--save-txt会把预测结果保存为 txt 文件,方便后续脚本做定量分析。这一步能直观看到模型在不同场景里的表现。还要注意一个细节:best.pt和last.pt是有区别的。best.pt是验证集 mAP 最高的权重,last.pt是最后一次 epoch 的权重。在训练后期出现过拟合时,last.pt的泛化性能往往明显差于best.pt,所以部署和测试统一用best.pt即可。

6. 把鸟类检测模型导出 ONNX 并在本地做批处理推理的小技巧

训练完成后,你大概率不会只满足于跑通 demo。实际项目中经常需要把模型部署到服务端或者离线批量识别大量图片。yolov5 自带的export.py可以一键导出为 TorchScript、ONNX、TensorRT 等格式,但有几个小细节需要注意。导出 ONNX 时用命令行参数指定 opset 版本和动态输入尺寸,能让后续推理更灵活。

python export.py --weights runs/train/exp/weights/best.pt --include onnx --opset 12 --dynamic

--dynamic参数允许输入图像的宽高不固定,适合鸟类识别中图片尺寸参差不齐的场景。如果日常推理都用 640x640,可以不开启,这样模型体积稍小。ONNX 导出成功后,在本地做批量推理时可以直接用 onnxruntime 加载模型,不再依赖 PyTorch 环境,部署时更加轻量。推理脚本的核心逻辑是:读图 → letterbox 缩放 → 归一化 → forward → NMS 后处理 → 映射回原图坐标。

因为鸟类检测经常要处理连续监控截图或相机拍摄的海量图片,批量推理时我会把 NMS 阈值设为 0.45,置信度阈值设在 0.2 到 0.3 之间。低置信度阈值会让输出框变多,但配合 NMS 能保留更多重叠遮挡的鸟类目标;如果后续有人工审核环节,甚至可以降到 0.1,把候选框全捞出来再筛。日常项目里我的习惯是每次训练前都会固定随机种子,并把数据划分文件保存一份快照,这样后续复现实验时不会因为数据顺序改变而困惑。做完一轮完整流程后,最值得记录的是数据清洗和转换脚本,这些代码往往在新数据集上还能复用;模型权重反而只对当前数据集有效。希望这篇笔记能帮你在鸟类检测项目上少走几个坑,从数据包到可用模型的路径走得更顺。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询