Rasterio读取的NDVI/NDWI栅格数组与QGIS值差异及绘图异常排查
问题描述
我有256张NDVI、NDWI影像,使用以下代码读取:
import os, rasterio src_mois = (rasterio.open(path)) array_mois = src_mois.read(1) print(array_mois)
部分影像读取后的数组如下(但QGIS中显示这些影像的值范围为-0.607159至-0.681409):
[[-3.4028235e+38 -3.4028235e+38 -3.4028235e+38 ... -3.4028235e+38 -3.4028235e+38 -3.4028235e+38] [-3.4028235e+38 -3.4028235e+38 -3.4028235e+38 ... -3.4028235e+38 -3.4028235e+38 -3.4028235e+38] [-3.4028235e+38 -3.4028235e+38 -3.4028235e+38 ... -3.4028235e+38 -3.4028235e+38 -3.4028235e+38] ... [-3.4028235e+38 -6.2753040e-01 -6.2753040e-01 ... -3.4028235e+38 -3.4028235e+38 -3.4028235e+38] [-3.4028235e+38 -6.1740422e-01 -6.1740422e-01 ... -3.4028235e+38 -3.4028235e+38 -3.4028235e+38] [-3.4028235e+38 -6.5297663e-01 -6.5297663e-01 ... -3.4028235e+38 -3.4028235e+38 -3.4028235e+38]]
多数影像读取后的数组值与QGIS中显示一致:
[[ 0.34498805 0.4038521 0.45953733 ... -0.00084021 -0.01416653 -0.01416653] [ 0.33337444 0.36398682 0.41986722 ... -0.00888733 -0.02618947 -0.02618947] [ 0.3356307 0.323984 0.34316206 ... -0.0089799 -0.01649707 -0.01649707] ... [-0.28778303 -0.312718 -0.312718 ... 0.49572146 0.5651871 0.5805117 ] [-0.2846862 -0.2940772 -0.2940772 ... 0.413783 0.46547 0.5263974 ] [-0.27166343 -0.2786367 -0.2786367 ... 0.3622923 0.37553316 0.40998626]]
我的目标是对这些影像取平均并使用Seaborn绘图,但直接绘图时程序似乎将-3.4028235e+38识别为-3,导致结果异常。请问这是什么原因?
原因分析与解决办法
1. 异常值本质
你看到的-3.4028235e+38是32位浮点型栅格的标准NoData(无效数据)标记,这个值是该数据类型能表示的最小负数,用来标记影像中无有效观测的区域。
2. QGIS正常显示的原因
QGIS会自动读取栅格元数据里的NoData配置,渲染时会跳过这些无效值,只展示有效数据的范围,所以你能看到正确的-0.607159至-0.681409区间。
3. 绘图异常的原因
Seaborn和底层Matplotlib不会自动识别这个特殊的NoData值,会把它当作正常数据处理。由于这个值远小于NDVI/NDWI的正常范围(-1到1),会极大拉低数据集的统计均值,同时绘图时坐标轴会被这个极小值强制拉伸,正常数据的分布被压缩,看起来像是程序把它识别成-3——这其实是坐标轴刻度自动取整导致的视觉错觉,程序实际处理的是原始的极小值。
4. 解决步骤
要解决这个问题,必须在计算和绘图前屏蔽无效值:
步骤1:读取NoData值
从rasterio数据源中直接获取元数据里的NoData配置:
src_mois = rasterio.open(path) nodata_val = src_mois.nodata array_mois = src_mois.read(1)
步骤2:替换为NaN
用numpy将NoData值替换为NaN(Not a Number),后续计算和绘图会自动忽略这类值:
import numpy as np array_mois[array_mois == nodata_val] = np.nan
步骤3:计算均值与绘图
使用np.nanmean()计算均值(自动忽略NaN),然后过滤NaN值再绘图:
import seaborn as sns import matplotlib.pyplot as plt # 假设所有处理后的影像数组存入all_arrays列表 mean_array = np.nanmean(all_arrays, axis=0) # 展平数组并过滤NaN flat_mean = mean_array.flatten() flat_mean = flat_mean[~np.isnan(flat_mean)] # 示例:绘制直方图 sns.histplot(flat_mean) plt.title("Mean NDVI/NDWI Distribution") plt.show()
内容的提问来源于stack exchange,提问作者sam
相关产品推荐
相关产品推荐

