
简介面向智慧农业方向毕设与病害识别入门者这是一份基于Python与OpenCV的苹果叶病害检测系统完整工程包覆盖赤霉病、枯叶病与铁锈病三类常见病害的识别检测。项目采用YOLO系列检测方案可直接读取图片或视频输出检测结果也可替换数据集训练其他作物病害适合本科毕设、课程设计或农业信息化项目二次开发。压缩包共382个文件约54.26MB包含Python源码、标注数据集图片与txt标签、yaml配置、训练好的pt权重模型、Dockerfile及启动脚本等目录结构完整。内容预览可见训练/验证批次图与测试预测图便于快速核对效果。已有508人访问学习适合具备Python基础、希望快速搭建完整识别流程的开发者参考使用。1. 苹果叶病害识别系统这套毕设源码能识别什么、凭什么识别毕设季最常见的场景就是拿到一个“基于 pythonopencv 的苹果叶病害识别检测系统”源码包里面装着标注好的病害数据集、训练好的模型和操作说明。它的核心价值是把一张叶片照片自动归类为健康的还是得了病如果得了病进一步分出是黑星病、黑腐病还是锈病——这类靠肉眼经验才能判断的事模型能在几秒内出结果。我拿到这种项目包的第一步从来不是解压就运行而是先搞清三件事数据集用什么结构标注的、模型用什么框架保存的、预测脚本从哪里读图。要拿这个方向做课设或毕设的本科生以及想找一条完整图像分类链路练手的开发者都可以往下看。2. OpenCV 在苹果叶病害识别里的真实分工从读图到颜色空间转换的关键环节系统名字里写着 Python 和 OpenCV但真正判断“这是什么病”的不是 OpenCV而是训练好的分类模型。OpenCV 的位置在模型前后前面负责把一张随手拍的叶片照片变成模型能吃的标准输入后面负责把模型输出的数字翻译成看得懂的框、标签和病斑区域。把这条链路的边界划清楚你才知道调参的时候该动谁。2.1 一条完整的“叶片图像 → 病害类别”流水线是怎么训练出来的常见做法是搭建一条图像分类流水线读图 → 预处理 → 模型推理 → 后处理。数据预处理环节几乎全部由 OpenCV 完成。以下是一个典型的预处理函数几乎每个识别项目里都有类似的一段import cv2 import numpy as np def preprocess_leaf(image_path, target_size(224, 224)): # 1. 读图OpenCV 默认返回 BGR 顺序很多模型是按 RGB 训练的顺序错了颜色特征完全错位 image cv2.imread(image_path) if image is None: raise ValueError(f无法读取图片: {image_path}检查路径是否含中文或文件损坏) # 2. 颜色空间转换BGR - RGB这一步被漏掉是新手最常见的翻车点 image cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # 3. 统一缩放模型输入层尺寸固定不匹配时前向传播直接报 shape 错误 image cv2.resize(image, target_size, interpolationcv2.INTER_AREA) # 4. 归一化把 0~255 的像素值压到 0~1避免大数值把模型激活函数推到饱和区 image image.astype(np.float32) / 255.0 # 5. 增加 batch 维模型推理接口要求输入至少是四维 (batch, h, w, c) return np.expand_dims(image, axis0)这段代码逻辑上分成三层前面是物理图像的读取和色彩校正中间是几何和亮度归一化最后是数据结构对齐。第 3 步的 INTER_AREA 是 cv2.resize 里适合缩小图像的插值方式比默认的双线性在叶片纹理上保留更多边缘信息如果你要把小图放大反而应该用 INTER_CUBIC。第 4 步有没有做直接影响迁移学习效果——预训练模型大多是在归一化后的输入上训练的直接喂 0~255 的原始像素第一层卷积的响应会全部偏大训练起来收敛慢甚至 logits 溢出。第 5 步是给 model.predict() 用的。Keras、PyTorch 甚至是 OpenCV 自带的 dnn 模块推理接口都要求一个 batch 维单张图也要扩成四维。记住这个函数后面你拿到的所有源码包都能套用。2.2 为什么预处理首选 HSV 颜色空间病斑分割的阈值经验叶片病害里黑星病初期是橄榄绿色斑点黑腐病是黑褐色腐烂斑锈病是橙黄色粉状孢子堆——这些差异在 RGB 空间里容易被光照和反光干扰转到 HSV 之后色调H分量对不同颜色病斑的区分干净得多。这就是几乎所有这类源码都会加一段 HSV 处理的原因。# 转到 HSV 颜色空间 hsv cv2.cvtColor(leaf_bgr, cv2.COLOR_BGR2HSV) # 病斑区域阈值黄褐色到深褐色H 在 10~35S 和 V 取中间偏上 lower_brown np.array([10, 40, 40]) upper_brown np.array([35, 255, 255]) disease_mask cv2.inRange(hsv, lower_brown, upper_brown) # 形态学闭运算填补病斑内部的小空洞让区域连续 kernel cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)) disease_mask cv2.morphologyEx(disease_mask, cv2.MORPH_CLOSE, kernel)这段代码的核心是 inRange 的两个阈值数组。lower_brown 的 H10 近似黄褐色起点H35 覆盖到深褐S 和 V 设置 40 起步是为了把浅色背景和亮度太低的阴影排除出去。这组数是经验值不是金科玉律——不同相机、不同光照拍出来的病斑色调范围会整体平移。你拿到数据集后应该先抽十张病斑明显的图用 Matplotlib 拖一个 HSV 滑块观察病斑落在哪个区间再回来改阈值别直接拿默认值跑。有了 mask 之后还能算病斑面积占比。统计 disease_mask 中非零像素数除以整片叶子的像素数这个比值可以直接作为病害严重程度的量化特征输出到答辩用的报告里。很多系统只做“有没有病”的分类加上这个面积比值就把系统从“识别”提升到了“评估”的层次这是后面第六章要展开讲的方向。2.3 标注数据集在源码里怎么组织目录结构、划分比例和标注格式“带标注好的病害数据集”是这类源码包里最值钱的部分。常见做法是按类别分文件夹因为 torchvision 的 ImageFolder 和 Keras 的 flow_from_directory 都直接吃这种结构源码里不需要写多余的解析逻辑。如果你之前跑过 YOLOv8 训练自己的数据集对这种目录组织一定不陌生。典型目录长这样dataset/ ├── train/ │ ├── apple_scab/ # 苹果黑星病 │ ├── black_rot/ # 黑腐病 │ ├── cedar_rust/ # 雪松苹果锈病 │ └── healthy/ # 健康叶片 ├── val/ └── test/目录名就是类别名也是模型输出层的类别顺序。这里有一个坑Keras 的 flow_from_directory 按字典序排序类别而 PyTorch 的 ImageFolder 按文件夹遍历顺序两者不一定一致。也就是说同一批数据在 TensorFlow 里训出来的类别编号和 PyTorch 里训出来的可能对不上。如果源码包的模型是用 TensorFlow 保存的预测脚本里又用了 PyTorch 风格的顺序那 100% 会出现“把黑星病识别成健康”的错位。标注方式上纯分类项目通常不需要画框目录本身即标注如果要搞“检测”数据里才会出现 PASCAL VOC 的 xml 或者 COCO 的 json。标题写的是“识别检测系统”如果源码包里有 xml/json说明除了分类还有一个目标检测分支脚本结构会比纯分类复杂不少。你拿到包后第一件事就是确认这一点打开操作说明看它说的“识别”是只输出类别还是要把病斑位置框出来。两者对应的模型文件格式通常是不同的——纯分类是 h5/pth 这样的全图分类权重检测则可能是 YOLO 权重或 Faster RCNN 系列。数据划分比例上毕设项目里 7:1.5:1.5 和 8:1:1 都常见。样本量不大的时候我一般倾向 8:1:1因为验证集和测试集各占 10% 足够评估再留更多就是浪费训练数据。你需要做的第一件事是数每个类别的图片张数。如果某一类只有几十张而其他类有几百张那训练时一定要开类别权重否则模型很快会退化成“全判健康”的懒惰分类器——这会在第五章的避坑里再细说。3. 把源码包跑通python 环境、opencv 依赖和最小预测命令很多毕设源码包做出来是在作者自己电脑上跑的换台机器跑不通十有八九是环境问题。操作说明里通常会给一页环境配置但最常见的失败不在包名而在版本。这一章用最小步骤带你把环境搭起来、目录认清、预测跑通。3.1 环境版本怎么搭python 3.83.10 配 opencv-python 的常见组合装 Python 就一条原则从官网下载安装包别用乱七八糟的一键安装渠道。我一般建议先装 Python再建虚拟环境最后用 pip 安装依赖。Python 版本不要追新opencv-python 对 Python 3.11 之后的版本支持会滞后尤其某些带 dnn 或 contrib 特性的旧版本轮子不一定有匹配包。最不容易出问题的组合是 Python 3.9 或 3.10配 opencv-python 4.6 到 4.8 这样的大版本。下面是一组典型命令# 进入解压后的项目根目录 cd apple_leaf_disease # 创建虚拟环境命令在 Windows/macOS/Linux 通用 python -m venv venv # 激活虚拟环境Windows 用 venv\Scripts\activate source venv/bin/activate # 优先按项目自带的 requirements 安装装不上再单独处理单个包 pip install -r requirements.txt建虚拟环境而不是直接 pip install 到全局是因为装错版本有后悔药——环境删掉重来不会污染全局。requirements.txt 里一般会有 opencv-python、numpy、pillow、scikit-learn、matplotlib以及模型框架对应的包tensorflow 或 torch 二选一。如果 pip 在某个包上报错把那一行版本号去掉重装即可不必整个环境推倒重来。另外你很可能遇到两个选择opencv-python 和 opencv-contrib-python。毕设这个体量基本不需要 contrib装最普通的 opencv-python 就够contrib 里那些 SIFT、ORB 特征点在叶片病害场景下作用有限别为了一个炫酷功能给自己增加维护成本。验证环境是否装对用一条命令python -c import cv2; print(cv2.__version__); import numpy; print(numpy.__version__)如果输出两个版本号说明 cv2 和 numpy 都就绪如果 import cv2 直接抛 ModuleNotFoundError那 95% 是没有装 opencv-python先执行 pip install opencv-python 再验证。注意如果操作说明里明确写了 Python 版本要求以说明为准不用强行降级折腾。3.2 解压后先看目录源码、数据集、模型和说明文档的分工解压一个毕设源码 zip我最怕的就是直接双击 train.py。正确顺序是先把目录结构过一遍。通常这类包会包含这些部分文件/目录作用运行时机train.py训练脚本读数据集产出模型权重你想重新训练时predict.py单图推理脚本日常识别gui.py图形界面入口展示用models/*.h5/pth/onnx预训练好的模型文件predict 时加载dataset/标注好的病害图片训练和测试requirements.txt依赖清单装环境操作说明/README作者写的运行手册先读这个这里有个判断技巧先看操作说明里“模型文件”那一节确认权重格式。Keras 老格式是单个 .h5新版是 .kerasPyTorch 是 .pth 或 .ptONNX 是 .onnx。格式不同对应的加载代码完全不同。如果操作说明没写清楚你可以在源码里搜“load_model”或“torch.load”看看它加载了什么后缀的文件就能反推出模型类型。千万别根据文件夹名字猜模型加载部分最容易被改名误导。模型加载的语句通常长这样model tf.keras.models.load_model(models/leaf_model.h5)或者 model torch.load(models/leaf_model.pth, map_locationcpu)。你要是看到 torch.load注意它默认会加载到 GPU 上没 GPU 的电脑必须加 map_locationcpu否则会报显存相关错误。3.3 用最小命令跑一次预测从 venv 到输出结果图环境就绪、模型文件确认存在之后最小操作就是跑一次推理。源码包如果带 GUI我建议先不要开 GUI而是找 predict.py 这种命令行脚本它能更快暴露问题。运行方式一般是# --image 后跟一张测试图片具体参数名以源码 argparse 里为准 python predict.py --image dataset/test/black_rot/sample_01.jpg # 常见输出类别名 置信度并保存一张带标注的结果图predict.py 的 argparse 里通常有 --image、--weights、--save_dir 三个参数。--weights 没指定时会拿默认路径的模型文件--save_dir 控制结果图输出到哪个目录避免覆盖原图。如果脚本成功你会看到类似 predicted class: black_rot (0.956) 的输出并在指定输出目录下看到一张画了框或标了标签的图。如果报错优先看错误栈最下面三行——绝大多数情况下要么是路径不存在要么是模型文件加载失败要么是输入尺寸不对。跑通预测这个动作本身不需要 GPUCPU 就够因为推理单张图只是若干次矩阵乘法。真正吃资源的是训练如果你打算重新训练下面一章的参数话题就绕不过去了。4. 参数调优让识别精度从“能跑”到“能答辩”答辩时老师最爱问的不是“你怎么跑通的”而是“这两个参数为什么这么设改了会怎样”。所以调参不只是为了提高精度更是为了给自己留出可以说出道理的空间。这一章只讲最容易见效的几组参数。4.1 OpenCV 预处理参数resize 尺寸、滤波核与阈值的经验取值resize 尺寸必须等于模型输入这是硬约束。常见 CNN 输入是 224x224ResNet、VGG或 256x256部分 Inception你只要在加载模型后打印一下模型的 input shape 就能确认。插值方式也会轻微影响边缘锐度下采样用 INTER_AREA上采样用 INTER_CUBIC这是一条不容易出错的经验。# 打印模型输入尺寸决定 resize 的目标值 import cv2 from model_utils import load_model model load_model(models/leaf_model.h5) # Keras 模型可以这样看输入 print(model.input_shape)滤波核方面GaussianBlur 的核大小写成 (3,3) 就够别迷信更大。核从 3 加到 5噪声确实多滤掉一点但病斑边缘也会被提前抹平如果病斑本身就是小斑点核越大越分不清。阈值方面HSV 分割的阈值前面已经给了一组起点这里补充一个验证技巧把每张训练图的病斑区域像素值打印成直方图看 H 分量的波峰位置再反向修正阈值数组。如果 H 分量波峰在 20 附近那 [10,35] 是合理的在 45 附近就要把 upper 改成 55。还有两个容易被忽略但很影响结果的小参数cv2.adaptiveThreshold 的 blockSize 和 C 值它们用于把叶片从背景分离。blockSize 必须是奇数一般取 11 或 15C 是偏置项取值 2 到 10越大越保守。如果你发现叶片边缘被裁掉就把 C 调大一点。# 光照不均时Otsu 自动阈值未必好使不如手动 HSV inRange _, binary cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV cv2.THRESH_OTSU)Otsu 自动阈值更适合整张图光照一致的情况光照不均的叶片图还是手动调 HSV 的 inRange 更靠得住。OpenCV 预处理看起来琐碎但这些参数直接决定模型输入质量远比后期调学习率更直观。4.2 模型训练超参学习率、batch size 和 epoch 的起点方案如果你打算重新训练模型而不是直接用作者给的权重超参数建议从保守组合开始Adam 优化器初始学习率 1e-3batch size 16 或 32训练 30 到 50 个 epoch配合早停。数据量不大时学习率 1e-3 是安全的起点如果损失在第一个 epoch 就发散到 nan把学习率降到 1e-4。# 以 Keras 为例的一组可起步的编译与训练配置 model.compile( optimizeradam, losscategorical_crossentropy, metrics[accuracy] ) history model.fit( train_generator, validation_dataval_generator, epochs50, batch_size16, callbacks[ tf.keras.callbacks.EarlyStopping( monitorval_loss, patience5, restore_best_weightsTrue ) ] )batch size 的选取原则是能放进显存或内存的前提下取大一点但毕设数据集通常只有几千张16 或 32 的差异不大反而是数据增强的影响更明显。后面如果验证集准确率上不去先别急着调学习率回来检查是不是类别不均衡以及增强有没有过度扭曲叶片纹理。patience5 的意思是连续 5 个 epoch 验证损失不降就停并且恢复最优权重这个回滚机制就是后悔药。迁移学习在这个方向几乎是必选动作拿 ImageNet 预训练的权重初始化模型冻结前几层只训练最后几层全连接学习率降到 1e-4通常几十个 epoch 就能收敛到 90% 以上。完全从零训练一个小型 CNN 不是不行但需要的数据量和调参时间至少要翻两倍答辩时老师也很容易用“为什么不用迁移学习”把你问住。4.3 用混淆矩阵和准确率判断模型有没有真的学会准确率是最容易骗人的指标。当四类数据比例是 8:1:1:1模型全判第一类也有 80% 的准确率看起来很高实际是废物。所以评估阶段必须做两件事输出混淆矩阵并单独看每一类的召回率。# 用 sklearn 直接生成混淆矩阵和每一类的分类报告 from sklearn.metrics import confusion_matrix, classification_report # y_true 是真实标签下标列表y_pred 是模型 argmax 后的预测下标列表 cm confusion_matrix(y_true, y_pred) print(cm) report classification_report( y_true, y_pred, target_names[apple_scab, black_rot, cedar_rust, healthy], digits3 ) print(report)读混淆矩阵时盯两个位置主对角线是否明显高于其他格子以及哪两类最容易互相混。苹果叶病害里黑星病初期和健康叶最容易混因为病斑还没变褐锈病和黑腐病颜色接近也容易混。如果这两类互相错判说明模型学到的主要是颜色特征缺少纹理特征下一步该在预处理时强化边缘信息比如加一个 Sobel 梯度通道。如果某类召回率明显偏低基本可以断定训练数据里它的样本最少或最难分。解决方法是给这类加权重或者在数据增强时对它做更多样的扰动。这是评估环节给你指出的改进方向比无脑调参有依据得多。把这些指标截图放进答辩 PPT比贴十张运行截图都管用。5. 避坑指南数据集、模型文件和 opencv 依赖的 4 个典型翻车现场前面几章提供的是正常路径但这套源码包真正耗时间的环节往往是异常路径。下面四条是这类项目里出现频率最高的现场每条我都按“现象 → 原因 → 解决”写清楚也算是我带毕设这几年攒下的血泪经验浓缩。5.1 import cv2 直接报 ModuleNotFoundError环境没对现象启动预测脚本第一行就红字ModuleNotFoundError: No module named cv2。原因绝大多数情况是虚拟环境没有激活就执行了 pip install包装进了全局或者 requirements.txt 里写的是 opencv 而不是 opencv-python系统装的是别的名字。还有一个隐蔽原因是 Python 版本太新opencv-python 还没发布对应 wheelpip 会尝试从源码编译然后失败。解决先激活虚拟环境再执行 pip install opencv-python。装完后输入 python -c import cv2; print(cv2.version)能打印出 4.x 就没问题。如果仍然装不上把 Python 降级到 3.9 或 3.10别折腾源码编译——顺便说一句别闲着去走 opencv 的 cmake 编译步骤除非你的代码真的用了 contrib 模块否则编译一次两小时对毕设没有任何好处。5.2 预测结果一直指向同一个类别索引映射与类别不平衡问题现象不论输入哪张图输出总是“healthy”或固定另一个类且置信度接近 1。原因两个方向要分开看。一是类别索引映射错位训练时用 ImageFolder 按目录字母序生成 class_idx预测脚本里却用了一个手写的列表顺序对不上于是模型其实分对了但脚本把下标翻译错了。二是数据极端不均衡训练集里 healthy 占了 85%模型学到的捷径就是“不管什么都猜 healthy”因为它能最小化整体 loss。解决先在源码里打印模型输出的类别索引字典再和 data/train 下的目录顺序逐一比对修正 label_map。然后做一次类别数量统计如果最大类是最小类的十倍以上训练时加 class_weight或者在采样时对小类做重复采样。改完这两个地方预测结果一般会恢复。5.3 cv2.imread 读不了中文路径图片预处理脚本里加一行解码现象脚本跑起来不报错但 cv2.imread 返回 None程序在下一步 cvtColor 时崩掉或者数据集放在 Windows 桌面上路径里带“毕设”两个字就出现大量警告。原因OpenCV 的 imread 在 Windows 上对非 ASCII 路径的处理一直有问题。它在底层调的是 C 风格文件接口传中文字符串容易失败。macOS 和 Linux 上少见但国内毕设数据集几乎都放在中文目录下所以这个坑命中率极高。解决不用 imread改用 np.fromfile 配合 imdecode这是公认的兼容方案直接替换读取函数即可import cv2 import numpy as np def imread_unicode(path): # np.fromfile 以二进制把文件读成数组绕开 imread 的路径解析问题 data np.fromfile(path, dtypenp.uint8) return cv2.imdecode(data, cv2.IMREAD_COLOR)然后把这个函数统一替换源码里所有 cv2.imread 调用。同时在项目根目录跑一个批量改名脚本把数据集路径改成英文双保险。还有一点路径里的空格也会让部分解析逻辑出问题英文路径加下划线最省心。提示替换 imread 后记得把脚本里所有依赖 cv2.imread 返回非 None 的判断同步更新否则返回值从 None 变成 ndarray类型判断逻辑会失效。5.4 训练到一半卡死或者直接被系统杀掉batch size 和损坏图片在捣乱现象训练在第一个 epoch 之后进程消失没有任何错误堆栈或者 Jupyter 内核直接重启推理时偶尔也会卡住不动。原因要么是 batch size 设得太大内存或显存被吃满要么是数据加载方式在频繁读磁盘小文件IO 成为瓶颈还有一种常被忽略的情况是数据集中混进了损坏图片或零字节文件在数据加载的 decode 环节抛了异常但被生成器吞掉线程就卡死在原地。解决先把 batch size 降到 8 或 16 验证训练能推进再用 opencv 批量检查一遍所有图片能否被正常解码import cv2 import os bad_files [] for root, _, files in os.walk(dataset): for name in files: if not name.lower().endswith((.jpg, .jpeg, .png)): continue path os.path.join(root, name) # 只做解码检查不关心图片内容 img cv2.imread(path) if img is None: bad_files.append(path) print(f损坏或不可读文件数: {len(bad_files)}) for f in bad_files[:10]: print(f)这段批量检查代码走一遍全量数据集把读不出来的图列出来然后手动删掉或重新导出。数据加载侧优先考虑把所有图片在训练前预缩放到模型输入尺寸并打包成 .npy 或 TFRecord训练时就是纯内存读取速度会快好几倍也避免边训练边读图时 IO 波动。6. 给毕设加分用 ROI 提取和可视化报告让识别系统更完整6.1 用 OpenCV 轮廓检测自动裁出叶片区域如果你的源码包里的识别脚本是整张图直接送进模型那当背景里有土、草、手指的时候模型很容易被环境干扰。一个成本不高的改进是在预处理时先用 HSV 绿色掩膜找出叶片主体再裁出 ROI 后送模型。这段逻辑用 OpenCV 写不超过 15 行# 分离绿色叶片与背景再裁出主体区域 hsv cv2.cvtColor(image_bgr, cv2.COLOR_BGR2HSV) # 绿色范围叶片偏黄绿时可把 H 上限放宽到 80 mask cv2.inRange(hsv, np.array([35, 30, 30]), np.array([85, 255, 255])) mask cv2.morphologyEx(mask, cv2.MORPH_CLOSE, np.ones((7, 7), np.uint8)) contours, _ cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) if contours: x, y, w, h cv2.boundingRect(max(contours, keycv2.contourArea)) leaf_crop image_bgr[y:yh, x:xw]这段的核心是 RETR_EXTERNAL 只取最外层轮廓避免叶子边缘锯齿或虫洞被当作多个轮廓boundingRect 取最小外接矩形。裁出来的区域再送进前面 2.1 的预处理函数背景干扰被压到最低。6.2 输出带病斑标记和面积统计的识别报告把识别结果从“一行文字”变成“一张带框的图 面积占比”放进论文和 PPT 里说服力完全不同。下面这段把病斑 mask 的像素比例和类别标签一起写到结果图上# 在裁好的叶片 ROI 上画出病斑轮廓并标注类别与面积占比 scale disease_mask.shape[0] * disease_mask.shape[1] ratio cv2.countNonZero(disease_mask) / scale # 找病斑轮廓并画框颜色用红色线宽 2 contours, _ cv2.findContours( disease_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE ) for c in contours: x, y, w, h cv2.boundingRect(c) if w * h 50: # 过滤太小的噪点区域 continue cv2.rectangle(leaf_crop, (x, y), (x w, y h), (0, 0, 255), 2) label_text f{class_name} | 病斑面积占比: {ratio * 100:.1f}% cv2.putText(leaf_crop, label_text, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2) cv2.imwrite(output/result.jpg, leaf_crop)这组代码里 w*h50 是去掉单个像素噪点的经验阈值具体数值可随图像分辨率调整。病斑面积占比是个连续量它让分类模型输出的“患病”直接升级成“病情程度”老师看到这个答办难度会低很多。我现在拿到任何图像分类的源码包第一件事就是在模型加载和预测之间把类别映射表打印出来逐行核对一遍。这个习惯帮我避开了至少两次答辩现场的翻车。这套流程从环境到参数再到这里每一步都是有据可查的如果你照着重跑一遍遇到最多的其实不是模型问题而是路径和依赖问题。希望帮到你。本文还有配套的精品资源点击获取
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。