final 2024_Remote_Sensing
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
import sys
|
||||
import rasterio
|
||||
import numpy as np
|
||||
|
||||
def create_change_map(old_tif, new_tif, out_tif):
|
||||
"""
|
||||
Creates a change map from two classified TIFF files by:
|
||||
1. Cropping both to their overlapping extent.
|
||||
2. Encoding changes as (old_class * 10 + new_class).
|
||||
|
||||
Parameters
|
||||
----------
|
||||
old_tif : str
|
||||
Path to the old classified TIFF file.
|
||||
new_tif : str
|
||||
Path to the new classified TIFF file.
|
||||
out_tif : str
|
||||
Path to the output change map TIFF file.
|
||||
"""
|
||||
|
||||
# Open both rasters
|
||||
with rasterio.open(old_tif) as src_old, rasterio.open(new_tif) as src_new:
|
||||
|
||||
# 1) Check that both have the same CRS
|
||||
if src_old.crs != src_new.crs:
|
||||
raise ValueError("Error: Old and new rasters must have the same CRS for cropping.")
|
||||
|
||||
# 2) Check that both have the same resolution
|
||||
# (assuming square pixels; if not, adjust accordingly)
|
||||
old_res = (abs(src_old.transform.a), abs(src_old.transform.e))
|
||||
new_res = (abs(src_new.transform.a), abs(src_new.transform.e))
|
||||
if not (np.isclose(old_res[0], new_res[0]) and np.isclose(old_res[1], new_res[1])):
|
||||
raise ValueError("Error: Old and new rasters do not have the same resolution.")
|
||||
|
||||
# 3) Determine the overlapping bounding box
|
||||
left = max(src_old.bounds.left, src_new.bounds.left)
|
||||
bottom = max(src_old.bounds.bottom, src_new.bounds.bottom)
|
||||
right = min(src_old.bounds.right, src_new.bounds.right)
|
||||
top = min(src_old.bounds.top, src_new.bounds.top)
|
||||
|
||||
if left >= right or bottom >= top:
|
||||
raise ValueError("Error: The input rasters have no overlapping extent.")
|
||||
|
||||
# 4) Create windows that correspond to this overlapping area
|
||||
window_old = src_old.window(left, bottom, right, top)
|
||||
window_new = src_new.window(left, bottom, right, top)
|
||||
|
||||
# 5) Read the data from each window (single band assumed)
|
||||
old_data = src_old.read(1, window=window_old)
|
||||
new_data = src_new.read(1, window=window_new)
|
||||
|
||||
# 6) Confirm they now have the same shape after cropping
|
||||
if old_data.shape != new_data.shape:
|
||||
raise ValueError("Error: The cropped rasters do not have the same shape.")
|
||||
|
||||
# 7) Generate the change map as old_value * 10 + new_value
|
||||
change_data = old_data * 10 + new_data
|
||||
|
||||
# 8) Build the output profile
|
||||
out_transform = src_old.window_transform(window_old)
|
||||
out_profile = src_old.profile.copy()
|
||||
out_profile.update({
|
||||
'height': old_data.shape[0],
|
||||
'width': old_data.shape[1],
|
||||
'transform': out_transform,
|
||||
'dtype': rasterio.int16,
|
||||
'count': 1,
|
||||
'compress': 'lzw' # optional compression
|
||||
})
|
||||
|
||||
# 9) Write out the change map
|
||||
with rasterio.open(out_tif, 'w', **out_profile) as dst:
|
||||
dst.write(change_data.astype(rasterio.int16), 1)
|
||||
|
||||
def main():
|
||||
# Expect exactly three arguments besides the script name
|
||||
if len(sys.argv) != 4:
|
||||
print("Usage: python change_detection.py <old_classified.tif> <new_classified.tif> <out_change.tif>")
|
||||
sys.exit(1)
|
||||
|
||||
old_tif_path = sys.argv[1]
|
||||
new_tif_path = sys.argv[2]
|
||||
out_tif_path = sys.argv[3]
|
||||
|
||||
create_change_map(old_tif_path, new_tif_path, out_tif_path)
|
||||
print(f"[INFO] Change map created: {out_tif_path}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user