
简介这份资源是2021年辽宁省土地利用ESRI 10米精度栅格数据集面向GIS分析、城市规划、环境评估与农业研究等方向的学习者和从业者可用于土地资源分布研究、变化监测与规划管理。数据源自ESRI官方按中国大陆架整理并依省级行政区裁剪坐标系为WGS84地理坐标系便于跨区域比较与叠加分析。压缩包为rar格式整体约55.3MB内含727幅TIF格式栅格文件TIF可存储地理参考与元数据适合在ArcGIS等平台中直接加载处理。土地利用分类涵盖农田、森林、建设用地、水域等类型能支撑土地利用规划、环境影响评估与城市发展趋势分析。目前已有134人学习下载适合需要高精度省级土地覆盖数据的中高级GIS用户参考使用。1. 辽宁省10m土地利用ESRI数据从下载到能跑模型中间隔着多少坑手里有一份“2021年土地利用ESRI辽宁省10m精度”的数据第一反应往往是打开ArcGIS看一眼觉得分类挺全、颜色挺好看然后就想直接扔进模型里跑。但真正做过空间分析的人都知道从拿到这份栅格到它能被模型正常读取、统计面积、做变化检测中间至少隔着坐标系、NoData、分类编码、切片边界这四道坎。这份数据本质上是2021年辽宁省全域的10米分辨率土地覆盖栅格采用ESRI标准分类体系常见类别包括耕地、林地、草地、水体、建设用地、未利用地等。它适合做省域尺度的土地利用格局分析、生态评估、城市扩张监测也适合作为遥感分类模型的标签底图。但如果你只是把它当普通图片处理后面一定会翻车。这一章先把这份数据是什么、能干什么、坑在哪说清楚后面几章再一步步拆解怎么把它变成能用的分析底图。2. 拿到栅格先别急着分类统计坐标系、NoData与分类编码的预处理2.1 为什么ESRI分类体系不能直接对应国内常用地类ESRI土地利用分类体系是Esri基于Sentinel-2影像生产的全球土地覆盖产品所用的分类标准共分9个一级类水体、树木、草地、淹没植被、农作物、灌木、建成区、裸地、雪冰。这套体系跟国内常用的《土地利用现状分类》GB/T 21010-2017不是一一对应的。比如ESRI的“农作物”既包含水田也包含旱地而国内分类里水田和旱地是分开的ESRI的“建成区”包含道路、建筑、工业用地国内则细分了工矿仓储、住宅、交通等。如果你直接拿ESRI的分类编码去套国内的土地利用转移矩阵结果一定是错的。常见做法是建一张映射表把ESRI的9类映射到国内常用的6个一级类耕地、林地、草地、水域、建设用地、未利用地。映射关系不是唯一的取决于你的研究目的。做生态评估时淹没植被通常归入水域做城市扩张分析时裸地有时要单独保留有时要归入未利用地。我一般会先在属性表里统计每个类别的像元数确认数据里实际出现了哪些类别再决定映射方案。import rasterio import numpy as np # 打开辽宁省2021年土地利用栅格 with rasterio.open(liaoning_2021_landuse_10m.tif) as src: print(坐标系:, src.crs) print(分辨率:, src.res) print(影像尺寸:, src.width, x, src.height) print(NoData值:, src.nodata) # 读取第一波段 data src.read(1) # 统计各分类编码的像元数 unique, counts np.unique(data, return_countsTrue) for val, cnt in zip(unique, counts): print(f类别 {val}: {cnt} 像元)这段代码先确认三个关键信息坐标系是不是地理坐标系EPSG:4326还是投影坐标系如EPSG:32651分辨率是不是真的10米NoData值是多少。很多人在网上下载的栅格元数据里写的分辨率和实际像元大小不一致尤其是经过重采样或裁剪后的数据。如果坐标系是地理坐标系像元大小单位是度不是米直接算面积会得到荒谬的结果。辽宁省跨EPSG:32650和EPSG:32651两个UTM带如果要做面积统计建议统一重投影到Albers等面积投影比如EPSG:4526CGCS2000 / 3-degree Gauss-Kruger zone 41或自定义Albers。2.2 重投影与重采样10m精度怎么保住重投影到等面积投影时重采样方法的选择直接影响面积统计精度。常见做法是分类栅格用最近邻nearest连续栅格用双线性或三次卷积。土地利用是分类数据必须用最近邻否则会出现不存在的类别值。重采样到10米时如果源数据本身就是10米理论上不需要重采样但重投影会引入像元变形最近邻能保证类别值不变代价是边界会有锯齿。from rasterio.warp import calculate_default_transform, reproject, Resampling # 重投影到Albers等面积投影 dst_crs EPSG:4526 # CGCS2000 / 3-degree Gauss-Kruger zone 41 with rasterio.open(liaoning_2021_landuse_10m.tif) as src: transform, width, height calculate_default_transform( src.crs, dst_crs, src.width, src.height, *src.bounds ) kwargs src.meta.copy() kwargs.update({ crs: dst_crs, transform: transform, width: width, height: height, nodata: 0 }) with rasterio.open(liaoning_2021_landuse_albers.tif, w, **kwargs) as dst: for i in range(1, src.count 1): reproject( sourcerasterio.band(src, i), destinationrasterio.band(dst, i), src_transformsrc.transform, src_crssrc.crs, dst_transformtransform, dst_crsdst_crs, resamplingResampling.nearest # 分类数据必须用最近邻 )参数说明dst_crs选EPSG:4526是因为辽宁省大部分区域在中央经线123°E附近3度带投影变形小。如果你的研究区跨带用Albers自定义投影更合适参数设为中央经线123°E双标准纬线40°N和52°N。nodata设为0因为ESRI分类编码从1开始0可以作为背景值。重投影后一定要再统计一次各类别像元数确认没有因为重采样产生新的类别值或丢失类别。2.3 NoData处理那些“看起来是0”的像元NoData是栅格分析里最容易被忽视的坑。很多下载的栅格把NoData设为0但0在ESRI分类里不是有效类别所以没问题。但有些数据把NoData设为-9999或255如果你不处理统计面积时会把NoData当成一个巨大的类别。更隐蔽的情况是数据边缘有零散NoData像元做邻域分析时这些像元会被当成0参与计算导致结果出现异常值。处理方式很简单在读取时用maskedTrue或者在重投影后把NoData像元统一设为0并在后续分析中排除。如果做面积统计建议先裁剪到辽宁省行政边界再统计避免边界外的NoData干扰。import geopandas as gpd from rasterio.mask import mask # 用辽宁省行政边界裁剪 liaoning gpd.read_file(liaoning_boundary.shp) with rasterio.open(liaoning_2021_landuse_albers.tif) as src: # 确保边界坐标系与栅格一致 liaoning liaoning.to_crs(src.crs) geoms [geom for geom in liaoning.geometry] out_image, out_transform mask(src, geoms, cropTrue, nodata0) # 更新元数据 out_meta src.meta.copy() out_meta.update({ height: out_image.shape[1], width: out_image.shape[2], transform: out_transform, nodata: 0 }) with rasterio.open(liaoning_2021_landuse_clipped.tif, w, **out_meta) as dst: dst.write(out_image)裁剪后统计各类别面积用像元数乘以像元面积10m×10m100m²再换算成公顷或平方公里。注意重投影后像元大小可能不是精确的10米要用src.res读取实际值。如果重投影后像元大小变成9.8米或10.2米面积统计会有偏差这是正常的等面积投影下像元面积基本一致但边界处会有半个像元的误差。3. 从栅格到面积统计表用Python做辽宁省各地类汇总3.1 按行政区统计面积的完整脚本拿到预处理后的栅格下一步是按行政区统计各地类面积。常见做法是用rasterstats的zonal_stats或者用geopandas叠加rasterio手动统计。zonal_stats更方便但要注意它默认统计的是像元值不是面积。你需要先算出每个像元的面积再乘以像元数。import geopandas as gpd import rasterio import numpy as np from rasterstats import zonal_stats # 读取行政区划和栅格 districts gpd.read_file(liaoning_districts.shp) with rasterio.open(liaoning_2021_landuse_clipped.tif) as src: arr src.read(1) transform src.transform nodata src.nodata # 计算像元面积平方米 pixel_area abs(transform[0] * transform[4]) # 10m * 10m 100m² # 定义ESRI类别到国内一级类的映射 esri_to_china { 1: 水域, # 水体 2: 林地, # 树木 3: 草地, # 草地 4: 水域, # 淹没植被 5: 耕地, # 农作物 6: 草地, # 灌木 7: 建设用地, # 建成区 8: 未利用地, # 裸地 9: 未利用地 # 雪冰 } # 按行政区统计 results [] for idx, row in districts.iterrows(): geom [row.geometry] stats zonal_stats(geom, arr, affinetransform, nodatanodata, categoricalTrue, category_mapesri_to_china) if stats: for cat, count in stats[0].items(): area_ha count * pixel_area / 10000 # 换算成公顷 results.append({ 行政区: row[name], 地类: cat, 面积_公顷: round(area_ha, 2) }) import pandas as pd df pd.DataFrame(results) df.to_csv(liaoning_landuse_area_by_district.csv, indexFalse, encodingutf-8-sig)参数说明categoricalTrue表示按类别统计category_map把ESRI编码映射到中文类别名。pixel_area用transform[0] * transform[4]计算注意transform[4]通常是负数取绝对值。如果重投影后像元不是正方形要分别用transform[0]和transform[4]的绝对值相乘。统计结果保存为CSV时用utf-8-sig编码避免Excel打开乱码。3.2 面积统计的精度验证和官方数据对不上怎么办统计出来的面积跟统计年鉴对不上是常态。原因有几个一是ESRI分类体系的“耕地”包含休耕地和部分果园比国内耕地口径大二是10米分辨率下道路、沟渠等线状地物被归入建成区或未利用地导致建设用地偏大三是边界处混合像元的影响。我一般会做两件事一是把统计结果按地类汇总到省一级跟辽宁省统计年鉴的耕地、林地、建设用地面积做对比偏差在10%以内可以接受二是如果偏差超过20%检查是不是NoData没处理好或者重投影时像元面积算错了。另一个常见问题是行政区划边界和栅格边界不完全重合导致边缘像元被重复统计或漏统计。zonal_stats默认用像元中心点判断归属如果行政区很小可能会漏掉。解决办法是用all_touchedTrue但这样会重复统计边界像元。我一般先用all_touchedFalse跑一遍再用all_touchedTrue跑一遍对比差异如果差异超过5%说明行政区边界和栅格对齐有问题需要手动调整。4. 避坑与排查土地利用栅格处理中最容易翻车的5个地方4.1 现象面积统计结果出现负数或极大值原因NoData值没处理好或者重投影时用了双线性插值导致分类值被插值成小数再取整时出现异常值。解决分类栅格重采样必须用最近邻NoData在读取时用maskedTrue排除统计前确认src.nodata的值并在zonal_stats里显式传入nodata参数。4.2 现象ArcGIS里打开正常Python读取全是0原因栅格的NoData值被设为0而Python读取时没有排除NoData或者栅格的压缩方式Python不支持。解决用rasterio.open时加maskedTrue或者先用gdal_translate转成未压缩的GeoTIFF。如果数据是LZW压缩的rasterio通常能读但某些老版本会有问题转成DEFLATE压缩更稳。4.3 现象重投影后类别值变了出现2.5、3.7这种小数原因用了双线性或三次卷积重采样。解决分类数据永远用最近邻。如果已经错了重新用最近邻跑一遍不要试图用取整修复取整会改变类别边界。4.4 现象按行政区统计时某些区县面积为0原因行政区划的坐标系和栅格不一致或者行政区边界是MultiPolygonzonal_stats没正确处理。解决先用to_crs统一坐标系再把MultiPolygon拆成单个Polygon或者用explode。如果还是0检查行政区是否在栅格范围内用geopandas的clip先裁剪行政区。4.5 现象10米精度数据在模型里跑得特别慢原因辽宁省全域10米栅格大约有几十亿像元直接读进内存会爆。解决用窗口读取rasterio.windows分块处理或者先重采样到30米做粗略分析再对重点区域用10米精细分析。如果做深度学习用torch.utils.data.Dataset配合rasterio的窗口读取不要一次性加载。5. 进阶用法用这份数据做变化检测和模型标签的3个技巧5.1 多期数据对齐2021年和2020年栅格怎么配准如果你手里还有2020年或2019年的同款数据做变化检测的第一步是确保两期栅格的坐标系、分辨率、范围完全一致。常见做法是用rasterio的reproject把两期数据统一到同一个网格或者用gdalwarp的-te和-tr参数强制对齐。对齐后做差值得到变化图。注意ESRI分类体系在不同年份可能有微调比如2020年的“裸地”在2021年可能被归入“建成区”做变化检测前要先确认两期数据的分类标准是否一致。# 两期栅格对齐后做变化检测 with rasterio.open(liaoning_2020_landuse_aligned.tif) as src1: arr2020 src1.read(1) with rasterio.open(liaoning_2021_landuse_aligned.tif) as src2: arr2021 src2.read(1) # 计算变化像元 change (arr2020 ! arr2021) (arr2020 ! 0) (arr2021 ! 0) change_count np.sum(change) print(f变化像元数: {change_count}) print(f变化面积: {change_count * 100 / 10000:.2f} 公顷) # 统计各地类之间的转移矩阵 from sklearn.metrics import confusion_matrix mask (arr2020 ! 0) (arr2021 ! 0) cm confusion_matrix(arr2020[mask], arr2021[mask]) print(转移矩阵:) print(cm)这段代码先排除NoData像元再计算变化像元数和转移矩阵。转移矩阵的行是2020年类别列是2021年类别对角线是未变化像元。如果对角线数值远小于非对角线说明两期数据分类标准不一致需要重新映射。5.2 用这份数据做语义分割标签的注意事项把土地利用栅格作为语义分割标签时要注意三点一是类别不平衡建设用地和水体像元数远少于林地训练时要用类别权重或Focal Loss二是边界模糊10米分辨率下地块边界有1-2个像元的过渡带标签噪声会影响模型精度可以用形态学操作平滑边界三是NoData区域要设为忽略索引ignore_index不要当成背景类训练。我一般会先把栅格转成PNG或NumPy数组用ignore_index0类别从1开始。如果做多分类输出层用softmax损失函数用CrossEntropyLoss(ignore_index0, weightclass_weights)。class_weights用sklearn.utils.class_weight.compute_class_weight按像元频率算。5.3 一个我常用的验证习惯每次处理完土地利用栅格我都会做一件事随机抽1000个像元用高分辨率影像比如Google Earth或天地图目视核对类别。如果准确率低于85%说明数据质量或预处理有问题。这个习惯帮我发现过好几次重投影导致的类别偏移也发现过下载的数据其实是30米重采样到10米的假精度。10米数据在辽宁省这种地形复杂区域山区林地和草地的混淆率较高目视核对能快速定位问题区域。希望帮到你。本文还有配套的精品资源点击获取