前言
往期专栏我们完成了水体、植被、建筑、城镇、灾害 五大遥感核心场景的全链路AI实战,覆盖生态、国土、应急三大主流应用领域。本期正式落地民生刚需、国家重点监管的农业遥感赛道。
耕地是粮食安全的核心载体,耕地保有量、地块完整性、作物种植结构、复种指数,是自然资源普查、农业农村监测、国土空间管控的核心考核指标。随着全国耕地非农化、非粮化严格管控,高精度、自动化、批量式耕地与作物遥感解译成为行业刚需技术。
传统农业遥感手段存在明显技术瓶颈:传统NDVI阈值、面向对象分割极易混淆耕地裸地、季节性荒地、休耕地块;零散细碎耕地边界模糊、地块粘连严重;不同农作物光谱相似度高,人工规则分类精度极低,完全无法满足精细化农业监测需求。
针对农业场景复杂痛点,本期专栏推出农业遥感专属AI方案 :采用地块分割+作物分类双分支网络 ,结合植被时序特征、纹理特征、光谱特征,实现耕地精准提取、非农干扰自动剔除、多作物类型智能分类、全域批量制图全流程自动化作业。
整套方案适配全国不同地貌耕地场景,无论是平原连片耕地、山地细碎梯田、城郊零散种植地,均可实现高精度解译,完美适配工程项目与科研实验。
核心落地应用场景
-
国土耕地保护:耕地范围提取、非农化违建排查、耕地保有量动态监测
-
精准农业生产:作物种植结构统计、种植面积普查、长势分级评估
-
农业科研分析:耕地时空演变、种植结构变迁、复种指数反演课题
-
乡村规划调研:全域耕地资源摸底、土地整治成效定量评估
一、农业遥感核心识别难点(行业通用痛点)
相比于城市、水体、植被常规地物,耕地与作物识别的混淆度更高、场景更复杂,也是绝大多数新手做农业遥感精度上不去的核心原因:
-
裸地与耕地高度混淆:休耕耕地、季节性裸田与自然裸土光谱几乎一致,传统算法无法区分
-
耕地地块粘连严重:平原连片农田无明显边界,普通分割模型容易整块融合,无法区分独立地块
-
同类作物光谱趋同:水稻、玉米、大豆等农作物生长期光谱重叠,单靠光谱无法精准分类
-
干扰地物繁杂:田间道路、大棚、沟渠、杂草带极易被误判为耕地,干扰识别精度
-
细碎耕地漏检率高:山地梯田、城郊零散小地块面积小、特征弱,模型容易丢失目标
二、本期AI农业遥感核心技术方案
针对农业场景痛点,我们采用双分支特征融合架构,分离「耕地地块分割」与「作物类型分类」任务,兼顾边界精度与分类准确率:
-
地块分割分支:优化U-Net边界感知模块,强化耕地边缘特征,解决地块粘连、边界模糊问题
-
作物分类分支:融合NDVI时序特征+纹理特征,破除同谱作物混淆难题
-
干扰剔除模块:专属特征过滤田间道路、沟渠、裸地、荒地非耕地干扰
-
批量后处理:小斑块去噪、空洞填充、地块规整化,输出标准化耕地成果
三、全流程农业遥感AI解译落地链路
标准化可复用作业流程,适配全国任意区域耕地监测与作物普查:
多光谱遥感影像获取 → 辐射/大气校正预处理 → 农业指数(NDVI/EVI)计算 → 耕地AI精准分割 → 非耕地干扰自动剔除 → 作物类型智能分类 → 耕地面积/种植面积统计 → 全域批量专题制图

耕地地块精准分割效果图
四、环境依赖与全套核心代码
4.1 一键安装依赖
bash
pip install torch rasterio opencv-python numpy pandas albumentations -i https://pypi.tuna.tsinghua.edu.cn/simple
4.2 农业遥感专属:耕地分割+作物分类双分支模型
python
# -*- coding: utf-8 -*-
# 农业遥感AI模型|耕地地块分割 + 多作物分类|干扰剔除
# 解决裸地混淆、地块粘连、作物错分核心问题
import torch
import torch.nn as nn
import torch.nn.functional as F
# 边界强化双卷积模块(适配耕地细碎边界)
class EdgeConv(nn.Module):
def __init__(self, in_c, out_c):
super().__init__()
self.conv1 = nn.Conv2d(in_c, out_c, 3, padding=1)
self.bn1 = nn.BatchNorm2d(out_c)
self.conv2 = nn.Conv2d(out_c, out_c, 3, padding=1)
self.bn2 = nn.BatchNorm2d(out_c)
self.relu = nn.ReLU(inplace=True)
def forward(self, x):
x = self.relu(self.bn1(self.conv1(x)))
x = self.relu(self.bn2(self.conv2(x)))
return x
# 农业遥感双分支网络
class FarmSegNet(nn.Module):
def __init__(self, in_channels=4, seg_classes=2, cls_classes=4):
"""
in_channels: RGB+NDVI四通道输入
seg_classes: 耕地分割2类(非耕地/耕地)
cls_classes: 作物分类4类(水稻/玉米/大豆/其他作物)
"""
super().__init__()
# 共享特征提取层
self.e1 = EdgeConv(in_channels, 64)
self.e2 = EdgeConv(64, 128)
self.e3 = EdgeConv(128, 256)
self.pool = nn.MaxPool2d(2)
# 分割分支:耕地地块提取
self.up1 = nn.ConvTranspose2d(256, 128, 2, 2)
self.up2 = nn.ConvTranspose2d(128, 64, 2, 2)
self.seg_out = nn.Conv2d(64, seg_classes, 1)
# 分类分支:作物类型识别
self.gap = nn.AdaptiveAvgPool2d(1)
self.cls_fc = nn.Linear(256, cls_classes)
def forward(self, x):
# 编码特征提取
e1 = self.e1(x)
e2 = self.e2(self.pool(e1))
e3 = self.e3(self.pool(e2))
# 分割分支前向
u1 = self.up1(e3) + e2
u2 = self.up2(u1) + e1
seg_pred = self.seg_out(u2)
# 分类分支前向
gap_feat = self.gap(e3).flatten(1)
cls_pred = self.cls_fc(gap_feat)
return seg_pred, cls_pred
# 农业专属损失函数(解决耕地样本不均衡、裸地混淆)
class FarmLoss(nn.Module):
def __init__(self):
super().__init__()
self.ce_seg = nn.CrossEntropyLoss()
self.ce_cls = nn.CrossEntropyLoss()
def forward(self, seg_pred, seg_label, cls_pred, cls_label):
# 分割Dice优化,弱化裸地干扰
dice = 1 - torch.sum(seg_pred * seg_label) / (torch.sum(seg_pred) + torch.sum(seg_label) + 1e-6)
loss_seg = 0.6 * self.ce_seg(seg_pred, seg_label) + 0.4 * dice
loss_cls = self.ce_cls(cls_pred, cls_label)
return loss_seg + 0.3 * loss_cls
# 模型推理测试
if __name__ == "__main__":
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = FarmSegNet().to(device)
test_img = torch.randn(1, 4, 512, 512).to(device)
seg_res, cls_res = model(test_img)
farm_mask = torch.argmax(seg_res, dim=1)
crop_type = torch.argmax(cls_res, dim=1)
print("✅ 耕地分割+作物分类推理完成")

不同作物分类识别对比图
五、非耕地干扰自动剔除代码
针对性剔除田间道路、沟渠、裸土、荒地、建设用地等干扰,一键净化耕地掩膜,彻底解决农业遥感最头疼的混淆问题。
python
# 耕地干扰自动剔除|裸地/荒地/道路噪声净化
import cv2
import numpy as np
def remove_farm_noise(mask_path, save_path, min_area=300):
"""
min_area: 最小耕地斑块阈值,过滤细碎噪声
"""
mask = cv2.imread(mask_path, 0)
# 二值化耕地掩膜
binary = np.where(mask == 1, 255, 0).astype(np.uint8)
# 连通域分析剔除小噪声
num, labels, stats, _ = cv2.connectedComponentsWithStats(binary, connectivity=8)
clean_mask = np.zeros_like(binary)
for i in range(1, num):
area = stats[i, cv2.CC_STAT_AREA]
if area > min_area:
clean_mask[labels == i] = 255
cv2.imwrite(save_path, clean_mask)
print("✅ 非耕地干扰剔除完成,耕地掩膜已净化")
return clean_mask
if __name__ == "__main__":
remove_farm_noise("./farm_raw_mask.png", "./farm_clean_mask.png")

干扰剔除前后对比图
六、耕地面积统计 + 批量自动制图代码
支持单张/批量影像耕地面积统计,一键导出Excel报表,自动生成标准化农业专题图,无需人工PS修图。
python
# 耕地面积统计 + 批量专题制图工具
import cv2
import pandas as pd
import matplotlib.pyplot as plt
import os
# 哨兵2 10m分辨率 单像素面积100㎡
PIXEL_AREA = 100
def farm_stat_and_plot(mask_path, origin_img_path, save_plot_path):
# 面积统计
mask = cv2.imread(mask_path, 0)
farm_pix = len(mask[mask == 255])
farm_m2 = farm_pix * PIXEL_AREA
farm_km2 = farm_m2 / 1000000
# 保存统计报表
df = pd.DataFrame({
"耕地像素总数":[farm_pix],
"耕地面积(㎡)":[round(farm_m2,2)],
"耕地面积(km²)":[round(farm_km2,4)]
})
df.to_excel("./耕地面积统计报表.xlsx", index=False)
# 批量制图叠加
origin = cv2.imread(origin_img_path)
mask_color = np.zeros_like(origin)
mask_color[mask == 255] = [0,255,0]
fusion = cv2.addWeighted(origin, 0.7, mask_color, 0.3, 0)
plt.figure(figsize=(12,8))
plt.imshow(cv2.cvtColor(fusion,cv2.COLOR_BGR2RGB))
plt.axis("off")
plt.tight_layout()
plt.savefig(save_plot_path, dpi=300, bbox_inches="tight")
plt.close()
print("✅ 耕地统计完成 + 专题图输出成功")
return df
# 批量处理文件夹
def batch_farm_process(folder_path):
for file in os.listdir(folder_path):
if file.endswith("_mask.png"):
farm_stat_and_plot(os.path.join(folder_path,file),
os.path.join(folder_path,file.replace("_mask","_origin")),
os.path.join(folder_path,file.replace("_mask.png","_result.png")))
if __name__ == "__main__":
farm_stat_and_plot("./farm_clean_mask.png", "./origin.png", "./farm_final_plot.png")

耕地批量制图成果图
七、本期核心项目总结
-
农业遥感最大难点是裸地、荒地、休耕耕地混淆,双分支AI特征融合方案可从根源解决该行业痛点
-
边界强化模块完美适配细碎梯田、连片农田场景,彻底改善地块粘连、边界模糊问题
-
一站式实现分割、分类、去噪、统计、制图全自动化,大幅降低农业遥感落地门槛
-
适配国土耕地核查、精准农业、科研时序分析,通用性强、落地效果稳定
📌 下期预告
模型优化实战:注意力机制、损失函数、超参调优全套进阶技巧,手把手教你把模型精度拉满,彻底解决分割错漏分问题!