卫星影像林地识别任务像素值归一化方法选型咨询
卫星影像林地语义分割的归一化方案选择
两种方法的核心差异
两种方式虽然最终都把像素映射到[0,1]区间,但缩放逻辑完全不同:
- 直接除以255:以8位影像的理论全局值域[0,255]为统一基准做线性缩放,所有影像、所有patch、所有通道的缩放比例固定,完整保留像素间的原始相对亮度、光谱差异。
- 参考示例中的
MinMaxScaler用法:对每个切分后的256×256影像patch单独计算像素极值,按公式(x - patch内通道最小值)/(patch内通道最大值 - patch内通道最小值)做缩放,会自动把每个patch的对比度拉满,直接抹除不同patch间的整体亮度、色调差异。
场景适配结论
针对卫星影像林地识别任务,90%以上的场景优先选择全局固定缩放(8位影像除以255,16位影像除以65535),不建议直接照搬示例里的单patch MinMaxScaler写法,核心原因如下:
- 卫星影像的像素值对应实际地物的光谱反射率,是区分林地、耕地、建筑、水体等地类的核心依据。单patch独立归一化会扭曲地物间的原始光谱相对关系:比如阴坡覆盖的均匀林地暗patch,经过拉伸后最暗的林地像素会被映射为0、最亮的林地像素被映射为1,和阳坡裸地patch的像素值分布完全重合,直接破坏模型识别林地依赖的光谱特征。
- 单patch归一化会引入训练-推理分布偏移:推理阶段输入的影像patch如果存在极值异常(比如patch内有小片云、反光水面),归一化后的像素分布会和训练集分布产生明显差异,直接导致模型精度跳水。
- 示例代码用单patch MinMaxScaler是适配其所用的小样本航拍数据集——该数据集存在明显的局部曝光不均问题,单patch拉伸相当于做了简易的局部对比度增强,这个前提在多数经过辐射校正的卫星影像场景下不成立。
特殊情况调整
如果你的卫星影像没有做过辐射归一化,不同时相、不同景的影像整体亮度差异极大,可以使用MinMaxScaler,但必须遵守一个原则:提前在整个训练集所有数据上计算逐通道的全局最小值、最大值,固定缩放参数后再应用到所有训练、验证、推理数据上,绝对不能对单个patch/单张影像单独fit缩放参数。
参考代码片段
示例中两种归一化的对应实现如下:
from sklearn.preprocessing import MinMaxScaler, StandardScaler scaler = MinMaxScaler() root_directory = 'Semantic segmentation dataset/' patch_size = 256 image_dataset = [] for path, subdirs, files in os.walk(root_directory): dirname = path.split(os.path.sep)[-1] if dirname == 'images': images = os.listdir(path) for i, image_name in enumerate(images): if image_name.endswith(".jpg"): image = cv2.imread(path+"/"+image_name, 1) SIZE_X = (image.shape[1]//patch_size)*patch_size SIZE_Y = (image.shape[0]//patch_size)*patch_size image = Image.fromarray(image) image = image.crop((0 ,0, SIZE_X, SIZE_Y)) image = np.array(image) print("Now patchifying image:", path+"/"+image_name) patches_img = patchify(image, (patch_size, patch_size, 3), step=patch_size) for i in range(patches_img.shape[0]): for j in range(patches_img.shape[1]): single_patch_img = patches_img[i,j,:,:] # 单patch MinMaxScaler写法(不推荐直接用于卫星影像) single_patch_img = scaler.fit_transform(single_patch_img.reshape(-1, single_patch_img.shape[-1])).reshape(single_patch_img.shape) # 全局除以255写法(8位影像推荐) #single_patch_img = (single_patch_img.astype('float32')) / 255. single_patch_img = single_patch_img[0] image_dataset.append(single_patch_img)
提示:如果使用16位存储的卫星影像(如Sentinel-2、Landsat系列原始产品),像素值域为0-65535,直接除以255会导致像素值远超[0,1]区间,此时应替换为除以65535,或使用提前算好全局参数的MinMaxScaler。
内容的提问来源于stack exchange,提问作者Nico1654
相关产品推荐
相关产品推荐

