如何用JPG掩码+无云影像实现TIFF卫星数据去云?求Python方案
卫星影像去云解决方案(基于Rasterio/skimage)
前提说明
需确保三幅影像的空间范围、分辨率、波段数完全匹配。若存在偏差,需先完成影像配准操作,否则替换后会出现错位问题。
方案一:基于Rasterio实现(推荐,支持地理元数据保留)
Rasterio专为地理栅格数据设计,能自动保留影像的坐标系统、投影等地理信息,适合专业卫星影像处理。
代码实现
import rasterio import numpy as np # 替换为你的文件路径 cloudy_tif = "cloudy_image.tif" cloud_mask_jpg = "cloud_mask.jpg" clear_tif = "clear_image.tif" output_tif = "denoised_result.tif" # 读取含云影像及元数据 with rasterio.open(cloudy_tif) as src_cloudy: cloudy_arr = src_cloudy.read() # 数组形状:(波段数, 高度, 宽度) save_profile = src_cloudy.profile # 用于保存结果的元数据模板 # 读取无云影像 with rasterio.open(clear_tif) as src_clear: clear_arr = src_clear.read() # 读取云掩码(JPG灰度图取单通道) with rasterio.open(cloud_mask_jpg) as src_mask: mask_arr = src_mask.read(1) # 生成云区布尔掩码:黑色像素(值为0)标记为True cloud_mask = mask_arr == 0 # 校验尺寸一致性 assert cloudy_arr.shape == clear_arr.shape, "含云与无云影像的波段数/尺寸不匹配" assert cloud_mask.shape == cloudy_arr.shape[1:], "掩码与影像的高度/宽度不匹配" # 替换云区像素:遍历每个波段,用无云影像覆盖云区 denoised_arr = cloudy_arr.copy() for band_idx in range(cloudy_arr.shape[0]): denoised_arr[band_idx][cloud_mask] = clear_arr[band_idx][cloud_mask] # 保存去云结果 with rasterio.open(output_tif, 'w', **save_profile) as dst: dst.write(denoised_arr)
注意事项
- 若JPG掩码因压缩导致黑色像素值不是严格的0,可调整阈值为
mask_arr < 10(根据实际情况微调) - 所有影像的投影、分辨率必须一致,否则替换后会出现空间错位
方案二:基于skimage实现(适合无地理元数据需求的场景)
skimage专注于通用图像处理,操作简洁,但无法直接处理地理元数据,适合已完成配准的影像。
代码实现
from skimage.io import imread, imsave import numpy as np # 替换为你的文件路径 cloudy_tif = "cloudy_image.tif" cloud_mask_jpg = "cloud_mask.jpg" clear_tif = "clear_image.tif" output_tif = "denoised_result.tif" # 读取影像:skimage读取TIFF为(高度, 宽度, 波段数)格式 cloudy_arr = imread(cloudy_tif) clear_arr = imread(clear_tif) # 读取掩码并转为灰度图 mask_arr = imread(cloud_mask_jpg, as_gray=True) # 生成云区布尔掩码 cloud_mask = mask_arr == 0 # 校验尺寸一致性 assert cloudy_arr.shape == clear_arr.shape, "含云与无云影像的波段数/尺寸不匹配" assert cloud_mask.shape == cloudy_arr.shape[:2], "掩码与影像的高度/宽度不匹配" # 适配多波段影像:将掩码扩展为(高,宽,1)维度,与影像通道匹配 if len(cloudy_arr.shape) == 3: cloud_mask = np.expand_dims(cloud_mask, axis=-1) # 替换云区:云区用无云影像填充,非云区保留原影像 denoised_arr = np.where(cloud_mask, clear_arr, cloudy_arr) # 保存结果:需保持与原影像一致的数据类型(如uint8、uint16) imsave(output_tif, denoised_arr.astype(cloudy_arr.dtype))
注意事项
- skimage读取TIFF的通道顺序为
(H,W,C),与Rasterio的(C,H,W)不同,需注意数组维度差异 - 若需要保留地理元数据,建议结合Rasterio读取/保存影像,仅用skimage完成像素替换操作
内容的提问来源于stack exchange,提问作者Salvatore Danilo Palumbo
相关产品推荐
相关产品推荐

