feat(utils): 添加地表反射率转RGB图像功能.
This commit is contained in:
parent
c19f334035
commit
d01ba65d64
@ -139,7 +139,7 @@ def process_granule(
|
|||||||
name: str,
|
name: str,
|
||||||
roi: list,
|
roi: list,
|
||||||
clip=True,
|
clip=True,
|
||||||
tile_id: str = None,
|
tile_id: str = "",
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""
|
"""
|
||||||
读取解压并重命名处理后的指定类型 NASADEM 数据并进行预处理, 包括读取, 裁剪, 镶嵌, 并对坡度坡向进行缩放
|
读取解压并重命名处理后的指定类型 NASADEM 数据并进行预处理, 包括读取, 裁剪, 镶嵌, 并对坡度坡向进行缩放
|
||||||
@ -215,12 +215,10 @@ def main(region: list, asset_name: list, tile_id: str):
|
|||||||
os.makedirs(unzip_dir, exist_ok=True)
|
os.makedirs(unzip_dir, exist_ok=True)
|
||||||
os.makedirs(output_dir, exist_ok=True)
|
os.makedirs(output_dir, exist_ok=True)
|
||||||
results_urls_file = f"{output_root_dir}\\NASADEM_{tile_id}_results_urls.json"
|
results_urls_file = f"{output_root_dir}\\NASADEM_{tile_id}_results_urls.json"
|
||||||
if not os.path.isfile(results_urls_file):
|
# 默认覆盖上一次检索记录
|
||||||
results_urls = earthdata_search(asset_name, roi=bbox)
|
results_urls = earthdata_search(asset_name, roi=bbox)
|
||||||
with open(results_urls_file, "w") as f:
|
with open(results_urls_file, "w") as f:
|
||||||
json.dump(results_urls, f)
|
json.dump(results_urls, f)
|
||||||
else:
|
|
||||||
results_urls = json.load(open(results_urls_file))
|
|
||||||
# 构造待解压的文件列表
|
# 构造待解压的文件列表
|
||||||
zip_file_list = [os.path.join(download_dir, os.path.basename(result[0])) for result in results_urls]
|
zip_file_list = [os.path.join(download_dir, os.path.basename(result[0])) for result in results_urls]
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ envs_dirs:
|
|||||||
- D:\program\miniforge3\envs
|
- D:\program\miniforge3\envs
|
||||||
- 其他路径地址(可选,创建虚拟环境时将会按照顺序查找)
|
- 其他路径地址(可选,创建虚拟环境时将会按照顺序查找)
|
||||||
channels:
|
channels:
|
||||||
- defaults
|
- conda-forge
|
||||||
show_channel_urls: true
|
show_channel_urls: true
|
||||||
channel_alias: https://mirrors.tuna.tsinghua.edu.cn/anaconda
|
channel_alias: https://mirrors.tuna.tsinghua.edu.cn/anaconda
|
||||||
default_channels:
|
default_channels:
|
||||||
@ -117,6 +117,13 @@ mamba env create -f setup/environment.yml
|
|||||||
mamba activate lpdaac
|
mamba activate lpdaac
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- 导出当前虚拟环境
|
||||||
|
|
||||||
|
```sh
|
||||||
|
mamba env export > setup/lpdaac.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## 3 设计思路
|
## 3 设计思路
|
||||||
|
|
||||||
### 3.1 数据组织
|
### 3.1 数据组织
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Authors: Hong Xie
|
Authors: Hong Xie
|
||||||
Last Updated: 2025-07-07
|
Last Updated: 2025-08-13
|
||||||
===============================================================================
|
===============================================================================
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -506,9 +506,9 @@ def reproject_image(
|
|||||||
target_image.shape[1] == image.shape[1]
|
target_image.shape[1] == image.shape[1]
|
||||||
and target_image.shape[2] == image.shape[2]
|
and target_image.shape[2] == image.shape[2]
|
||||||
):
|
):
|
||||||
# 若判断为降尺度/等尺度, 则直接使用 cubic_spline 重采样投影到目标影像
|
# 若判断为降尺度/等尺度, 则直接使用 cubic 重采样投影到目标影像
|
||||||
image_reprojed = image.rio.reproject_match(
|
image_reprojed = image.rio.reproject_match(
|
||||||
target_image, resampling=Resampling.cubic_spline
|
target_image, resampling=Resampling.cubic
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# print("target_image shape is not match with image shape", image.shape, "to", target_image.shape)
|
# print("target_image shape is not match with image shape", image.shape, "to", target_image.shape)
|
||||||
@ -520,7 +520,7 @@ def reproject_image(
|
|||||||
# 使用 target_crs 进行重投影
|
# 使用 target_crs 进行重投影
|
||||||
reproject_kwargs = {
|
reproject_kwargs = {
|
||||||
"dst_crs": target_crs,
|
"dst_crs": target_crs,
|
||||||
"resampling": Resampling.cubic_spline,
|
"resampling": Resampling.cubic,
|
||||||
}
|
}
|
||||||
if target_shape is not None:
|
if target_shape is not None:
|
||||||
reproject_kwargs["shape"] = target_shape
|
reproject_kwargs["shape"] = target_shape
|
||||||
@ -563,7 +563,7 @@ def mosaic_images(
|
|||||||
tif_list,
|
tif_list,
|
||||||
nodata=nodata,
|
nodata=nodata,
|
||||||
method=method,
|
method=method,
|
||||||
resampling=Resampling.cubic_spline,
|
resampling=Resampling.cubic,
|
||||||
)
|
)
|
||||||
# 将结果重新构建为 xarray 数据集
|
# 将结果重新构建为 xarray 数据集
|
||||||
# 单张SAR影像直接读取 transform: 233400.0 30.0 0.0 3463020.0 0.0 -30.0
|
# 单张SAR影像直接读取 transform: 233400.0 30.0 0.0 3463020.0 0.0 -30.0
|
||||||
|
97
utils/sr2rgb.py
Normal file
97
utils/sr2rgb.py
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
"""
|
||||||
|
将 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)
|
Loading…
x
Reference in New Issue
Block a user