简介:本资源是一套面向高校本科生毕业设计与农业智能化课程实践的Python无人机植保系统开发方案,聚焦作物病虫害图像识别与无人机精准施药两大核心功能,适用于具备基础Python编程与深度学习认知的学习者开展项目实战与二次开发。压缩包共32个文件,含15个核心Python源码(如main.py、classify.py、crossvit.py、engine.py等)、6个编译缓存文件、5个备份文件(.zbak)、3个说明类文本及1份PDF项目文档,完整覆盖模型训练、图像推理、无人机控制逻辑与系统集成全流程,总大小9.43MB。已有40人下载学习,适合用于毕业课题实现、课程设计答辩或科研原型验证。用户可直接运行主程序调用预训练模型完成病害分类,结合配套文档理解CrossViT混合架构设计思路、数据增强策略与施药路径规划逻辑,并基于清晰模块化目录(models/datasets/utils等)快速定位功能扩展点。 植保无人机这几年在农业圈里越来越普及,但绝大多数飞机干的还是“均匀喷洒”的活儿——不管地里有没有病虫害、病害轻重如何,全田一个流量喷过去。说实话,这既浪费药,又污染环境,还容易产生抗药性。我前后做了大半年这个“基于Python的无人机病虫害智能识别与精准施药系统”,核心目标就一个:让无人机自己看清哪里有病,然后只对有病的区域精准喷药。这篇文章是我整个开发过程的完整复盘,从数据采集、模型训练到机载部署、变量喷洒控制,再到源码结构和项目文档的整理规范,把能讲的细节全部摊开来讲,希望能给做农业AI、植保无人机开发的朋友省点弯路。
1. 为什么是Python:语言选型和系统边界
1.1 生态优势与适用边界
先聊一个最容易被问到的选型问题:无人机飞控底层基本都是C/C++写的,为什么上层识别和施药决策要用Python?其实我一开始也在纠结,但做完之后才发现,这个选择几乎没有悬念。
Python在这个项目里的核心优势有三个。第一个是CV和深度学习的生态实在太好了。目标检测这块,YOLO系列的官方实现、Ultralytics库、Detectron2、MMDetection,全部都是Python优先,包括数据预处理、模型训练、验证、导出,整个链路用Python写是最顺的。第二个是快速迭代。前期模型方案没定的时候,我经常一天换一个backbone跑实验,Python改起来快、试错成本低,要是全用C++,光是编译时间就够喝一壶了。第三个是地面站和后处理脚本的需求。处方图生成、数据可视化、数据库交互、Web服务,这些都是Python的强项,没必要用底层语言和自己过不去。
但必须说清楚边界:Python不是用来写飞控的。姿态解算、GPS融合、电机控制这些实时性要求极强(毫秒级)的模块,我全部沿用现有飞控方案,用的是PX4和ArduPilot这套开源体系。Python跑在上层的树莓派或Jetson上,通过MAVLink协议和飞控通信,负责视觉感知、决策计算和喷洒指令下发。简而言之:飞控管飞机稳不稳,Python管飞机去哪喷、喷多少。
1.2 系统整体架构
整个系统我拆成了四个部分:
- 采集层:无人机平台 + RGB可见光相机 + 多光谱相机(可选)+ 树莓派/Jetson机载电脑
- 识别层:Python推理服务,运行YOLOv8模型,实时检测农作物病虫害目标
- 决策层:根据识别结果生成农田病虫害热力图 -> 栅格处方图 -> 变量喷洒指令
- 执行层:飞控接收指令,控制喷洒泵流量和喷头开关,实现按需施药
再加上地面站电脑上的训练、标注、可视化模块,整体就是一套“端-边-云”简配版架构。我选的是端侧为主,也就是所有识别和决策都在机载电脑上完成,避免依赖4G/5G网络——大田作业信号差是常态,断网就罢工的系统没有任何实用价值。
注意:机载电脑选型很重要。树莓派4B只能跑轻量模型(YOLOv8n),且帧率在10FPS左右徘徊;Jetson Nano能跑到15-20FPS;Jetson Orin NX则可以比较从容地跑YOLOv8s并同时处理多光谱数据。如果预算允许,尽量别在机载算力上省钱,这会直接影响识别精度和响应速度。
2. 数据是项目的命根子:数据集构建与标注
2.1 无人机的采集参数设计
很多做图像识别的人习惯去网上找公开数据集,但农业病虫害识别这件事,公开数据集的泛化能力很差,因为不同地区、不同光照、不同品种下的病虫害表观差异太大了。我坚持用无人机实地采集的数据训练,效果比拿网上的水稻稻瘟病图片训练出来好非常多。
采集参数是这么定的:飞行高度3米,速度2m/s,航向重叠率80%,旁向重叠率70%,相机垂直向下(云台俯仰-90度)。为什么要定这个高度?因为经过实测,3米高度下单张图片覆盖约2.5m×2.5m地面范围,GSD(地面采样距离)约0.38cm/pixel,既能看清叶片上的病斑纹理,又不至于因为飞太低导致单架次覆盖面积太小、效率太低。如果你用的是12MP相机,可以参考这个公式来估算GSD:
GSD(cm/pixel) = (传感器宽度(mm) × 飞行高度(m) × 100) / (焦距(mm) × 图像宽度(pixel))我用的DJI P4 Multispectral,等效焦距5.74mm,传感器宽度6.3mm,图像宽度1600像素,代入公式就是:
GSD = (6.3 × 3 × 100) / (5.74 × 1600) = 0.206cm/pixel这个分辨率下,稻飞虱若虫、玉米叶斑病这类小目标都能看清。如果只拍大范围的枯死区域,可以把高度放到5-6米,但小病斑就会严重漏检,这个后面会展开说。
采集时间上,我踩过一个坑:不要在正午直射光下采集。强烈的顶光会在叶片上形成镜面反射,病害区域的颜色特征被“洗掉”一大截,模型学到的特征全是错的。最优窗口是上午9:00-11:00或下午15:00-17:00,光线柔和稳定。如果是阴天那更好,云层就是天然的柔光箱,全天可飞。
2.2 标注规范和工具链
数据标注用的是LabelImg和Roboflow两个工具。小批量自己标注用LabelImg,开源免费;大批量我传到Roboflow上标注,团队协作方便,还能顺带做自动增强。
标注规范上,我制定了三条硬性规则:
- 类别按“病种+严重度”划分,比如“稻瘟病-叶片”、“稻瘟病-穗颈”、“稻飞虱-聚集区”、“健康叶片”。不要把不同严重程度混在一个框里,否则模型会糊涂。
- 标注框要贴合目标边缘,不要把大片背景包进去。背景里有土壤、水、杂草,框大了模型会学到噪声。
- 小目标单独加强标注,无人机视角下很多病害区域在整张图里只占几十个像素,这种小目标如果不标注精确,模型很容易学成背景。
标注完成后,按YOLO格式导出,目录结构如下:
dataset/ ├── images/ │ ├── train/ (约2200张) │ ├── val/ (约300张) │ └── test/ (约200张) ├── labels/ │ ├── train/ (与images同名txt文件,每行: class x_center y_center width height) │ ├── val/ │ └── test/ └── data.yaml (类别定义)数据增强策略我做了三组对比实验,直接用mAP50做评判标准:只用翻转+旋转的增强,mAP50是68.7%;加上色彩抖动(HSV扰动)和随机仿射变换后,mAP50升到78.2%;再加马赛克增强,直冲到84.9%。但马赛克增强我建议在最后20个epoch自动关闭,否则会引入太多合成噪声,导致模型在小目标上过曝。
3. 识别模型训练与调优全过程
3.1 为什么不选更“轻”或更“老”的模型
我先后试过SSD、EfficientDet、YOLOv5和YOLOv8。SSD在无人机小目标上的表现很拉跨——底层特征图分辨率不够,病害区域在16×16的网格上可能就一个点;EfficientDet准确率不错,但推理速度很尴尬,在Jetson Nano上跑不动;YOLOv5和YOLOv8都是能用的,最终选YOLOv8是因为Ultralytics的生态更完善,导出TensorRT引擎、量化部署这些环节省事得多。
具体选哪个尺寸,取决于部署算力:
| 模型 | 参数量 | Jetson Nano推理耗时 | mAP50(我的数据集) | 适用场景 |
|---|---|---|---|---|
| YOLOv8n | 3.2M | 约55ms | 74.3% | 性能有限、追求实时 |
| YOLOv8s | 11.2M | 约130ms | 83.6% | 平衡之选 |
| YOLOv8m | 25.9M | 约260ms | 86.1% | 算力充足、离线分析 |
最终我选的是YOLOv8s,实测推理速度能支撑无人机在2m/s速度下逐帧分析不丢目标,准确率也能到83%以上,是性价比最高的档位。
3.2 训练细节和关键参数
训练前需要把数据集的data.yaml配好,我的是这样的:
path: /home/user/dataset train: images/train val: images/val test: images/test names: 0: rice_blast_leaf 1: rice_blast_panicle 2: brown_planthopper_colony 3: healthy_leaf然后直接用Ultralytics的CLI训练:
yolo detect train \ data=data.yaml \ model=yolov8s.pt \ epochs=200 \ imgsz=640 \ batch=16 \ lr0=0.01 \ optimizer=AdamW \ patience=30 \ augment=True几个参数我是刻意调的:
- imgsz=640:YOLOv8默认imgsz就是640,但我原本想用1280试试能不能提升小目标精度。实测mAP是高了1.8个点,但推理时间从130ms变成470ms,帧率直接掉到2FPS,无人机一动就全是动态模糊的漏检,根本没法用。最终退回640。
- optimizer=AdamW:比SGD收敛更快,前期验证阶段省时间。但如果你做最终精调,想榨干模型性能,建议换回SGD+cosine学习率调度。
- patience=30:30轮验证集指标不涨就早停。这个很关键,不然每轮都在烧时间。
- warmup_epochs=3:前3个epoch让学习率从0线性涨到0.01,避免模型一上来就震荡。
训练过程中我每10个epoch做一次验证——用测试集里无人机实地拍摄但绝不在训练集出现过的图片测,观察的是PR曲线(精确率-召回率曲线)和F1分数,而不是只盯mAP。mAP高不代表实际好用,它综合了所有置信度阈值的效果,但实际喷洒决策里,你只能选一个阈值。我更关注在Recall(召回率)不低于85%的条件下,Precision(精确率)还能不能保住80%以上。
3.3 模型调优:针对漏检的专项优化
第一版模型最大的问题不是总mAP低,而是小目标漏检严重。稻飞虱聚集区在500×500像素的检测框里往往只占30-50像素,模型直接给“忽略”了。
针对这个问题,我做了三件事:
- 增加小目标检测头:修改YOLOv8的模型结构,在P2层(160×160特征图)加了一个检测头。Ultralytics里可以通过
yolo detect train ... model=yolov8s-p2.yaml来加载P2版本模型。这个改动让小目标mAP50从58.1%升到64.7%,代价是推理时间增加约15%。 - 切图策略:在预处理阶段,把单张640×640的图切成4张320×320的子图分别推理,然后把检测结果映射回原图坐标。这个方案对小目标提升最明显(mAP50涨了6个点),但推理时间变成原来的4倍,所以只在近地面精细扫描模式使用。
- 难例挖掘:把验证集里所有漏检的图片收集起来,重新标注后mix进训练集,相当于给模型开小灶。这招实验了3轮,每轮提升约2个点,到后期比单纯堆数据更有效。
4. 从识别到行动:处方图与精准施药控制
4.1 处方图生成:从检测框到栅格地图
识别模型输出的是一堆检测框,但无人机不能对着几个框去喷药,需要把这些信息转换成处方图(Prescription Map)。处方图本质是一张栅格地图,每个格子记录一个施药量等级,通俗理解就是“地图上的每一个50cm×50cm小方格,对应一个喷多喷少的指令”。
生成流程分四步:
第一步:坐标转换。把检测框中心点的像素坐标,结合无人机GPS信息、IMU姿态角、云台角度和相机内参,通过地理配准把像素点投影到真实地理坐标。这一步我用的OpenCV的cv2.solvePnP做位姿估计,配合cv2.projectPoints做坐标映射。无风悬停状态下的投影误差能控制在0.5米内,大风天会到1-1.5米,这个精度对喷洒来说完全够用。
第二步:格网化。在无人机航线上按地面50cm×50cm间距生成栅格网。为什么是50cm?这不是拍脑袋定的,而是根据喷洒系统的喷幅决定的——单喷头有效喷幅是3米,但如果你用1米×1米的格子决策,一片刚出现病斑的区域可能被平均掉,喷药边界糊成一片。50cm的格子既能保证决策精度,又不至于让计算量爆炸(10公顷的田大概40万个格子,Python十秒内能算完)。
第三步:病情指数计算。对每个格子,统计该区域内检测出的病斑面积占比。让每个格子输出一个0-100的“病情指数”:
病情指数 = (格子内病斑面积总和 / 格子面积) × 100然后映射到喷洒量等级:
| 病情指数 | 喷洒等级 | 单位面积用药量(mL/ha) | 泵占空比PWM |
|---|---|---|---|
| 0-5 | 不喷 | 0 | 0% |
| 5-20 | 轻度 | 750 | 30% |
| 20-50 | 中度 | 1500 | 60% |
| 50以上 | 重度 | 2250 | 100% |
第四步:生成KML/GeoJSON处方图文件。我用pykml库把这些格子输出成KML格式,导入DJI地面站后会直接以图层形式叠加在实时地图上,飞手能直观看到哪里喷、哪里不喷。
4.2 变量喷洒控制:PWM脉宽调制
处方图必须转成飞控能听懂的语言才能执行。我的方案是:让机载电脑通过一个PWM占空比信号控制喷洒泵的电压输出,从而调节流量。直接用的是一个支持20kHz频率的舵机扩展板,Python通过pigpio库操作GPIO口输出PWM信号。
关键代码长这样:
import pigpio import time pi = pigpio.pi() PUMP_PIN = 18 PWM_FREQ = 20000 # 20kHz def set_spray_duty(level): # level: 0-100, 0为关闭,100为全开 duty_cycle = int((level / 100) * 255) pi.set_PWM_dutycycle(PUMP_PIN, duty_cycle) pi.set_PWM_frequency(PUMP_PIN, PWM_FREQ) # 根据处方图格子状态实时调节 for grid in prescription_map: current_level = grid.required_duty set_spray_duty(current_level) # 到达下一个格子需要的时间 time.sleep(grid.crossing_time)注意一点:PWM频率不能太低,电机泵的惯性比较大,20kHz低频下占空比变化会产生机械抖动,喷头雾化效果会变差。4-20kHz之间比较合适,太低有噪音,太高飞控供电容易出纹波。
这里还有个大坑:泵的流量和PWM占空比并不是线性关系。我测了同一个小型隔膜泵,5V供电下占空比20%时流量是0.15L/min,60%时是0.42L/min,但90%时才0.48L/min,曲线在60%以后就趋于饱和了。所以不要直接用线性映射,建议先测一次自己的泵,做一张PWM-流量标定表存在配置文件里,程序里用插值查表的方式换算。
4.3 航线规划:喷洒重叠率和转弯优化
精准施药除了喷得准,还得保证不重喷、不漏喷。重喷意味着药害,漏喷意味着防效崩盘。
航线规划这块我用的是pypolygon库做主航线生成。核心逻辑是:根据农田边界多边形和喷幅宽度,在边界内生成“牛耕式”平行航线,航线间距设为喷幅的0.9倍(这个系数能保证10%重叠,补偿风引起的漂移)。航线间距计算:
航线间距 = 喷幅宽度 × (1 - 重叠率) = 3m × (1 - 0.1) = 2.7m转弯识别是另一个细节。地里通常有电线杆、大树、田埂凸起,如果无人机以固定速度直线飞行,到田头转弯如果减速不及时,很容易撞障碍物或冲出边界。我加了一个简单的“预判-减速”逻辑:机载电脑读取当前航点与下一个航点距离,当距离小于5米时,通过MAVLink发送减速指令给飞控,让无人机把速度从2m/s降下来,转弯完成后恢复到巡航速度。
5. 机载部署、源码结构与项目文档
5.1 Jetson上的模型部署和推理加速
在Jetson设备上跑YOLOv8s,直接用PyTorch推理的话帧率大概只有7FPS,而实际飞行中要保持2m/s速度且不漏检,至少需要10FPS。所以必须做模型加速,我的方案是TensorRT INT8量化。
用Ultralytics导出TensorRT引擎很简单:
yolo export model=best.pt format=engine device=0 half=True但这里有两个坑。第一个是INT8量化会掉精度,我的模型从半精度FP16的83.6%掉到81.2%,如果任务不是特别吃算力,建议直接上FP16——推理速度比FP32快一倍,精度损失微乎其微。第二个是TensorRT引擎生成时device必须和推理时的device一致,不能在自己电脑的RTX显卡上生成引擎,然后复制到Jetson上跑,会直接报错“Misshapen weights”。要在Jetson本机上执行导出命令。
推理端的Python代码我开始用的是ultralytics包直接predict,但后来发现有个更舒服的姿势:导出成TensorRT引擎后,用tensorrt+pycuda自己做预处理和后处理。速度还能再快一截,并且可以定制输出后处理逻辑。
机载端完整调用链:
import cv2 import numpy as np import tensorrt as trt import pycuda.driver as cuda import pycuda.autoinit # 加载TensorRT引擎 logger = trt.Logger(trt.Logger.WARNING) runtime = trt.Runtime(logger) with open("best.engine", "rb") as f: engine = runtime.deserialize_cuda_engine(f.read()) context = engine.create_execution_context() # 预处理:resize到640x640,转RGB,归一化 def preprocess(frame): img = cv2.resize(frame, (640, 640)) img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img = img.astype(np.float32) / 255.0 # CHW格式 img = np.transpose(img, (2, 0, 1)) img = np.ascontiguousarray(img) return img # 推理 frame = capture_read() input_tensor = preprocess(frame) # 分配GPU显存并执行推理 # ... (省略显存分配细节) output = context.execute_v2(bindings=bindings)运行后整体能到16FPS,比PyTorch快一倍多,机上实时检测就没压力了。
5.2 源码目录设计
一个完整项目如果代码乱成一锅粥,后期维护就是噩梦。我的项目结构参考了几个开源项目的习惯,按模块分好:
drone_agri_system/ ├── config/ │ ├── camera_params.yaml # 相机内参、外参 │ ├── spray_params.yaml # PWM-流量标定表、喷洒等级配置 │ └── flight_params.yaml # 飞行高度、速度、重叠率 ├── data/ │ ├── raw/ # 原始无人机影像 │ ├── processed/ # 预处理后的裁剪图、增强图 │ ├── labels/ # 标注文件 │ └── augmented/ # 增强后图片 ├── models/ │ ├── weights/ │ │ └── best.engine # TensorRT加速引擎 │ └── model_arch.yaml # 模型结构备份 ├── scripts/ │ ├── train.py # 训练脚本 │ ├── infer.py # 推理脚本(调试用) │ ├── export_trt.py # 导出TensorRT引擎 │ └── georeference.py # 地理配准与坐标转换 ├── src/ │ ├── detection/ │ │ ├── detector.py # YOLOv8推理封装 │ │ └── postprocess.py # NMS、置信度过滤 │ ├── mapping/ │ │ ├── prescription.py # 处方图生成 │ │ └── kml_generator.py # KML导出 │ ├── control/ │ │ ├── spray_controller.py # PWM喷洒控制 │ │ └── mavlink_bridge.py # MAVLink通信 │ └── navigation/ │ └── path_planner.py # 航线规划 ├── tests/ │ ├── test_detector.py │ └── test_prescription.py ├── docs/ │ ├── 用户手册.md │ ├── 开发者文档.md │ └── 部署与标定指南.md ├── requirements.txt └── README.md这个结构有几个好处:配置和代码分离——调参时只改yaml文件,不用动代码;模块解耦——识别、处方图、喷洒控制各独立成模块,可以单独测试替换;文档和代码同仓——别人拿到源码就能上手,不用四处问人。
5.3 文档配套:让项目能真正被别人复现
源码很重要,但文档才是决定项目能不能被他人复现的灵魂。我在README里详细写了三个部分:
第一部分是环境配置,包括Jetson上的JetPack版本(我用的是5.1.2)、CUDA版本(11.4)、TensorRT版本(8.5.2)、以及Python虚拟环境怎么建:
python3 -m venv venv_agri source venv_agri/bin/activate pip install -r requirements.txt第二部分是数据流说明,从原始无人机影像到最终处方图的每一步处理逻辑,配了流程图和文件格式说明。第三部分是故障排查表,把无人机失联、GPS信号差、GPU显存溢出、PWM信号异常等常见问题的排查步骤都列清楚了。
文档这件事,我的心得是:别追求文档的规模,追求文档的准确。一份能让一个从没接触过你的人,按着文档从环境搭建到跑通全流程,这个文档才算合格。我写文档花了两周,但后来自我复盘时,好几次都是靠文档里的命令和配置把环境重建了一遍,省了大量时间。
6. 常见问题与排查技巧实录
6.1 识别相关的问题
Q1:模型在白天识别效果好,傍晚或阴天误检率猛增。
这是光照泛化问题。根本原因是训练数据集里大部分是晴天的图片。解决办法是:在采集阶段就刻意在一天的不同时间段、不同天气条件下都飞,让训练集覆盖更丰富的光照条件;另外一个取巧的办法是训练前把图像增强里的亮度增强、对比度增强开到最大(hsv_h=0.015, hsv_s=0.7, hsv_v=0.4),让模型更鲁棒。
Q2:大田作业时出现大量把枯草、土壤误检为病斑的情况。
排查下来是训练数据里背景太单一——我只标了农田里的画面,标注框周围全是绿色植株。模型学到的是“绿色背景下形状像病斑的块状物”,当背景变成黄褐色枯草时,判断就乱了。解决方法是:收集负样本,把明显健康的田块、杂草多的田块、枯死区域全部单独采集标注成“背景”类,重新训练后误检率下降了一半。
Q3:识别到了病斑,但喷洒边界和实际病区对不上,偏了1-2米。
这是坐标配准问题。优先检查无人机RTK是否开启。我一开始用的是普通GPS,定位精度只有±1.5米,所以病区边缘错位1米以上是常态。换RTK后定位精度到±0.02米,边界对得很整齐。没有RTK条件的话,可以在每次起飞前让无人机飞过几个已知GPS坐标的靶标点,后处理时做一次仿射变换校正。
6.2 喷洒执行相关的问题
Q1:喷头雾化效果差,药液大部分滴落到叶片上,叶背完全没有覆盖。
这通常是压力问题,不是流量问题。PWM只控制泵的转速,如果转速太低,药液压力不够,喷出来的不是雾而是水滴,无法穿透到叶背。我试过的补救方案:把喷洒等级的最小PWM从30%调高到45%,保证基础压力足够;另外喷头换成防滴漏的陶瓷喷嘴,小压力下雾化效果更好。
Q2:转弯时喷头还在喷,导致地头重喷,作物出现灼伤。
解决思路是惯性导航预判:机载电脑根据航线数据判断无人机已经进入转弯段时,提前2秒发送关闭喷洒指令。具体实现是订阅飞控的导航状态,当状态从AUTO_MODE.NAV_WAYPOINT切换为NAV_SPEED_CHANGE或转弯动作时,立即停泵。这个逻辑写在mavlink_bridge.py里,实测能将重喷区域面积减少90%。
Q3:药箱快空时,流量和设定值偏差越来越大,导致实际施药量不足。
液位下降后泵的吸入压力减小,同一个PWM占空比下流量会下降。我加了一个“剩余药量估算模块”——根据每次喷洒的电量消耗和时间预估剩余药量,当剩余量低于20%时调高PWM占空比补偿,低于10%时发出返航警报。
6.3 系统与部署问题
Q1:Jetson设备在高温环境下频繁降频,推理速度从16FPS掉到8FPS。
田间作业的机载电脑经常被太阳暴晒,散热风扇如果被粉尘堵住,温控降频跑不掉。我的处理方案:一是优化风扇策略,用Python读取温度传感器,温度高于60度时强制风扇全速;二是尽量把Jetson装在有遮阳的封闭机箱里,并加散热鳍片;三是把检测任务的推理分辨率从640降到512作为紧急降级方案。
Q2:TensorRT引擎在Jetson上加载报错了,提示“engine file is generated on a different device”。
这是典型错误。解决方案就是在Jetson本机重新执行导出命令,不要在开发机上导出engine再拷贝。如果你没有Jetson的显示环境,用SSH执行导出命令就可以,但要确保Jetson里已安装与部署环境完全一致的CUDA、TensorRT版本,否则还是会报错。
7. 这个项目后续还能怎么扩展
做完这套系统后,我自己后续有四个扩展方向,这里一并分享出来供参考。
第一个方向是多光谱融合。当前用的RGB相机只能识别叶片的可见光表观症状,而很多病害在可见光出现症状之前,近红外波段的反射率就已经有明显变化了。多光谱相机(或者直接用DJI P4 Multispectral)可以同时采集绿、红、红边、近红外四个波段,计算NDVI(归一化植被指数),提前3-5天发现病害区域,做到“治未病”。NDVI计算很简单:
ndvi = (nir - red) / (nir + red)但要把多光谱影像和RGB识别结果对齐,仍然需要做影像配准——我当时就因为两者分辨率不同而头疼过一阵子。
第二个方向是做时序变化检测。目前是单次飞行生成单次处方图,但病虫害是动态发展的。如果你同一块田每周飞一次,把多次的处方图叠加做时间序列分析,就能看出病害传播方向、衰退速度,还能评估上一次施药的实际效果。这部分我用的是简单的差值分析,效果比单期图好很多。
第三个方向是接入物联网气象站数据。施药效果受风速、温度、湿度影响很大。如果处方图生成时就把气象数据融合进去,比如风速超过3m/s时自动扩大喷洒边界、降低飞行速度、加大PWM占空比,可以让喷洒更精准。
第四个方向是地面变量喷杆联动。无人机喷幅有限、载药量小,大田作业效率始终不如地面机械。我的规划是:把处方图直接输出成变量喷洒机的控制文件,地面的自走式喷杆喷雾机按处方图作业。无人机负责“侦察”,地面机械负责“打击”,两者协同才是农业精准施药的终极形态。
就我个人实际操作下来的感觉,这个项目最大的难点根本不在模型训练上,而在数据质量和工程稳定性。模型你花两周就能训一个效果还不错的,但把模型从实验室搬到田间地头,让它在大太阳、大风、信号差、灰尘大的环境里稳定跑上几个小时,这才是真正考验人的地方。我做这套系统的过程中,至少一半的坑都是在“看起来应该很简单”的环节踩到的——坐标偏移、泵流量非线性、转弯重喷、高温降频,一个个都是工程问题。
所以我最后想给的建议是:如果你想做类似的系统,千万别只盯着模型指标刷分,一定要花时间在数据采集规范、硬件散热、通讯稳定性、异常处理这些“不起眼”的工程细节上。这些细节决定的是你的系统在实验室里能跑通,还是在地里能真正干活。
本文还有配套的精品资源,点击获取