YOLOv5花卉识别源码解析:从训练到部署的完整指南
2026/9/23 12:41:06 网站建设 项目流程

简介:面向深度学习与图像识别入门者,这套基于Python与Shell语言的YOLOv5花卉识别模型设计源码,是一套完整覆盖数据准备、模型训练、推理部署的智能识别工程实现。包体共一百零二个文件,体积仅一点一九兆字节,其中四十个YAML配置与十一个拓展模板负责定义数据集路径与训练超参数,三十二个Python源文件实现模型核心逻辑,五个Shell脚本可自动化批处理与部署流程;另有Docker容器配置、Jupyter教程和Markdown说明文档,便于快速搭建复现环境。目前已有三百七十人学习参考,这些模块协同工作,既可直接运行检测花卉,也可基于模板二次开发,迁移至其他目标检测或分类任务;结合Shell脚本还能灵活调整训练流程,非常适合作为深度学习初学者的完整实战参考,具有较高的参考价值。

1. YOLOv5花卉识别源码:这套 101 文件的项目到底能做什么

YOLOv5 花卉识别模型源码,严格来说不是一份“课程设计报告”,而是一份可以直接拉起来训练、推理的完整工程。它把 YOLOv5 目标检测算法和花卉识别这个垂直场景绑在一起,用 40 个 YAML 配置文件和 29 个 Python 源文件把数据定义、模型结构、训练参数、推理流程全部串起来。对刚入门深度学习的 Python 开发者来说,这份源码的价值在于:你能在一套公开的标准工程里,看到“数据怎么标、配置怎么改、权重怎么训、结果怎么出”的完整链路;对熟手而言,它又留着足够的自定义空间,直接换成自己的数据集就能跑。下面我按实际落地顺序拆解这套源码,把文件分工、训练参数、踩坑记录一次说透。

2. 项目骨架拆解:Python 文件、YAML 配置与 Shell 脚本的协作关系

2.1 Python 源文件的职责边界:train.py、detect.py 与 utils 家族

一个 YOLOv5 工程里,Python 文件并不是平均分摊工作量,而是严格分级:入口脚本只负责承接用户指令,核心逻辑全部下沉到utils/目录。这 29 个 Python 源文件里,你首先需要分清三个层级。

第一层是入口文件:train.py承担模型训练,detect.py承担推理预测,val.py承担验证集评估,export.py承担权重格式导出。这四个文件的特点是参数解析密集,几乎没有算法细节。你运行python train.py --data flower.yaml时,真正干活的是被调用的utils/datasets.py(数据加载)和utils/loss.py(损失函数)。

第二层是工具库:utils/目录里塞着数据集加载、增强策略、损失计算、指标评估、日志可视化等模块。举个具体例子,utils/datasets.pyLoadImagesAndLabels类负责读取标注文件、做 Mosaic 增强、缓存打标的图片到内存。这个类的设计决策直接影响训练速度——如果你的机器内存小,可以把cache_images参数从True改成False,代价是每个 epoch 多花时间读磁盘。

第三层是模型定义:models/目录下的yolo.py负责动态构建网络,common.py存放了ConvBottleneckC3SPPF等基本组件。YOLOv5 最值得称道的设计是:修改网络深度和宽度不需要改网络结构代码,只需要改 YAML 里的depth_multiplewidth_multiple两个参数。

提示:如果你的电脑连环境都没装好,建议先跳过 29 个 Python 文件逐个阅读这一步,直接把requirements.txt里的依赖装完,跑一次detect.py看到输出再回头看代码。

2.2 YAML 配置设计:三类配置文件不能混为一谈

这套源码里的 YAML 文件总数最多,但功能上必须分为三类理解。

第一类是数据集配置,典型如data/flower.yaml。它的字段结构是:

# data/flower.yaml train: ../datasets/flower/images/train # 训练集图片路径 val: ../datasets/flower/images/val # 验证集图片路径 nc: 5 # 类别总数:菊花、蒲公英、玫瑰、向日葵、郁金香 names: ['daisy', 'dandelion', 'rose', 'sunflower', 'tulip']

这段配置的逻辑很清楚:trainval告诉训练器从哪里读图片,ncnames共同定义了类别维度的语义。注意nc必须与names数组的长度一致,这个我在后面的避坑章节会专门展开——类别数不一致是训练报错的重灾区。

第二类是模型结构配置,比如models/yolov5s.yaml

# models/yolov5s.yaml nc: 5 # 覆盖为数据集的类别数 depth_multiple: 0.33 # 控制网络深度倍率 width_multiple: 0.50 # 控制网络宽度倍率 anchors: - [10, 13, 16, 30, 33, 23] # P3 特征层 anchor - [30, 61, 62, 45, 59, 119] # P4 特征层 anchor - [116, 90, 156, 198, 373, 326] # P5 特征层 anchor

depth_multiplewidth_multiple这两个参数的组合直接代表了模型规模。yolov5s 是 0.33 和 0.50,yolov5m 是 0.67 和 0.75,yolov5l 是 1.0 和 1.0。对于花卉这种类别少、目标尺度相对统一的任务,用 s 版本起步即可,没必要直接上 l。

第三类是超参数配置,即data/hyps/hyp.scratch-low.yaml。这里定义的是学习率、权重衰减、数据增强强度等训练过程参数。这三类配置文件的修改频率完全不同:数据集配置每次换数据都要改,模型结构配置定下来基本不动,超参数配置则需要根据训练曲线的表现反复调整。

2.3 Shell 脚本的自动化价值:从数据集准备到环境部署

这套源码里的 5 个 Shell 脚本,对照 YOLOv5 的标准工程,作用集中在三块:下载数据集、下载预训练权重、启动训练流程。get_coco.sh这类脚本是被复用的高频件,虽然它下载的是 COCO 数据集,但你完全可以改写它来拉取花卉数据集。

#!/bin/bash # 改造版:下载花卉数据集并完成解压 # 原脚本思路来自 get_coco.sh,核心逻辑保留,数据源替换 mkdir -p ../datasets/flower cd ../datasets/flower # 下载并解压花卉数据集压缩包 # wget -c 支持断点续传,避免大文件断了重来 wget -c https://example.com/flower_dataset.zip unzip -q flower_dataset.zip -d . # 生成训练/验证集目录划分 # 常见目录约定:images 下分 train 和 val,labels 结构与 images 对齐 mkdir -p images/train images/val labels/train labels/val

这段脚本的要点在最后两行——YOLOv5 的数据加载器默认按照imageslabels同级目录去寻找对应标注文件。如果数据集压缩包里的目录结构不是这样,你要么改脚本做重映射,要么改flower.yaml里的train路径。Shell 脚本在这里的价值不是“必须用 Shell 才能完成”,而是把一次性的环境准备工作固化成可重放的命令序列,换台机器重跑一遍就恢复环境。

Dockerfile 的存在也是同一逻辑:如果你要在服务器或者别人的机器上复现项目,docker build -t yolov5-flower .一步到位,包括 CUDA、PyTorch 在内的环境全部固化在镜像里。.dockerignore的作用则是防止把datasets/runs/这类大目录带进构建上下文,这个细节能帮你节省大量 Docker 构建时间。

# Dockerfile 关键段:锁定基础镜像版本,减少环境漂移 FROM pytorch/pytorch:1.12.1-cuda11.3-cudnn8-runtime # 安装系统依赖 RUN apt-get update && apt-get install -y libgl1 libglib2.0-0 # 复制项目代码并安装 Python 依赖 WORKDIR /yolov5-flower COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # 复制其余源码文件 COPY . .

版本锁定是这份 Dockerfile 里最值得借鉴的地方。pytorch/pytorch:1.12.1-cuda11.3-cudnn8-runtime这个 tag 写死了 PyTorch 和 CUDA 的版本组合,避免latest标签带来的不确定性——我见过不少翻车案例,都是因为拉了一个新版 PyTorch 镜像导致 CUDA 版本和本机驱动不兼容。

3. 环境与数据准备:从依赖安装到 YOLO 标注格式落地

3.1 依赖安装顺序与版本冲突避让

YOLOv5 的依赖集中在requirements.txt里,核心是 PyTorch、OpenCV、Matplotlib、Pandas、Seaborn 这些库。安装顺序有讲究,我一般先装 PyTorch 再装其他依赖:

# 创建独立 conda 环境,Python 版本锁定 3.8-3.10 conda create -n yolov5 python=3.9 -y conda activate yolov5 # 优先安装 PyTorch,CUDA 版本按本机驱动选择 # 本机驱动支持 CUDA 11.3,所以装对应版本 pip install torch==1.12.1 torchvision==0.13.1 --extra-index-url https://download.pytorch.org/whl/cu113 # 安装项目其余依赖 pip install -r requirements.txt

为什么强调这个顺序?因为requirements.txt里如果有torch>=1.8.0这样的宽松约束,pip 会自动解析并安装最新版 PyTorch。最新版 PyTorch 可能要求更高的 CUDA 版本,而你的显卡驱动根本带不动,最后跑train.py的时候直接报CUDA error: no kernel image is available。先手动装好适配本机驱动的 PyTorch,再让 pip 处理其他依赖,就不会出现这种版本倒挂。

依赖装完验证环境,我的习惯是先跑一次推理而不是直接开训练:

# 用项目自带的图片做推理,验证环境可用 python detect.py --weights yolov5s.pt --source bus.jpg # 输出应包含: # image 1/1 /path/to/bus.jpg: 640x640 4 persons, 1 bus, Done. (0.088s)

这一步能验证 PyTorch、模型加载、图像处理链路的完整性。如果detect.py能顺利输出目标框,说明环境基本没问题,可以进入数据准备阶段。

3.2 YOLO 标注格式的数据集目录规范

YOLO 系列对数据格式的约定非常严格,每个标注文件是.txt,文件名与图片名保持一致(不含扩展名),内容每一行代表一个目标:

# 对应一张图片里的第 1 个目标 <class_id> <x_center> <y_center> <width> <height> # 归一化坐标,取值范围 0~1 # 举例:类别 2(玫瑰)、中心点 (0.5, 0.4)、宽高 (0.3, 0.2) 2 0.500 0.400 0.300 0.200

这里最容易犯的错误是坐标格式混用。YOLO 格式要求的是归一化后的中心点坐标,而 LabelImg 等标注工具导出 XML 时给出的是左上角和右下角的绝对像素坐标。两者之间必须做一次换算:

# 将 VOC 格式(左上角右下角)转换为 YOLO 格式的脚本片段 import os def voc_to_yolo(x1, y1, x2, y2, img_w, img_h): """ 参数:边界框左上角(x1,y1)、右下角(x2,y2)、图像宽高(img_w, img_h) 返回:YOLO 格式的归一化中心点和宽高 """ # 计算框的实际宽高像素值 box_w = x2 - x1 box_h = y2 - y1 # 中心点坐标换算为归一化值 x_center = (x1 + box_w / 2.0) / img_w y_center = (y1 + box_h / 2.0) / img_h # 宽高换算为归一化值 norm_w = box_w / img_w norm_h = box_h / img_h return f"{x_center:.6f} {y_center:.6f} {norm_w:.6f} {norm_h:.6f}"

这个换算看起来是小学数学,但实际翻车的点在于四舍五入精度。如果你把坐标保留到小数点后两位,小目标(比如远处的郁金香花朵)的框可能会偏移 3% 以上,直接影响 mAP 评估结果。我一般保留六位小数,这是 YOLOv5 官方标注文件的标准精度。

目录结构方面,正确的布局应该是:

datasets/flower/ ├── images/ │ ├── train/ # 训练集图片,约 2500 张 │ └── val/ # 验证集图片,约 500 张 └── labels/ ├── train/ # 与 images/train 一一对应的 txt 标注 └── val/

一个经常被忽略的坑:labels目录下如果存在没有对应图片的标注文件,或者图片找不到标注文件,YOLOv5 会输出WARNING: Ignoring corrupted image and/or label然后跳过该样本。少量跳过没问题,但如果跳过数量超过总数的 5%,意味着你的数据本身就有质量问题,训练出来的模型精度必然受影响。

3.3 data 配置修改:路径、类别名和验证集划分的细节

data/flower.yaml里,路径写的是../datasets/flower/images/train,这是相对于你运行训练命令所在目录的路径。我的经验是:要么始终在项目根目录下执行训练,要么把配置里的路径改成绝对路径。很多新手把训练命令放到datasets/flower目录下执行,结果路径解析错误,报AssertionError: train: ../datasets/flower/images/train does not exist

验证集的作用是监控训练过程中的过拟合,而不是参与训练。配比上,我从不为验证集单独采样,而是直接用train/val的目录划分。如果数据集总量小于 1000 张,我建议采用 9:1 划分,因为验证集太小的话 mAP 曲线的抖动会非常剧烈,难以判断模型是否真正收敛。

注意:YOLOv5 的数据加载器会自动做多种数据增强,包括 Mosaic、随机仿射变换、HSV 色彩增强。训练集图片数量越少,增强策略的影响越显著,这是正常现象,不要看到训练集 loss 不降就认为是代码问题。

4. 训练与推理实战:命令行参数背后的边界条件

4.1 训练命令拆解:每个参数改的是什么

YOLOv5 的训练入口是train.py,它接收的每个参数对应训练流程中的一个独立决策点。下面是一条典型的训练命令:

python train.py \ --data data/flower.yaml \ # 数据集配置 --weights yolov5s.pt \ # 预训练权重,迁移学习起点 --img 640 \ # 输入图片尺寸,单位像素 --batch-size 16 \ # 单次迭代的样本数 --epochs 100 \ # 总训练轮数 --device 0 \ # GPU 设备编号,-1 为 CPU --workers 8 \ # 数据加载线程数 --cache ram \ # 缓存图片到内存,加速读取 --project runs/ \ # 训练输出目录 --name flower_run # 本次训练的名称标识

--weights参数值得细说:yolov5s.pt是在 COCO 数据集上预训练好的权重。用它做迁移学习的起点,相当于模型已经学会了通用的边缘、纹理、形状特征,你只需要让它适应花卉这个新任务。如果改成--weights ''(空字符串),模型会从零开始训练,收敛速度和最终精度都会明显差一截。对花卉识别这种数据量在几千张级别的项目,务必使用预训练权重。

--cache ram是我在新项目里必开的参数。它的原理是把打标后的图片矩阵缓存到内存中,省去每个 epoch 重新读磁盘的开销。代价是内存占用上升,16GB 内存的机器跑 2500 张 640×640 图片勉强够用。如果你的内存紧张,宁可把--workers降下来也别关 cache。

4.2 超参数文件:yolov5 花卉识别场景下的调参侧重点

YOLOv5 的超参数文件不仅控制学习率这类基础优化器参数,还控制几十项数据增强策略的强度。这些增强手段在训练时随机对图片做扰动,相当于免费扩充数据集。花卉识别场景下,我关注的超参数有三个:

# data/hyps/hyp.scratch-low.yaml 关键字段 lr0: 0.01 # 初始学习率 lrf: 0.01 # 最终学习率 = lr0 * lrf,即 0.0001 momentum: 0.937 # SGD 动量系数 weight_decay: 0.0005 # 权重衰减,防止过拟合 hsv_h: 0.015 # HSV 色相增强幅度 hsv_s: 0.7 # 饱和度增强幅度 hsv_v: 0.4 # 明度增强幅度 fliplr: 0.5 # 水平翻转概率

花卉识别里,hsv_h这个参数比在通用目标检测里更敏感。因为不同花卉的颜色本身就是重要的区分特征,如果把色相增强设得过大(比如hsv_h: 0.1),训练集里红色的玫瑰可能会被随机增强成蓝色,模型会困惑于“颜色到底算不算特征”,最终在真实场景的红色玫瑰上表现不佳。我通常把hsv_h从默认值下调一半到0.0075,同时保留饱和度增强——因为同一朵花在不同光照下饱和度变化是真实的自然现象。

学习率方面要注意一个细节:YOLOv5 采用的是“前 3 个 epoch 预热 + 余弦退火”的策略,lr0是峰值学习率而不是起始值。如果你训练了 20 个 epoch 发现 loss 在高位震荡,第一反应不应该是调低学习率,而是检查是否收敛到错误的局部最优——这时把lr0从 0.01 调成 0.001 重训,往往效果立竿见影。

4.3 detect.py 推理:单张图片与批量场景的差异

训练完成后,推理流程通过detect.py驱动。先看单张图片场景:

# 单张图片推理 python detect.py \ --weights runs/train/flower_run/weights/best.pt \ --source data/images/test.jpg \ --conf-thres 0.25 \ # 置信度阈值,低于该值的检测框被丢弃 --iou-thres 0.45 \ # NMS 的 IoU 阈值,控制重叠框的合并策略 --img 640 \ # 推理时保持与训练一致的输入尺寸 --save-txt # 同时输出标注文件

推理时的--img参数必须和训练时保持一致。如果你用 640 训练、用 1280 推理,模型的感受野和 anchor 尺度匹配关系会错位,小目标检测率反而下降,不是分辨率越高越好。

--conf-thres--iou-thres这两个参数在花卉识别里有特殊的调优空间。花卉检测不像行人检测那样要求召回率优先,比如做花田统计时,漏检几朵效果不大,但误检会直接污染统计结果。这时可以把--conf-thres提高到 0.4 甚至 0.5,牺牲少量召回换取更干净的检测结果。批量场景的差异在于:处理视频或大规模图片目录时,输出结果不再是一张带框的图,而是一份包含坐标、类别的结构化文件:

# results 目录下生成的 labels 文件,每行一条检测结果 # 格式:<class> <confidence> <x_center> <y_center> <width> <height> 2 0.873 0.521 0.314 0.278 0.356 0 0.654 0.781 0.203 0.167 0.231

这份文件是后续做统计分析的基础。比如你要统计一片花田里玫瑰和郁金香的数量,直接解析这个 txt 文件按类别累加即可,不需要调用任何模型接口。

5. 避坑排查:花卉识别训练中五个翻车场景的复现与修复

5.1 训练中途崩溃:CUDA out of memory

现象:train.py跑了几个 batch 后直接报错RuntimeError: CUDA out of memory. Tried to allocate 2.00 GiB

原因:显存不足,通常是 batch-size 设置过大,或者--cache ram把内存占满后触发了 GPU 和 CPU 之间的数据搬运瓶颈。

解决:先看 GPU 显存容量再定 batch-size。8GB 显存跑 yolov5s + 640 输入,稳妥值是 8;16GB 显存可以开到 16。如果非要开 32,必须用梯度累积模拟:把--batch-size设为 8,同时在train.py源码的train()函数里找到accumulate = max(round(64 / batch_size), 1)这一行,保持不动即可,YOLOv5 已经内置了梯度累积的逻辑,64 / 8 = 8,等价于每 8 个小 batch 做一次参数更新,实际效果接近 64 的大 batch。

5.2 验证集 mAP 为 0:类别配置张冠李戴

现象:训练正常跑完 100 个 epoch,mAP@0.5显示 0,但训练集 loss 正常下降。

原因:data/flower.yamlnames列表顺序与数据集标注文件的class_id不一致。比如标注文件里0代表雏菊,但配置里names[0]写成了郁金香,模型学到的特征和类别标签对不上,验证时所有预测都被判为错误类别。

解决:逐张核对标注文件的类别 ID 与 YAML 配置的映射关系。

# 检查标注文件里出现了哪些类别 ID # 对 labels 目录下所有 txt 文件提取第一个字段并排序统计 cat ../datasets/flower/labels/train/*.txt | awk '{print $1}' | sort | uniq -c

如果输出显示类别 ID 只有 0-3 四个值,但配置里写了nc: 5,说明数据集缺失某个类别的样本。此时训练仍能进行,但那个缺失类别的精度永远为 0。这也是nc与标注实际不一致的典型表现。

5.3 推理时漏检严重:训练和推理的分辨率不一致

现象:训练时 mAP 有 0.85,但拿手机拍的真实花卉照片做推理,大量花朵检测不到或框位置偏移。

原因:detect.py执行时用了默认的--img 640,但训练时用的--img 416。分辨率不一致导致模型输出的特征图尺寸变化,anchor 的尺度匹配关系完全失效。

解决:检查训练输出目录下的opt.yaml文件,找到训练时的imgsz参数,推理时严格保持一致:

# 查看训练参数记录 cat runs/train/flower_run/opt.yaml | grep imgsz # 推理时带上与训练一致的尺寸 python detect.py --weights runs/train/flower_run/weights/best.pt \ --source test.jpg --img 416

5.4 训练极慢:DataLoader workers 导致的进程阻塞

现象:训练时每个 epoch 耗时从 3 分钟暴涨到 20 分钟,GPU 利用率显示 30% 左右。

原因:Shell 脚本启动训练时没设置--workers,默认值 8 在部分平台上会启动过多子进程。这些子进程抢占 CPU 资源,导致 GPU 一直在等待数据加载完成。

解决:把--workers调低到 4,同时确认数据是否放在机械硬盘上。如果数据在机械硬盘,--cache ram的重要性比在 SSD 上更高。另外注意 Windows 系统上的一个特殊坑:DataLoader 的num_workers在 Windows 下设置成 0 才能跑,否则会报BrokenPipeError

5.5 可视化结果异常:detect 输出的框有大量重叠

现象:推理结果中同一朵花被多个框覆盖,框的置信度都很高。

原因:--iou-thres设置过高,NMS 无法有效合并重叠框。YOLOv5 在训练时默认用的是iou-thres=0.45,但推理时有人习惯调到 0.7,导致 NMS 判定“这两个框框的是不同目标”。

解决:恢复到 0.45 通常有效。但如果你检测的花卉目标尺寸分布特别不均匀——比如同时存在占据画面一半的大花和几个像素的小花——建议打开utils/general.py里的non_max_suppression函数,将agnostic=True这个参数加上,让 NMS 不再受类别限制地全局合并重叠框,对密集小目标场景有明显改善。

6. 部署优化:把训练好的权重导出并做 Shell 自动化推理

训练完成不等于项目交付。对花卉识别这个场景,最常见的落地方式是批量处理大量图片,或者在边缘设备上跑实时推理。这一章给出两个可直接套用的优化手段:ONNX 格式导出和 Shell 自动化推理。

YOLOv5 的export.py把 PyTorch 权重导出为 ONNX,核心诉求是摆脱 PyTorch 运行时依赖。部署到没有 GPU 的服务器时,ONNX 格式可以直接用 ONNX Runtime 加载,推理速度比原生的 PyTorch CPU 推理快一倍左右:

# 导出 ONNX 格式权重 python export.py --weights runs/train/flower_run/weights/best.pt \ --img 640 \ # 与训练一致 --batch 1 \ # 固定 batch=1,便于部署 --simplify \ # 简化计算图 --include onnx # 导出完成后会生成 best.onnx 文件

--simplify参数值得单独说明。它调用onnx-simplifier把计算图中冗余的节点合并掉,比如把连续的Conv + BatchNorm + ReLU三个节点融合成一个。这个操作对推理速度的提升非常可观,同时减小模型文件体积,属于必开选项。

ONNX 导出成功后,推理脚本可以彻底脱离 PyTorch:

# onnx_infer.py —— 用 ONNX Runtime 做推理的最小实现 import onnxruntime as ort import numpy as np import cv2 # 创建推理会话,可指定 CPU 或 CUDA 执行提供程序 session = ort.InferenceSession("best.onnx", providers=["CUDAExecutionProvider", "CPUExecutionProvider"]) # 预处理:从 OpenCV 格式转到模型输入格式 img = cv2.imread("test.jpg") img = cv2.resize(img, (640, 640)) img = img[:, :, ::-1].transpose(2, 0, 1) # BGR -> RGB, HWC -> CHW img = np.ascontiguousarray(img, dtype=np.float32) img /= 255.0 img = np.expand_dims(img, axis=0) # 增加 batch 维度 # 推理输出 shape: (1, 25200, 6),25200 是 640 输入下所有 anchor 的总数 outputs = session.run(None, {session.get_inputs()[0].name: img})[0]

这里有两点需要特别注意:第一,输入张量的维度排列是(batch, channel, height, width),和 OpenCV 默认的(height, width, channel)不同,转置是必须的;第二,25200 这个数字是 640×640 输入下三个特征层的 anchor 总数,如果训练时用的是其他输入尺寸,这个数字会变化。输出的每一行前半部分是框坐标,后半部分是每个类别的置信度,需要自己做 NMS 过滤。

批量图片推理是花卉识别的刚需场景,比如保险公司处理后端的农作物照片,或者农业研究机构处理无人机航拍图。纯手工对每张图片执行一次python detect.py太低效,这里用 Shell 脚本把这套流程自动化:

#!/bin/bash # 批量推理脚本:用 ONNX 模型处理整个目录的图片 # 定义输入输出目录,要求传入参数 INPUT_DIR=${1:?"用法: $0 <图片目录> <输出目录>"} OUTPUT_DIR=${2:?"用法: $0 <图片目录> <输出目录>"} # 输出目录不存在则创建 mkdir -p "$OUTPUT_DIR" # 遍历输入的常见图片格式 for img in "$INPUT_DIR"/*.jpg "$INPUT_DIR"/*.jpeg "$INPUT_DIR"/*.png; do # 检查文件是否存在,防止通配符匹配不到时报错 [ -f "$img" ] || continue # 提取不带扩展名的文件名 basename=$(basename "$img") name="${basename%.*}" # 调用 Python 推理脚本处理单张图片 python onnx_infer.py --input "$img" --output "$OUTPUT_DIR/${name}_result.jpg" echo "[INFO] 已处理: $basename" done echo "[DONE] 批量推理完成,结果保存在 $OUTPUT_DIR"

这个脚本的工程化细节在参数校验和文件存在性检查上。${1:?}语法在参数缺失时直接退出并输出错误信息,[ -f "$img" ] || continue避免通配符匹配到空路径时 Python 脚本报异常中断整个批处理。真正部署时,我会再加上find "$INPUT_DIR" -type f | parallel -j 4 python onnx_infer.py ...这类并行化手段,把四核 CPU 跑满,单张图片推理时间从 0.5 秒压缩到 0.15 秒左右。

回头说一个我用这套方案处理真实项目的教训:有一次给一个农业客户识别温室里的四种花卉,我把训练图片全换成了人工光照下拍摄的照片,结果到了自然光照环境里准确率掉了 12 个百分点。后来我强制在数据准备阶段加入 30% 的真实户外样本,并且把推理输入尺寸从 640 提高到 832,才把准确率拉回来。从那以后我做花卉识别项目,每次都强制走一遍“训练集场景多样性检查 + 推理尺寸对齐确认”这个流程,再也没有因为场景迁移吃过亏。希望这一套从环境搭建到部署优化的完整链条,能帮你在自己的花卉识别任务上少走几个来回。

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

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

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

立即咨询