耕地的数量和质量是保持农业可持续发展的关键,利用卫星遥感影像可以识别并提取耕地,并对耕地进行遥感制图,准确的耕地分布能够为国家决策部门提供重要支撑。目前高精度的耕地信息提取主要还是依靠人工解译,耗费大量人力、财力且效率较低,因此,遥感图像的耕地识别算法研究将对耕地遥感制图提供重要帮助。
资源三号(ZY-3)卫星是中国第一颗自主的民用高分辨率立体测绘卫星,通过立体观测,可以测制 1∶5 万比例尺地形图,为国土资源、农业、林业等领域提供服务,资源三号填补了中国立体测图这一领域的空白。图片来源于资源三号卫星获取的遥感图像数据,空间分辨率为 2 米,光谱为可见光波段(红,绿,蓝)。
题目提供 8 幅图像和相应耕地标签,用于参赛者模型训练和测试,图像为 tif 格式。原图像预览图如图 1 所示,标签图预览图如图2 所示,标签图中白色(值为 1)代表的是耕地类,黑色(值为 0)代表的是背景类。另提供 2 幅图像作为测试实例。
问题 1:计算 10 幅图中耕地在各图像中所占比例,并填写表 1,数据请呈现在论文中;
问题 2:从给定的 2 幅测试图像(Test1.tif、Test2.tif)中提取出耕地,制作耕地标签图,并将标签图分别上传到竞赛平台中(注意田块间的边界是否清晰);
问题 3:我国土地辽阔,地貌复杂,你有什么创新的思路能够快速、精准的识别出田块。
准确标记耕地及计算耕地面积能为国家决策部门提供重要支撑。通过计算机识别卫星遥感影像中的耕地面积能够加速耕地信息的提取,减少人力、财力消耗。
在初赛中,我队基于 U-Net 卷积神经网络建立模型对题目数据进行处理,实现了精确度较高的遥感图像耕地地块分割与提取,成功计算出耕地面积比例并制作出较为清晰的耕地标签图。参考“集成学习”的思想,我们提出“多图平均二值法”用以辅助 U-Net 模型预测。该方法成功降低了预测结果中的噪声干扰,显著提升了预测的准确度。
本文对初赛模型进行优化,提升其对耕地边界的识别能力。同时,本文分析了预测模型中的关键参数并定量评估其对模型精度的影响。
针对问题一,在初赛模型的基础上,本文进一步探究初赛提出的“多图平均二值法”的合理性与使用条件,并依据其原理改进了数据增广方法和模型训练参数,对数据增广的随机旋转范围和训练迭代次数进行优化,使得训练出的 U-Net 模型预测精度显著提升。优化后的模型准确率达 99.02%,损失率 0.041,在遥感图像空间分辨率为 2m 的条件下,测试中可作出误差在 2%范围内的对耕地的精确分割。同时,为了在保证预测精度的同时提升耕地标签图的视觉效果,本文提出采用腐蚀膨胀操作对预测结果做进一步处理。结果显示,腐蚀与膨胀操作使得模型预测效果得到进一步提升。相比初赛模型,本文模型具有更为优秀的分割性能和更为良好的视觉效果。本文模型的预测图像耕地边缘更为清晰,噪声基本消失,道路连通性强。利用上述优化模型,本文预测 Test3,Test4 图像的耕地地块分布并制作标签图,计算耕地面积占比。
针对问题二,我们对问题一中的优化模型进行深度分析,详细描述了该识别系统中的关键参数(模型训练参数和腐蚀膨胀操作核参数),并定量评估了它们对本文模型识别精度的影响。
本文所述的优化算法、模型,在遥感图像空间分辨率为 2m 的条件下,测试中可作出误差在 2%范围内的对耕地的精确分割,预测图像噪声低,耕地边缘完整,可为耕地遥感制图提供借鉴与参考。
(1)假设已知专业人工标记标签图足够准确划分耕地与非耕地;
(2)假设在神经网络预测中,局部图像特征可代表整体特征;
(3)假设耕地面积、像素点误差可以作为耕地标签预测模型的评价标准;
(4)假设灰度、形状大小、分布体现耕地特性。
(5)假设低于 400 平方米(100 像素点)的误差属于较小面积误差,对识别精度影响不大。
在问题一中,题目要求我们优化初赛模型,从给定的测试图像(Test3.tif、Test4.tif)中提取出耕地,制作耕地标签图并计算其面积。数据集仍采用初赛中给出的 8 张遥感图像和人工标签。我们需要对初赛模型的预测能力进行分析,寻找模型缺陷,重点关注其对耕地边界的提取情况。在初赛模型的基础上设计优化思路,改进模型,并用优化后的模型对测试图像进行预测,制作耕地标签图,计算耕地面积比例。另外,我们需要比较优化前后对不同类别图像的表现,分析模型优化的合理性并说明优化效果。难点在于提升模型预测精度,优化模型对噪声、边界的处理。
在问题二中,题目要求我们总结模型中的关键参数,并定量评估其对识别精度的影响。我们需要分析模型,总结对模型识别精度影响较大的参数。我们适当调整参数测试模型,定量评估它们对模型识别精度的影响,寻找最优参数设置。
import numpy as np
import tensorflow as tf
input_data = tf.Variable( np.random.rand(1,6,6,3), dtype = np.float32 )
filter_data = tf.Variable( np.random.rand(3, 3, 3, 1), dtype = np.float32)
y = tf.nn.conv2d(input_data, filter_data, strides = [1, 1, 1, 1], padding = 'VALID')
with tf.Session() as sess:
init = tf.initialize_all_variables();
sess.run(init);
print (sess.run(y));
print (sess.run(tf.shape(y)));
# -*- coding: utf-8 -*-
import numpy as np
import tensorflow as tf
input_data = tf.Variable( np.random.rand(1,6,6,3), dtype = np.float32 )
filter_data = tf.Variable( np.random.rand(2, 2, 3, 10), dtype = np.float32)
y = tf.nn.conv2d(input_data, filter_data, strides = [1, 1, 1, 1], padding = 'VALID')
output = tf.nn.max_pool(value = y, ksize = [1, 2, 2, 1], strides = [1, 1, 1, 1], padding = 'VALID')
with tf.Session() as sess:
init = tf.initialize_all_variables()
sess.run(init)
print (' --convResult--')
print (sess.run(y))
print (' --poolResult--')
print (sess.run(output))
print (sess.run(tf.shape(output)))