97 lines
3.6 KiB
Python
97 lines
3.6 KiB
Python
"""
|
||
将 COG 格式的 Red, Green, Blue 单波段地表反射率图像合成 RGB 图像
|
||
|
||
1. 对比度线性拉伸至 0-255;
|
||
2. 合并波段;
|
||
3. 保存为 uint8 格式 RGB 图像;
|
||
"""
|
||
|
||
import os
|
||
import rasterio as rio
|
||
import numpy as np
|
||
|
||
def sr2rgb(red_path, green_path, blue_path, output_path):
|
||
"""
|
||
将红、绿、蓝三个单波段地表反射率图像合成为RGB图像
|
||
|
||
参数:
|
||
red_path (str): 红色波段文件路径
|
||
green_path (str): 绿色波段文件路径
|
||
blue_path (str): 蓝色波段文件路径
|
||
output_path (str): 输出RGB图像路径
|
||
"""
|
||
# 检查文件是否存在
|
||
for path in [red_path, green_path, blue_path]:
|
||
if not os.path.exists(path):
|
||
raise FileNotFoundError(f"文件不存在: {path}")
|
||
|
||
print(f"正在处理文件:")
|
||
print(f" 红波段: {red_path}")
|
||
print(f" 绿波段: {green_path}")
|
||
print(f" 蓝波段: {blue_path}")
|
||
|
||
# 读取三个波段数据
|
||
with rio.open(red_path) as red_src:
|
||
red_band = red_src.read(1)
|
||
profile = red_src.profile
|
||
print(f"红波段形状: {red_band.shape}, 数据类型: {red_band.dtype}")
|
||
|
||
with rio.open(green_path) as green_src:
|
||
green_band = green_src.read(1)
|
||
print(f"绿波段形状: {green_band.shape}, 数据类型: {green_band.dtype}")
|
||
|
||
with rio.open(blue_path) as blue_src:
|
||
blue_band = blue_src.read(1)
|
||
print(f"蓝波段形状: {blue_band.shape}, 数据类型: {blue_band.dtype}")
|
||
|
||
# 线性拉伸到0-255范围
|
||
def stretch_band(band):
|
||
# 处理NaN值
|
||
band_no_nan = np.where(np.isnan(band), 0, band)
|
||
band_min = np.min(band_no_nan)
|
||
band_max = np.max(band_no_nan)
|
||
|
||
# 避免除零错误
|
||
if band_max == band_min:
|
||
stretched = np.zeros_like(band_no_nan, dtype=np.uint8)
|
||
else:
|
||
stretched = ((band_no_nan - band_min) / (band_max - band_min) * 255).astype(np.uint8)
|
||
return stretched
|
||
|
||
red_stretched = stretch_band(red_band)
|
||
green_stretched = stretch_band(green_band)
|
||
blue_stretched = stretch_band(blue_band)
|
||
|
||
# 合并三个波段为RGB图像
|
||
rgb_array = np.dstack((red_stretched, green_stretched, blue_stretched))
|
||
|
||
# 更新元数据
|
||
profile.update(
|
||
dtype=rio.uint8,
|
||
count=3,
|
||
photometric='RGB',
|
||
nodata=0 # 设置nodata为0,因为uint8的范围是0-255
|
||
)
|
||
|
||
# 保存RGB图像
|
||
with rio.open(output_path, 'w', **profile) as dst:
|
||
for i in range(3):
|
||
dst.write(rgb_array[:, :, i], i + 1)
|
||
|
||
print(f"RGB图像已保存到: {output_path}")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
# tif_dir = "D:\\NASA_EarthData_Script\\data\\HLS\\2024\\2024012"
|
||
# red_path = os.path.join(tif_dir, "HLS.S30.T49RGP.2024012T031101.v2.0.RED.subset.tif")
|
||
# green_path = os.path.join(tif_dir, "HLS.S30.T49RGP.2024012T031101.v2.0.GREEN.subset.tif")
|
||
# blue_path = os.path.join(tif_dir, "HLS.S30.T49RGP.2024012T031101.v2.0.BLUE.subset.tif")
|
||
# output_path = os.path.join(tif_dir, "HLS.S30.T49RGP.2024012T031101.v2.0.RGB.tif")
|
||
|
||
tif_dir = "D:\\NASA_EarthData_Script\\data\\HLS\\2025\\2025011"
|
||
red_path = os.path.join(tif_dir, "HLS.S30.T49RGP.2025011T031009.v2.0.RED.subset.tif")
|
||
green_path = os.path.join(tif_dir, "HLS.S30.T49RGP.2025011T031009.v2.0.GREEN.subset.tif")
|
||
blue_path = os.path.join(tif_dir, "HLS.S30.T49RGP.2025011T031009.v2.0.BLUE.subset.tif")
|
||
output_path = os.path.join(tif_dir, "HLS.S30.T49RGP.2025011T031009.v2.0.RGB.tif")
|
||
|
||
sr2rgb(red_path, green_path, blue_path, output_path) |