简介:黑河流域中游地区土地覆被分类数据集(2018)面向GIS与遥感领域的研究者、政策制定者及环保从业者,为分析区域土地利用现状、支撑水资源管理、生态保护与农业规划提供基础数据。该数据基于遥感影像与GIS空间分析生成,包含分类栅格及研究区边界等矢量文件。压缩包共9个文件,涵盖tif、shp、dbf、prj、sbn等格式,其中tif为土地覆被分类结果,shp及配套文件构成研究区矢量边界,总体积约1.36MB,便于快速下载与调用。目前已有138人学习关注。通过该数据集,用户可直接在ArcGIS、QGIS等平台中打开并叠加分析,提取各土地类别的面积与空间分布,还可结合多期数据研判土地覆被变化趋势,为干旱区水资源调度、生态脆弱性评估及土地利用规划提供量化依据。
1. 为什么黑河流域中游需要一份2018年的土地覆被分类图
黑河流域中游是水资源分配与生态保护交织的敏感区域,土地覆被类型直接影响下垫面参数、蒸散发模拟和旱区水文过程的边界条件。这份2018年的数据集并不是一张简单的“看图说话”的图片,而是一个工程化的GIS数据包:Classification.tif 保存了像元级的分类结果,StudyArea.shp 配套了研究区边界和投影信息。拿到数据后最容易被忽略的是文件之间的坐标基准是否一致,因为栅格和矢量的投影一旦不统一,后续的裁剪、面积统计和模型输入都会出现系统性偏差。下面从文件结构入手,逐步演示如何把这套数据安全地读入分析流程。
2. 数据包结构拆解:从Classification.tif到StudyArea.shp
2.1 一个rar里装了两类数据:栅格分类图与矢量边界
解压后的文件清单里,Classification.tif 是分类结果栅格,每个像元的整数值对应一种土地覆被类型,研究区边界则由一组 Shapefile 伴生文件承载。这里的栅格已经完成几何校正和分类后处理,在QGIS或ArcGIS中打开后可直接看到空间分布。设计者把栅格和矢量分开存放,而不是把边界直接烧录进栅格,是为了灵活应对尺度和统计口径变化:栅格保持连续表面的原始像元状态,矢量则能单独用于行政分区、流域分割或自定义研究区。常见的做法是用StudyArea对栅格做掩膜裁剪,既可以排除边界外像元,也能把大范围的分类结果整理到指定子区域。
2.2 用GDAL快速查看Classification.tif的元数据
开始统计分析前,先检查栅格的空间参考、像元尺寸和NoData设置,这一步能避开很多后期返工。在终端执行:
gdalinfo Classification.tif重点看Coordinate System is这一段,它标明投影是 UTM zone 47N 还是 WGS 84 经纬度;同时确认Band 1的Type是 Byte 还是 UInt16,这决定最大类别编码是否超出范围。如果需要查看直方图,可以加入-hist参数,但要注意这会在同目录生成辅助文件。另一个关键命令是检查矢量边界:
ogrinfo -al StudyArea.shp-al表示读取所有要素属性和几何范围。若输出中的Layer SRS与栅格投影不相同,后续用Python做掩膜或裁剪时就要通过重投影统一。特别强调一下:如果gdalinfo返回的像素尺寸很大(例如超过1000),通常说明这是遥感影像而非分类结果,这时需要检查波段数和数据类型,避免误用。
2.3 Shapefile的“伴生文件”为什么一个都不能少
Shapefile 不是单文件格式,而是一组文件的集合。很多人只拷贝 .shp,却打不开,就是因为缺少伴生文件。下表列出StudyArea各文件的作用:
| 文件后缀 | 作用 | 缺失后果 |
|---|---|---|
| .shp | 要素几何 | 无法显示图形 |
| .shx | 几何索引 | 读取缓慢或失败 |
| .dbf | 属性表字段 | 属性丢失 |
| .prj | 坐标投影定义 | 识别成未知坐标系 |
| .cpg | 属性表编码 | 中文字段乱码 |
| .sbn/.sbx | 空间索引 | 部分分析操作效率降低 |
| .shp.xml | 元数据 | 属性信息不完整 |
.cpg经常被忽视,它声明属性表字符编码;如果当前环境默认是 UTF-8 而数据是 GBK,读取研究区名称时会出现乱码。此时不需要重编辑数据,只需在QGIS的图层属性里手动指定编码即可。.sbn和.sbx是ArcGIS创建的空间索引,如果没有它们,QGIS也能打开,只是在做空间连接时速度会慢一些。这些伴生文件共同保证了矢量数据的完整性。
3. 从遥感影像到分类结果:算法选型与后处理参数
3.1 分类体系怎么定:一级类与二级类
土地覆被分类的第一步是确定分类体系。黑河流域中游的景观以绿洲农业、荒漠稀疏植被和河流水域为主,常用的一级类有六类:耕地、林地、草地、水域、建设用地和未利用地。但二级类划分差异较大,例如耕地可再分水田、水浇地;未利用地包括盐碱地、裸地和沙地。下表是经过归并后的参考编码体系:
| 编码 | 一级类 | 典型二级类 |
|---|---|---|
| 10 | 耕地 | 水田、水浇地、旱地 |
| 20 | 林地 | 有林地、灌木林、疏林地 |
| 30 | 草地 | 高覆盖度草地、中覆盖度草地、低覆盖度草地 |
| 40 | 水域 | 河流、湖泊、水库、坑塘 |
| 50 | 建设用地 | 城镇用地、农村居民点、交通用地 |
| 60 | 未利用地 | 盐碱地、沙地、裸土地 |
训练样本如果只按一级类采集,最大似然分类器容易栽在光谱相近的类别上,比如低覆盖度草地和裸土。稳妥的做法是先按二级类采集样本,分类后再把二级类归并到一级类。这样能在保持分类精度的同时,让后续应用中的类别口径统一。
3.2 监督分类中的特征空间与分类器参数:最大似然 vs SVM
分类特征的选择比分类器本身更影响精度。除了蓝、绿、红、近红外波段的反射率,常用特征还包括NDVI、NDWI、纹理特征和地形特征。将训练样本按7:3切分后,用支持向量机训练是比较通用的路线:
from sklearn.svm import SVC from sklearn.model_selection import train_test_split from sklearn.metrics import confusion_matrix # samples: n个样本的m维特征矩阵, labels: 训练样本对应的类别编码 X_train, X_test, y_train, y_test = train_test_split( samples, labels, test_size=0.3, random_state=42 ) # RBF核SVM: C控制误分类惩罚, gamma决定核宽度 model = SVC(kernel='rbf', C=100, gamma=0.01, class_weight='balanced') model.fit(X_train, y_train) # 预测并输出混淆矩阵 y_pred = model.predict(X_test) print(confusion_matrix(y_test, y_pred))这里的C和gamma需要根据样本量调整。C过大会造成过拟合,C过小则模型欠拟合;gamma越大模型越想贴近训练样本,越容易出现孤立点噪声。对多光谱影像,我一般先用StandardScaler标准化特征,否则不同波段的数值范围差异巨大,gamma值会失去可解释性。与SVM相比,最大似然分类器假定每一类光谱值服从正态分布,在类别样本不均衡、山区地形阴影较重时误差很大,目前高分辨率影像更适合用SVM或随机森林。
3.3 分类后处理:小图斑合并与精度评价
分类结果中的“椒盐”噪声是常见问题。一套可落地的后处理流程是:先去除孤立像元,再合并小图斑。如果用的是栅格,可以直接调用GDAL工具:
gdal_sieve.py -st 20 -8 Classification.tif Classification_sieved.tif-st 20表示小于20个像元的图斑将被合并到邻近图斑,-8指定用8邻域判断连通性。这个阈值不是固定的,对于30米分辨率影像,最小可识别地物往往是90米见方,对应9个像元;如果用于水文模型,常把面积小于最小产汇流单元的小图斑合并。后处理的代价是会损失边界细节,所以要根据用途决定阈值大小。后处理之后需要用独立的验证样本做精度检验,样本如果不足,可考虑分层随机采样。验证样本不具备时,可以借助高分辨率影像目视解译生成少量校验点,至少覆盖主要类别。
4. 实战:用Python统计土地覆被面积并生成专题图
4.1 用StudyArea裁剪分类栅格并统计各类别面积
实际项目中很少把整个流域的栅格直接纳入统计,通常先裁剪到研究范围。用 Python 操作时,必须确认栅格与矢量的坐标参考一致;否则掩膜结果会偏移出边界。可运行:
import rasterio as rio from rasterio.mask import mask import geopandas as gpd import numpy as np # 读取研究区矢量,并裁剪分类栅格 study_area = gpd.read_file("StudyArea.shp") with rio.open("Classification.tif") as src: out_img, out_transform = mask(src, study_area.geometry, crop=True, nodata=0) # 统计类别和像元数 classes, counts = np.unique(out_img, return_counts=True) # src.res[0]是栅格X方向分辨率,单位取决于投影;地理坐标系下是度,不是米 pixel_area = src.res[0] * src.res[1] areas_m2 = counts * pixel_area for cls, area_m2 in zip(classes, areas_m2): print(f"类别 {cls}: {area_m2:.2f} m²")这段代码里mask()的crop=True会把输出范围裁剪到矢量最小外接矩形,nodata=0是为了让边界外的像元赋为0,统计时需要用条件过滤掉。如果起始数据是WGS84经纬度,src.res[0]的单位是度,此时面积结果是“平方度”,没有物理意义。正确做法是先转成Albers等积投影或UTM投影,再计算像元面积。
4.2 计算混淆矩阵进行精度评估
如果手里有验证点数据,可以用rasterio.sample提取对应像元的分类值,然后计算混淆矩阵。参考代码如下:
import pandas as pd import rasterio as rio # 假设验证数据有x, y, true_label三列 points = pd.read_csv("verification.csv") coords = [(x, y) for x, y in zip(points["x"], points["y"])] with rio.open("Classification.tif") as src: preds = [s[0] for s in src.sample(coords)] points["pred"] = preds # 过滤NoData或无效值 points = points[points["pred"] != 0] conf_mat = pd.crosstab(points["true_label"], points["pred"], rownames=["真实"], colnames=["预测"]) print(conf_mat) # 总体精度 overall_acc = (points["true_label"] == points["pred"]).mean() print(f"Overall Accuracy: {overall_acc:.3f}")验证点必须落在有效像元内,且独立于训练样本。一个常见误用是拿训练样本当验证样本,导致精度虚高。抽样时建议采用分层随机抽样,保证每个类有足够样本量。混淆矩阵之后,还可以用sklearn.metrics.cohen_kappa_score计算Kappa系数,Kappa低于0.8时说明分类结果与真值分歧偏大。
4.3 生成土地覆被专题图
论文插图通常需要输出高分辨率专题图。直接在裁剪结果out_img上绘制,并叠加研究区边界即可。一个可复现的制图代码:
import matplotlib.pyplot as plt from matplotlib.colors import ListedColormap # 颜色列表,按类别编码排列,第0位给NoData cmap = ListedColormap(["#FFFFFF", "#F5DEB3", "#228B22", "#7CFC00", "#4682B4", "#808080", "#FFD700"]) fig, ax = plt.subplots(figsize=(10, 8)) im = ax.imshow(out_img, cmap=cmap, vmin=0, vmax=6) # 叠加边界 study_area.boundary.plot(ax=ax, edgecolor="black", linewidth=0.8) # 添加图例 for cls, lab in zip([1, 2, 3, 4, 5, 6], ["耕地", "林地", "草地", "水域", "建设用地", "未利用地"]): ax.scatter([], [], c=cmap(cls), label=lab) ax.legend(loc="lower right", fontsize=9) ax.set_title("Land Cover Classification (2018)") plt.savefig("landcover_2018.png", dpi=300, bbox_inches="tight")这里vmin=0, vmax=6必须和实际最大类别编码对齐,否则颜色映射会错位。如果某类没有出现,地图上仍会显示对应颜色块。输出时建议使用bbox_inches="tight"裁掉多余白边,再按期刊要求调整dpi。
5. 进阶:多期对比前的坐标对齐与面积精度控制
5.1 用gdalwarp统一投影与像元尺寸
当与2010年、2015年的数据进行对比时,绝对不能直接把不同投影的栅格叠加。常见做法是选一个共同基准面,让所有影像落入同一网格中。
gdalwarp -t_srs EPSG:32647 -tr 30 30 -r near -overwrite Classification.tif Classification_UTM47.tif-t_srs EPSG:32647把数据转到UTM 47N,-tr 30 30强制像元尺寸为30米,-r near表示用最近邻重采样,保证整数类别值不被插值成小数。需要注意,如果两个时期的分辨率不一致,比如一个30米一个16米,统一分辨率后可能丢掉小图斑,这种情况更推荐保留较高分辨率,并在统计阶段统一尺度。
5.2 面积按椭球计算:用geopandas的area
栅格统计时的像元面积是名义平面面积,在区域跨度大时,面积误差会明显放大。若将分类栅格转化为多边形,再在等积投影下计算面积,会更加接近椭球实际。
# 将栅格转为矢量的过程可借助rasterio.features.shapes from rasterio.features import shapes from shapely.geometry import shape import geopandas as gpd with rio.open("Classification.tif") as src: results = [] for geom, val in shapes(src.read(1), mask=src.read(1) != 0, transform=src.transform): if val != 0: results.append({"geometry": shape(geom), "class": int(val)}) gdf = gpd.GeoDataFrame(results, crs=src.crs) gdf_aea = gdf.to_crs("EPSG:5070") # 北美Albers,可替换为适合中国的等积投影 gdf_aea["area_m2"] = gdf_aea.geometry.areaEPSG:5070是北美地区的等积投影,中国区域更常用Albers正轴等积投影(例如EPSG:102025或自定义中央经线)。使用等积投影的好处是,任何位置的面积量算都不会因纬度不同而扭曲,这也是做面积变化分析时优先考虑的方法。
5.3 分区统计技巧:避免像元错位
矢量面边界与栅格像元边界几乎不可能完全重合,直接用面矢量提取像元,会沿着边界产生锯齿状切分。更可靠的做法是把矢量栅格化成与分类结果完全相同的网格,再做掩膜统计:
gdal_rasterize -burn 1 -tr 30 30 -te <xmin> <ymin> <xmax> <ymax> StudyArea.shp study_mask.tif其中的-te参数建议直接取目标栅格的范围,保证所有栅格在空间上完全重叠。之后再在Python中用np.ma或rasterio.mask进行统计。若需要边界内像元的面积权重统计,可以尝试exactextract库,它能计算栅格像元被矢量多边形覆盖的比例,统计精度比直接裁剪更高。操作时记得把不同年份的掩膜文件保存在独立目录,避免覆盖原始分类数据。
本文还有配套的精品资源,点击获取