PythonでJAXAの人工衛星だいち(ALOS)の世界標高データ活用(2)

前回:https://shikuuk.blogspot.com/2025/07/jaxaalospython.html

 ※JAXAさま AW3D30 DSM data map Download Page参照

 第2部はさきほどDownloadした「N030E130_N035E135.zip」に含まれている5×5のTileを1枚の大きなModelに結合する処理(モザイク処理と呼ぶそうです)のCodeをGemini先生にお願いしました。
import rasterio
import numpy as np
import os
from rasterio.enums import Resampling
from rasterio.merge import merge # Ensure merge is imported

def merge_elevation_tiles(tile_dir, output_filepath):
    """
    Reads all GeoTIFF elevation tiles in the specified directory,
    merges them into a single GeoTIFF file, and saves it.

    Args:
        tile_dir (str): Path to the directory containing GeoTIFF files.
        output_filepath (str): Output path for the merged GeoTIFF file.
    Returns:
        str: Path to the merged GeoTIFF file (on success), or None (on failure).
    """
    src_files_to_mosaic = []
    # Iterate through all files in the directory to find GeoTIFFs
    for filename in os.listdir(tile_dir):
        if filename.endswith('.tif'): # Only process .tif files
            filepath = os.path.join(tile_dir, filename)
            try:
                src_files_to_mosaic.append(rasterio.open(filepath))
            except rasterio.errors.RasterioIOError as e:
                print(f"Warning: Could not open {filepath} (possibly corrupted or not a valid GeoTIFF): {e}. Skipping.")
            except Exception as e:
                print(f"Warning: Unexpected error opening {filepath}: {e}. Skipping.")

    if not src_files_to_mosaic:
        print("No valid GeoTIFF tile files found to merge in the specified directory. Exiting.")
        return None

    print(f"Merging {len(src_files_to_mosaic)} tiles...")
    # Merge the datasets; resampling='nearest' for discrete elevation values
    mosaic, out_transform = merge(src_files_to_mosaic, resampling=Resampling.nearest)

    # Convert to float32 if needed to save memory (from float64)
    if mosaic.dtype == np.float64:
        mosaic = mosaic.astype(np.float32)
        print("Converted mosaic to float32 to save memory.")

    # Copy metadata from the first source file and update with merged properties
    out_meta = src_files_to_mosaic[0].meta.copy()
    out_meta.update({
        "driver": "GTiff",
        "height": mosaic.shape[1], # New height of the merged mosaic
        "width": mosaic.shape[2],  # New width of the merged mosaic
        "transform": out_transform, # New georeferencing transform
        "crs": src_files_to_mosaic[0].crs, # Coordinate Reference System (assumed consistent)
        "nodata": src_files_to_mosaic[0].nodata # NoData value
    })

    # Close all source files to release resources
    for src in src_files_to_mosaic:
        src.close()

    # Save the merged mosaic to a new GeoTIFF file
    try:
        with rasterio.open(output_filepath, "w", **out_meta) as dest:
            dest.write(mosaic)
        print(f"Successfully merged tiles to '{output_filepath}'.")
        return output_filepath
    except Exception as e:
        print(f"Error saving merged GeoTIFF: {e}")
        return None

# --- Main Execution Block ---
if __name__ == "__main__":
    # Define the directory where GeoTIFF files are extracted
    extracted_data_dir = '/content/extracted_elevation_data/N030E130_N035E135'

    # Define the output path for the merged GeoTIFF file
    output_merged_filepath = os.path.join(extracted_data_dir, 'merged_5x5_elevation.tif')

    print("Starting GeoTIFF tile merging process...")
    merged_file_path = merge_elevation_tiles(extracted_data_dir, output_merged_filepath)

    if merged_file_path:
        print(f"\nSuccessfully merged all tiles. Now analyzing statistics for: {merged_file_path}")
        try:
            with rasterio.open(merged_file_path) as src:
                # Read the entire merged data
                merged_elevation_data = src.read(1)

                # Convert NoData values to NaN
                if src.nodata is not None:
                    merged_elevation_data[merged_elevation_data == src.nodata] = np.nan

                # Get valid (non-NaN) elevation data for statistics
                valid_merged_elevation_data = merged_elevation_data[~np.isnan(merged_elevation_data)]

                if valid_merged_elevation_data.size > 0:
                    print(f"Merged data original pixel size: {src.height}x{src.width} pixels")
                    print(f"Merged data geographical bounds (Lon/Lat): Left={src.bounds.left:.2f}, Bottom={src.bounds.bottom:.2f}, Right={src.bounds.right:.2f}, Top={src.bounds.top:.2f}")
                    print(f"Merged data elevation range: Min={np.min(valid_merged_elevation_data):.2f}m, Max={np.max(valid_merged_elevation_data):.2f}m")
                    print(f"Merged data mean elevation: {np.mean(valid_merged_elevation_data):.2f}m")
                    print(f"Merged data standard deviation: {np.std(valid_merged_elevation_data):.2f}m")
                    print(f"Merged data 2nd percentile: {np.percentile(valid_merged_elevation_data, 2):.2f}m")
                    print(f"Merged data 98th percentile: {np.percentile(valid_merged_elevation_data, 98):.2f}m")
                else:
                    print("No valid elevation data found in the merged file for statistics.")

        except Exception as e:
            print(f"An error occurred during statistics analysis of the merged file: {e}")
    else:
        print("GeoTIFF file merging failed, cannot proceed with statistics analysis.")


 何度かGemini先生にCodeを書き直してもらっていますが、それほど苦労せずにモザイク処理ができました。このコードの大まかな流れは以下の通りと解釈しました。
  • mainで5*5のTileが格納されているDirectoryと、Marge(結合=モザイク処理)したModelを格納するFileNameをassignしたあと、Function‘merge_elevation_tiles’を呼び出す。
  • Function‘merge_elevation_tiles’では、Tileが格納されているDirectory内のFileNameを全て読み込み、その中から拡張子が‘.tif’(Geotiffファイル)をSelectし、DirectoryとFileNameを合成したStringを作成し、それらのStringをList‘src_files_to_mosaic’にAppendする。
  • ‘src_files_to_mosaic’に格納されたFileListのすべてを使って、‘mosaic, out_transform = merge(src_files_to_mosaic, resampling=Resampling.nearest)’でmosaic画像と地理参照情報out_transformを作成する。





続く。





コメント