final 2024_Remote_Sensing

This commit is contained in:
huaqo-games
2025-02-12 19:27:51 +01:00
parent 373d194038
commit 682eef1c3e
132 changed files with 964360 additions and 20192 deletions
+89
View File
@@ -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()
+96
View File
@@ -0,0 +1,96 @@
import argparse
import rasterio
import geopandas as gpd
import numpy as np
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from rasterio.features import geometry_mask
from shapely.geometry import mapping
# Step 1: Load the Raster Data
def load_raster(raster_path):
with rasterio.open(raster_path) as src:
bands = [src.read(i) for i in range(1, src.count + 1)]
profile = src.profile
return np.stack(bands, axis=-1), profile
# Step 2: Extract Features and Labels from Training Data
def extract_training_data(raster, training_shapefile, profile):
training_labels = gpd.read_file(training_shapefile)
features = []
labels = []
for _, row in training_labels.iterrows():
class_id = row['Class'] # Ensure 'class_id' column exists in the shapefile
geom = [mapping(row['geometry'])]
mask = geometry_mask(
geom, transform=profile['transform'], invert=True, out_shape=(profile['height'], profile['width'])
)
masked_pixels = raster[mask]
features.append(masked_pixels)
labels.append(np.full(masked_pixels.shape[0], class_id))
return np.vstack(features), np.hstack(labels)
# Step 3: Train the Random Forest Classifier
def train_classifier(features, labels):
X_train, X_test, y_train, y_test = train_test_split(features, labels, test_size=0.3, random_state=42)
classifier = RandomForestClassifier(n_estimators=100, random_state=42)
classifier.fit(X_train, y_train)
y_pred = classifier.predict(X_test)
print("Classification Report:")
print(classification_report(y_test, y_pred))
return classifier
# Step 4: Classify the Entire Raster
def classify_raster(raster, classifier, profile, output_path):
rows, cols, bands = raster.shape
flattened_data = raster.reshape(-1, bands)
predictions = classifier.predict(flattened_data)
classified_image = predictions.reshape(rows, cols)
profile.update(
count=1,
dtype=rasterio.uint8,
nodata=255
)
with rasterio.open(output_path, "w", **profile) as dst:
dst.write(classified_image.astype(rasterio.uint8), 1)
return classified_image
def main():
parser = argparse.ArgumentParser(description="Random Forest classification of a raster using training shapefile.")
parser.add_argument('--raster_path', required=True, help='Path to the input raster file.')
parser.add_argument('--training_shapefile', required=True, help='Path to the training shapefile.')
parser.add_argument('--output_path', required=True, help='Path for the classified raster output.')
args = parser.parse_args()
# Load raster and metadata
print("Loading raster...")
raster, profile = load_raster(args.raster_path)
# Extract training data
print("Extracting training data...")
features, labels = extract_training_data(raster, args.training_shapefile, profile)
# Train the classifier
print("Training the classifier...")
classifier = train_classifier(features, labels)
# Classify the raster
print("Classifying the raster...")
classify_raster(raster, classifier, profile, args.output_path)
print("Classification complete. Output saved to:", args.output_path)
if __name__ == "__main__":
main()
+39
View File
@@ -0,0 +1,39 @@
import argparse
import rasterio
import numpy as np
from sklearn.cluster import KMeans
def main(input_file, output_file, n_clusters):
with rasterio.open(input_file) as src:
raster_data = src.read()
profile = src.profile
rows, cols = raster_data.shape[1], raster_data.shape[2]
raster_data_reshaped = raster_data.reshape(raster_data.shape[0], -1).T
kmeans = KMeans(n_clusters=n_clusters, random_state=0)
kmeans.fit(raster_data_reshaped)
cluster_labels = kmeans.labels_
classified_raster = cluster_labels.reshape(rows, cols)
with rasterio.open(
output_file, 'w',
driver='GTiff',
height=rows,
width=cols,
count=1,
dtype=classified_raster.dtype,
crs=src.crs,
transform=src.transform,
) as dst:
dst.write(classified_raster, 1)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Unsupervised classification for raster data.")
parser.add_argument("input_file", type=str, help="Path to the input .tif file.")
parser.add_argument("output_file", type=str, help="Path to save the classified .tif file.")
parser.add_argument("--n_clusters", type=int, default=4, help="Number of clusters for classification (default: 4).")
args = parser.parse_args()
main(args.input_file, args.output_file, args.n_clusters)
-31
View File
@@ -1,31 +0,0 @@
# Lab Assignment 1 - Cartopgraphy, Colors, and Displaying Remotely-Sensed Data
Name: Joaquin Gottlebe
Matrikelnummer: 829101
## Map 1
![](map1.png)
## Question 1
#### Data
Data: The Land Surface Temperature (LST) and Emissivity daily data are retrieved at 1km pixels by the generalized split-window algorithm and at 6km grids by the day/night algorithm. In the split-window algorithm, emissivities in bands 31 and 32 are estimated from land cover types, atmospheric column water vapor and lower boundary air surface temperature are separated into tractable sub-ranges for optimal retrieval. In the day/night algorithm, daytime and nighttime LSTs and surface emissivities are retrieved from pairs of day and night MODIS observations in seven TIR bands. The product is comprised of LSTs, quality assessment, observation time, view angles, and emissivities.
Satelite: eMODIS Global LST V6
Entity ID: EMGLSTA20220911202209206
Begin Date: 2022-09-11 00:00:00-05
End Date: 2022-09-20 00:00:00-05
Source: https://earthexplorer.usgs.gov/
#### Map
![](map2.png)
## Question 2
![](plot1.png)
-11
View File
@@ -1,11 +0,0 @@
.PHONY: all run pdf clean
PYTHON=venv/bin/python
PANDOC=pandoc
all: run pdf
run:
$(PYTHON) script.py
pdf:
$(PANDOC) Lab1.md -o rcm01_2425_lab1_gottlebe_829101.pdf
-31
View File
@@ -1,31 +0,0 @@
# Lab Assignment 2
Name: Joaquin Gottlebe
Matrikelnummer: 829101
## Question 1
![](maps/ndvi_ndwi.png)
## Question 2
![](maps/surface_temp_b10.png)
![](maps/surface_temp_b11.png)
The original Raster file included values from -125 C which are not realistic in germany. Also Maximum temperatures from 44 degrees are not common, but could be explainable through realy heat conductiv material on very small areas.
Between Water bodies and land bodies. and also the north and south of the area.
## Question 3
![](maps/true_color.png)
![](maps/false_color.png)
The main differences of the map are the Bands and their display of it. For example the true color composite consists of band 2,3 and 4 in the order of RGB as 4,3,2. The false color composite consists of band 3,4 and 5 in the order ich which Vegetation is the most visible (5,4,3).
## Question 4
![](maps/ndvi_chiloe_2013.png)
![](maps/ndvi_chiloe_2024.png)
I choose this study area because i was on this island Chiloe in Chile for a bit and noticed a lot of National parks and vegeation there and i wanted to know how this changed in these past years. These two images show difference in NDVI between 2013 and 2024 of the island Chiloe in Chile and surroundings. I chose NDVI as it shows the difference in vegetation very well.
-23
View File
@@ -1,23 +0,0 @@
.PHONY: all run_scripts
# Path to the Conda environment and scripts
CONDA_ENV_NAME = gdal_env
ACTIVATE_SCRIPT = ~/miniforge3/bin/activate
SCRIPTS = top_of_atmosphere.py ndvi.py ndwi.py
PANDOC=pandoc
all: run_scripts
run_scripts:
@echo "Activating Conda environment and running scripts..."
@source $(ACTIVATE_SCRIPT) && conda activate $(CONDA_ENV_NAME) && \
python3 toa.py data/LC08_L1TP_193023_20170602_20170615_01_T1_MTL.txt toa data/LC08_L1TP_193023_20170602_20170615_01_T1_B2.TIF data/LC08_L1TP_193023_20170602_20170615_01_T1_B4.TIF data/LC08_L1TP_193023_20170602_20170615_01_T1_B3.TIF data/LC08_L1TP_193023_20170602_20170615_01_T1_B5.TIF && \
python3 toa_radiance.py data/LC08_L1TP_193023_20170602_20170615_01_T1_MTL.txt toa_radiance data/LC08_L1TP_193023_20170602_20170615_01_T1_B10.TIF data/LC08_L1TP_193023_20170602_20170615_01_T1_B11.TIF && \
python3 ndvi.py toa/LC08_L1TP_193023_20170602_20170615_01_T1_B4_toa.TIF toa/LC08_L1TP_193023_20170602_20170615_01_T1_B5_toa.TIF ndvi && \
python3 ndwi.py toa/LC08_L1TP_193023_20170602_20170615_01_T1_B3_toa.TIF toa/LC08_L1TP_193023_20170602_20170615_01_T1_B5_toa.TIF ndwi && \
python3 surface_temperature.py data/LC08_L1TP_193023_20170602_20170615_01_T1_MTL.txt toa_radiance/LC08_L1TP_193023_20170602_20170615_01_T1_B10_toa_radiance.TIF toa_radiance/LC08_L1TP_193023_20170602_20170615_01_T1_B11_toa_radiance.TIF surface_temperature && \
python3 toa.py data2/LC08_L1TP_233089_20131224_20200912_02_T1_MTL.txt toa2 data2/LC08_L1TP_233089_20131224_20200912_02_T1_B2.TIF data2/LC08_L1TP_233089_20131224_20200912_02_T1_B4.TIF data2/LC08_L1TP_233089_20131224_20200912_02_T1_B3.TIF data2/LC08_L1TP_233089_20131224_20200912_02_T1_B5.TIF && \
python3 toa.py data3/LC08_L1TP_233089_20240410_20240419_02_T1_MTL.txt toa3 data3/LC08_L1TP_233089_20240410_20240419_02_T1_B2.TIF data3/LC08_L1TP_233089_20240410_20240419_02_T1_B4.TIF data3/LC08_L1TP_233089_20240410_20240419_02_T1_B3.TIF data3/LC08_L1TP_233089_20240410_20240419_02_T1_B5.TIF && \
python3 ndvi.py toa2/LC08_L1TP_233089_20131224_20200912_02_T1_B4_toa.TIF toa2/LC08_L1TP_233089_20131224_20200912_02_T1_B5_toa.TIF ndvi2 && \
python3 ndvi.py toa3/LC08_L1TP_233089_20240410_20240419_02_T1_B4_toa.TIF toa3/LC08_L1TP_233089_20240410_20240419_02_T1_B5_toa.TIF ndvi3 && \
$(PANDOC) Lab2.md -o rcm01_2425_lab2_gottlebe_829101.pdf
-119
View File
@@ -1,119 +0,0 @@
# Cleanup
project = QgsProject.instance()
layer_ids = list(project.mapLayers().keys())
for layer_id in layer_ids:
project.removeMapLayer(layer_id)
# Loading B10 Layer
path_st_b10 = "/home/huaqo/dev/courses/2024_Remote_Sensing/lab2/false_color/false_color.tif"
st_b10_layer = QgsRasterLayer(path_st_b10, "False Color Composite")
if not st_b10_layer.isValid():
print("st_b10 layer failed to load!")
else:
QgsProject.instance().addMapLayer(st_b10_layer)
print("st_b10 Layer loaded!")
# Styling Layer
st_b10_style_path = '/home/huaqo/dev/courses/2024_Remote_Sensing/styles/false_color.qml'
if not st_b10_layer.loadNamedStyle(st_b10_style_path):
print("Failed to load st_b10 style!")
else:
print("st_b10 style loaded!")
# Load layout
layout = QgsPrintLayout(project)
layout.initializeDefaults()
# Map
map_item = QgsLayoutItemMap(layout)
map_item.attemptMove(QgsLayoutPoint(20, 30, QgsUnitTypes.LayoutMillimeters)) # Added space between top and map
map_item.attemptResize(QgsLayoutSize(200, 150, QgsUnitTypes.LayoutMillimeters)) # Reduced height for better spacing
map_item.zoomToExtent(st_b10_layer.extent())
layout.addLayoutItem(map_item)
# Add Coordinate Grid
grid = map_item.grid()
grid.setEnabled(True)
grid.setIntervalX(100000) # Set interval for grid lines in map units
grid.setIntervalY(100000)
grid.setAnnotationEnabled(True)
grid.setAnnotationPrecision(0) # Set annotation precision for grid labels
grid.setFrameStyle(QgsLayoutItemMapGrid.Zebra) # Optional grid style
# Label
title_label = QgsLayoutItemLabel(layout)
title_label.setText("False Color Composite - Lab 2")
title_label.setFont(QFont("Arial", 16))
title_label.setHAlign(Qt.AlignCenter)
title_label.attemptMove(QgsLayoutPoint(105, 10, QgsUnitTypes.LayoutMillimeters))
title_label.adjustSizeToText()
layout.addLayoutItem(title_label)
# Legend
legend_item = QgsLayoutItemLegend(layout)
legend_item.setLinkedMap(map_item)
legend_item.setTitle("Legend")
legend_item.setFrameEnabled(True)
legend_item.attemptMove(QgsLayoutPoint(245, 30, QgsUnitTypes.LayoutMillimeters)) # Adjusted for better alignment and spacing
layout.addLayoutItem(legend_item)
# Scalebar
scalebar_item = QgsLayoutItemScaleBar(layout)
scalebar_item.setStyle('Single Box') # Change to 'Single Box' or 'Double Box' for a proper scalebar
scalebar_item.setLinkedMap(map_item)
scalebar_item.setUnitLabel('m') # Add unit label to make it informative
scalebar_item.setNumberOfSegments(4) # Specify the number of segments in the scalebar
scalebar_item.setNumberOfSegmentsLeft(0) # Segments to the left of zero (if any)
scalebar_item.setUnitsPerSegment(50000) # Set distance per segment in map units
scalebar_item.setFont(QFont('Arial', 10)) # Set font size for better readability
scalebar_item.setHeight(5) # Set the height of the scalebar
scalebar_item.applyDefaultSize()
scalebar_item.attemptMove(QgsLayoutPoint(20, 190, QgsUnitTypes.LayoutMillimeters)) # Moved below the map for better organization
layout.addLayoutItem(scalebar_item)
# North Arrow
north_arrow_item = QgsLayoutItemPicture(layout)
north_arrow_item.setPicturePath('/home/huaqo/dev/courses/2024_Remote_Sensing/styles/north_arrow.svg')
if not north_arrow_item.picturePath():
print("North arrow image failed to load!")
north_arrow_item.setReferencePoint(QgsLayoutItemPicture.UpperLeft)
north_arrow_item.attemptMove(QgsLayoutPoint(30, 40, QgsUnitTypes.LayoutMillimeters)) # Adjusted placement for better visibility
north_arrow_item.attemptResize(QgsLayoutSize(15, 15, QgsUnitTypes.LayoutMillimeters)) # Increased size for better visibility
layout.addLayoutItem(north_arrow_item)
# Author
info_label = QgsLayoutItemLabel(layout)
info_label.setText("Author: Joaquin Gottlebe")
info_label.setFont(QFont("Arial", 12))
info_label.setHAlign(Qt.AlignLeft)
info_label.attemptMove(QgsLayoutPoint(245, 100, QgsUnitTypes.LayoutMillimeters))
info_label.adjustSizeToText()
layout.addLayoutItem(info_label)
# Author
info_label = QgsLayoutItemLabel(layout)
info_label.setText("Date: 16.11.2025")
info_label.setFont(QFont("Arial", 12))
info_label.setHAlign(Qt.AlignLeft)
info_label.attemptMove(QgsLayoutPoint(245, 110, QgsUnitTypes.LayoutMillimeters))
info_label.adjustSizeToText()
layout.addLayoutItem(info_label)
# Coordinate System
info_label = QgsLayoutItemLabel(layout)
info_label.setText("CRS: EPSG 32633")
info_label.setFont(QFont("Arial", 12))
info_label.setHAlign(Qt.AlignLeft)
info_label.attemptMove(QgsLayoutPoint(245, 120, QgsUnitTypes.LayoutMillimeters))
info_label.adjustSizeToText()
layout.addLayoutItem(info_label)
# Export
export_path = "/home/huaqo/dev/courses/2024_Remote_Sensing/lab2/maps/false_color.png"
exporter = QgsLayoutExporter(layout)
export_result = exporter.exportToImage(export_path, QgsLayoutExporter.ImageExportSettings())
if export_result != QgsLayoutExporter.Success:
print("Failed to export map!")
else:
print("Map exported to:", export_path)
-73
View File
@@ -1,73 +0,0 @@
from osgeo import gdal
import numpy as np
import sys
import os
import re
def tif_to_array(path):
data = gdal.Open(path)
if data is None:
raise FileNotFoundError(f"Cannot open file: {path}")
band = data.GetRasterBand(1)
array = band.ReadAsArray().astype(np.float32)
return data, array
def handle_nodata(array):
clean_array = np.where((array < 0) | (array > 1), np.nan, array)
return clean_array
def ndvi_calc(NIR,RED):
ndvi_array = (NIR - RED) / (NIR + RED + 1e-10)
return ndvi_array
def save_tif(array,data,output_path):
driver = gdal.GetDriverByName('GTiff')
rows, cols = array.shape
out_data = driver.Create(output_path, cols, rows, 1, gdal.GDT_Float32)
out_data.SetGeoTransform(data.GetGeoTransform())
out_data.SetProjection(data.GetProjection())
out_band = out_data.GetRasterBand(1)
out_band.WriteArray(array)
out_band.SetNoDataValue(-9999)
out_band.FlushCache()
out_data = None
def get_output_path(output_dir,input_path):
basename = os.path.basename(input_path)
basename_no_ext = os.path.splitext(basename)[0]
basename_no_ext = re.sub(r'_B[1-9]|_B10|_B11', '', basename_no_ext)
path = os.path.join(output_dir, f"{basename_no_ext}_ndvi.TIF")
return path
def print_min_max(array, label):
print(label," Min:", np.nanmin(array), " Max:",np.nanmax(array))
def main():
if len(sys.argv) != 4:
print("Usage: python3 script.py <red_band_path> <nir_band_path> <output_directory>")
sys.exit(1)
red_path = sys.argv[1]
nir_path = sys.argv[2]
output_dir = sys.argv[3]
red_data, red_array = tif_to_array(red_path)
nir_data, nir_array = tif_to_array(nir_path)
red_array = handle_nodata(red_array)
nir_array = handle_nodata(nir_array)
ndvi_array = ndvi_calc(nir_array, red_array)
if not os.path.exists(output_dir):
os.makedirs(output_dir)
output_path = get_output_path(output_dir,red_path)
save_tif(ndvi_array, red_data, output_path)
print_min_max(red_array, "RED")
print_min_max(nir_array, "NIR")
print_min_max(ndvi_array, "NDVI")
if __name__ == "__main__":
main()
-119
View File
@@ -1,119 +0,0 @@
# Cleanup
project = QgsProject.instance()
layer_ids = list(project.mapLayers().keys())
for layer_id in layer_ids:
project.removeMapLayer(layer_id)
# Loading NDVI Layer
path_ndvi = "/home/huaqo/dev/courses/2024_Remote_Sensing/lab2/ndvi3/LC08_L1TP_233089_20240410_20240419_02_T1_toa_ndvi.TIF"
ndvi_layer = QgsRasterLayer(path_ndvi, "NDVI")
if not ndvi_layer.isValid():
print("NDVI layer failed to load!")
else:
QgsProject.instance().addMapLayer(ndvi_layer)
print("NDVI Layer loaded!")
# Styling NDVI Layer
ndvi_style_path = '/home/huaqo/dev/courses/2024_Remote_Sensing/styles/ndvi.qml'
if not ndvi_layer.loadNamedStyle(ndvi_style_path):
print("Failed to load NDVI style!")
else:
print("NDVI style loaded!")
# Load layout
layout = QgsPrintLayout(project)
layout.initializeDefaults()
# Map
map_item = QgsLayoutItemMap(layout)
map_item.attemptMove(QgsLayoutPoint(20, 30, QgsUnitTypes.LayoutMillimeters)) # Added space between top and map
map_item.attemptResize(QgsLayoutSize(200, 150, QgsUnitTypes.LayoutMillimeters)) # Reduced height for better spacing
map_item.zoomToExtent(ndvi_layer.extent())
layout.addLayoutItem(map_item)
# Add Coordinate Grid
grid = map_item.grid()
grid.setEnabled(True)
grid.setIntervalX(100000) # Set interval for grid lines in map units
grid.setIntervalY(100000)
grid.setAnnotationEnabled(True)
grid.setAnnotationPrecision(0) # Set annotation precision for grid labels
grid.setFrameStyle(QgsLayoutItemMapGrid.Zebra) # Optional grid style
# Label
title_label = QgsLayoutItemLabel(layout)
title_label.setText("NDVI Chiloe 2024 - Lab 2")
title_label.setFont(QFont("Arial", 16))
title_label.setHAlign(Qt.AlignCenter)
title_label.attemptMove(QgsLayoutPoint(105, 10, QgsUnitTypes.LayoutMillimeters))
title_label.adjustSizeToText()
layout.addLayoutItem(title_label)
# Legend
legend_item = QgsLayoutItemLegend(layout)
legend_item.setLinkedMap(map_item)
legend_item.setTitle("Legend")
legend_item.setFrameEnabled(True)
legend_item.attemptMove(QgsLayoutPoint(245, 30, QgsUnitTypes.LayoutMillimeters)) # Adjusted for better alignment and spacing
layout.addLayoutItem(legend_item)
# Scalebar
scalebar_item = QgsLayoutItemScaleBar(layout)
scalebar_item.setStyle('Single Box') # Change to 'Single Box' or 'Double Box' for a proper scalebar
scalebar_item.setLinkedMap(map_item)
scalebar_item.setUnitLabel('m') # Add unit label to make it informative
scalebar_item.setNumberOfSegments(4) # Specify the number of segments in the scalebar
scalebar_item.setNumberOfSegmentsLeft(0) # Segments to the left of zero (if any)
scalebar_item.setUnitsPerSegment(50000) # Set distance per segment in map units
scalebar_item.setFont(QFont('Arial', 10)) # Set font size for better readability
scalebar_item.setHeight(5) # Set the height of the scalebar
scalebar_item.applyDefaultSize()
scalebar_item.attemptMove(QgsLayoutPoint(20, 190, QgsUnitTypes.LayoutMillimeters)) # Moved below the map for better organization
layout.addLayoutItem(scalebar_item)
# North Arrow
north_arrow_item = QgsLayoutItemPicture(layout)
north_arrow_item.setPicturePath('/home/huaqo/dev/courses/2024_Remote_Sensing/styles/north_arrow.svg')
if not north_arrow_item.picturePath():
print("North arrow image failed to load!")
north_arrow_item.setReferencePoint(QgsLayoutItemPicture.UpperLeft)
north_arrow_item.attemptMove(QgsLayoutPoint(30, 40, QgsUnitTypes.LayoutMillimeters)) # Adjusted placement for better visibility
north_arrow_item.attemptResize(QgsLayoutSize(15, 15, QgsUnitTypes.LayoutMillimeters)) # Increased size for better visibility
layout.addLayoutItem(north_arrow_item)
# Author
info_label = QgsLayoutItemLabel(layout)
info_label.setText("Author: Joaquin Gottlebe")
info_label.setFont(QFont("Arial", 12))
info_label.setHAlign(Qt.AlignLeft)
info_label.attemptMove(QgsLayoutPoint(245, 100, QgsUnitTypes.LayoutMillimeters))
info_label.adjustSizeToText()
layout.addLayoutItem(info_label)
# Author
info_label = QgsLayoutItemLabel(layout)
info_label.setText("Date: 16.11.2025")
info_label.setFont(QFont("Arial", 12))
info_label.setHAlign(Qt.AlignLeft)
info_label.attemptMove(QgsLayoutPoint(245, 110, QgsUnitTypes.LayoutMillimeters))
info_label.adjustSizeToText()
layout.addLayoutItem(info_label)
# Coordinate System
info_label = QgsLayoutItemLabel(layout)
info_label.setText("CRS: EPSG 32633")
info_label.setFont(QFont("Arial", 12))
info_label.setHAlign(Qt.AlignLeft)
info_label.attemptMove(QgsLayoutPoint(245, 120, QgsUnitTypes.LayoutMillimeters))
info_label.adjustSizeToText()
layout.addLayoutItem(info_label)
# Export
export_path = "/home/huaqo/dev/courses/2024_Remote_Sensing/lab2/maps/ndvi_chiloe_2024.png"
exporter = QgsLayoutExporter(layout)
export_result = exporter.exportToImage(export_path, QgsLayoutExporter.ImageExportSettings())
if export_result != QgsLayoutExporter.Success:
print("Failed to export map!")
else:
print("Map exported to:", export_path)
-139
View File
@@ -1,139 +0,0 @@
# Cleanup
project = QgsProject.instance()
layer_ids = list(project.mapLayers().keys())
for layer_id in layer_ids:
project.removeMapLayer(layer_id)
# Loading NDVI Layer
path_ndvi = "/home/huaqo/dev/courses/2024_Remote_Sensing/lab2/ndvi/LC08_L1TP_193023_20170602_20170615_01_T1_toa_ndvi.TIF"
ndvi_layer = QgsRasterLayer(path_ndvi, "NDVI")
if not ndvi_layer.isValid():
print("NDVI layer failed to load!")
else:
QgsProject.instance().addMapLayer(ndvi_layer)
print("NDVI Layer loaded!")
# Loading Additional Layer
path_overlay = "/home/huaqo/dev/courses/2024_Remote_Sensing/lab2/ndwi/LC08_L1TP_193023_20170602_20170615_01_T1_toa_ndwi.TIF" # Replace with your actual layer path
ndwi_layer = QgsRasterLayer(path_overlay, "NDWI")
if not ndwi_layer.isValid():
print("NDWI layer failed to load!")
else:
QgsProject.instance().addMapLayer(ndwi_layer)
print("NDWI Layer loaded!")
# Styling NDVI Layer
ndvi_style_path = '/home/huaqo/dev/courses/2024_Remote_Sensing/styles/ndvi.qml'
if not ndvi_layer.loadNamedStyle(ndvi_style_path):
print("Failed to load NDVI style!")
else:
print("NDVI style loaded!")
ndwi_style_path = '/home/huaqo/dev/courses/2024_Remote_Sensing/styles/ndwi.qml'
if not ndwi_layer.loadNamedStyle(ndwi_style_path):
print("Failed to load NDWI style!")
else:
print("NDWI style loaded!")
# Reference system (optional, uncomment if needed)
# crs = QgsCoordinateReferenceSystem("EPSG:4326")
# crsSrc = QgsCoordinateReferenceSystem("EPSG:32633")
# crsDest = QgsCoordinateReferenceSystem("EPSG:4326")
# Load layout
layout = QgsPrintLayout(project)
layout.initializeDefaults()
# Map
map_item = QgsLayoutItemMap(layout)
map_item.attemptMove(QgsLayoutPoint(20, 30, QgsUnitTypes.LayoutMillimeters)) # Added space between top and map
map_item.attemptResize(QgsLayoutSize(200, 150, QgsUnitTypes.LayoutMillimeters)) # Reduced height for better spacing
map_item.zoomToExtent(ndvi_layer.extent())
layout.addLayoutItem(map_item)
# Add Coordinate Grid
grid = map_item.grid()
grid.setEnabled(True)
grid.setIntervalX(100000) # Set interval for grid lines in map units
grid.setIntervalY(100000)
grid.setAnnotationEnabled(True)
grid.setAnnotationPrecision(0) # Set annotation precision for grid labels
grid.setFrameStyle(QgsLayoutItemMapGrid.Zebra) # Optional grid style
# Label
title_label = QgsLayoutItemLabel(layout)
title_label.setText("NDVI & NDWI - Lab 2")
title_label.setFont(QFont("Arial", 16))
title_label.setHAlign(Qt.AlignCenter)
title_label.attemptMove(QgsLayoutPoint(105, 10, QgsUnitTypes.LayoutMillimeters))
title_label.adjustSizeToText()
layout.addLayoutItem(title_label)
# Legend
legend_item = QgsLayoutItemLegend(layout)
legend_item.setLinkedMap(map_item)
legend_item.setTitle("Legend")
legend_item.setFrameEnabled(True)
legend_item.attemptMove(QgsLayoutPoint(245, 30, QgsUnitTypes.LayoutMillimeters)) # Adjusted for better alignment and spacing
layout.addLayoutItem(legend_item)
# Scalebar
scalebar_item = QgsLayoutItemScaleBar(layout)
scalebar_item.setStyle('Single Box') # Change to 'Single Box' or 'Double Box' for a proper scalebar
scalebar_item.setLinkedMap(map_item)
scalebar_item.setUnitLabel('m') # Add unit label to make it informative
scalebar_item.setNumberOfSegments(4) # Specify the number of segments in the scalebar
scalebar_item.setNumberOfSegmentsLeft(0) # Segments to the left of zero (if any)
scalebar_item.setUnitsPerSegment(50000) # Set distance per segment in map units
scalebar_item.setFont(QFont('Arial', 10)) # Set font size for better readability
scalebar_item.setHeight(5) # Set the height of the scalebar
scalebar_item.applyDefaultSize()
scalebar_item.attemptMove(QgsLayoutPoint(20, 190, QgsUnitTypes.LayoutMillimeters)) # Moved below the map for better organization
layout.addLayoutItem(scalebar_item)
# North Arrow
north_arrow_item = QgsLayoutItemPicture(layout)
north_arrow_item.setPicturePath('/home/huaqo/dev/courses/2024_Remote_Sensing/styles/north_arrow.svg')
if not north_arrow_item.picturePath():
print("North arrow image failed to load!")
north_arrow_item.setReferencePoint(QgsLayoutItemPicture.UpperLeft)
north_arrow_item.attemptMove(QgsLayoutPoint(30, 40, QgsUnitTypes.LayoutMillimeters)) # Adjusted placement for better visibility
north_arrow_item.attemptResize(QgsLayoutSize(15, 15, QgsUnitTypes.LayoutMillimeters)) # Increased size for better visibility
layout.addLayoutItem(north_arrow_item)
# Author
info_label = QgsLayoutItemLabel(layout)
info_label.setText("Author: Joaquin Gottlebe")
info_label.setFont(QFont("Arial", 12))
info_label.setHAlign(Qt.AlignLeft)
info_label.attemptMove(QgsLayoutPoint(245, 100, QgsUnitTypes.LayoutMillimeters))
info_label.adjustSizeToText()
layout.addLayoutItem(info_label)
# Author
info_label = QgsLayoutItemLabel(layout)
info_label.setText("Date: 16.11.2025")
info_label.setFont(QFont("Arial", 12))
info_label.setHAlign(Qt.AlignLeft)
info_label.attemptMove(QgsLayoutPoint(245, 110, QgsUnitTypes.LayoutMillimeters))
info_label.adjustSizeToText()
layout.addLayoutItem(info_label)
# Coordinate System
info_label = QgsLayoutItemLabel(layout)
info_label.setText("CRS: EPSG 32633")
info_label.setFont(QFont("Arial", 12))
info_label.setHAlign(Qt.AlignLeft)
info_label.attemptMove(QgsLayoutPoint(245, 120, QgsUnitTypes.LayoutMillimeters))
info_label.adjustSizeToText()
layout.addLayoutItem(info_label)
# Export
export_path = "/home/huaqo/dev/courses/2024_Remote_Sensing/lab2/maps/ndvi_ndwi.png"
exporter = QgsLayoutExporter(layout)
export_result = exporter.exportToImage(export_path, QgsLayoutExporter.ImageExportSettings())
if export_result != QgsLayoutExporter.Success:
print("Failed to export map!")
else:
print("Map exported to:", export_path)
-81
View File
@@ -1,81 +0,0 @@
from osgeo import gdal
import numpy as np
import sys
import os
import re
def tif_to_array(path):
data = gdal.Open(path)
if data is None:
raise FileNotFoundError(f"Cannot open file: {path}")
band = data.GetRasterBand(1)
array = band.ReadAsArray().astype(np.float32)
return data, array
def handle_nodata(array):
clean_array = np.where((array < 0) | (array > 1), np.nan, array)
return clean_array
def ndwi_calc(GREEN, NIR):
ndwi_array = (GREEN - NIR) / (GREEN + NIR + 1e-10)
return ndwi_array
def save_tif(array, data, output_path):
driver = gdal.GetDriverByName('GTiff')
rows, cols = array.shape
out_data = driver.Create(output_path, cols, rows, 1, gdal.GDT_Float32)
out_data.SetGeoTransform(data.GetGeoTransform())
out_data.SetProjection(data.GetProjection())
out_band = out_data.GetRasterBand(1)
out_band.WriteArray(array)
out_band.SetNoDataValue(-9999)
out_band.FlushCache()
out_data = None
def get_output_path(output_dir, input_path):
basename = os.path.basename(input_path)
basename_no_ext = os.path.splitext(basename)[0]
basename_no_ext = re.sub(r'_B[1-9]|_B10|_B11', '', basename_no_ext)
path = os.path.join(output_dir, f"{basename_no_ext}_ndwi.TIF")
return path
def print_min_max(array, label):
print(label, " Min:", np.nanmin(array), " Max:", np.nanmax(array))
def main():
if len(sys.argv) != 4:
print("Usage: python3 script.py <green_band_path> <nir_band_path> <output_directory>")
sys.exit(1)
green_path = sys.argv[1]
nir_path = sys.argv[2]
output_dir = sys.argv[3]
green_data, green_array = tif_to_array(green_path)
nir_data, nir_array = tif_to_array(nir_path)
green_array = handle_nodata(green_array)
nir_array = handle_nodata(nir_array)
ndwi_array = ndwi_calc(green_array, nir_array)
if not os.path.exists(output_dir):
os.makedirs(output_dir)
output_path = get_output_path(output_dir, green_path)
save_tif(ndwi_array, green_data, output_path)
print_min_max(nir_array, "NIR")
print_min_max(green_array, "GREEN")
print_min_max(ndwi_array, "NDWI")
if __name__ == "__main__":
main()
@@ -1,119 +0,0 @@
# Cleanup
project = QgsProject.instance()
layer_ids = list(project.mapLayers().keys())
for layer_id in layer_ids:
project.removeMapLayer(layer_id)
# Loading B10 Layer
path_st_b10 = "/home/huaqo/dev/courses/2024_Remote_Sensing/lab2/surface_temperature/LC08_L1TP_193023_20170602_20170615_01_T1_B11_toa_radiance_surfacetemp.TIF"
st_b10_layer = QgsRasterLayer(path_st_b10, "Surf. Temp. B11")
if not st_b10_layer.isValid():
print("st_b10 layer failed to load!")
else:
QgsProject.instance().addMapLayer(st_b10_layer)
print("st_b10 Layer loaded!")
# Styling Layer
st_b10_style_path = '/home/huaqo/dev/courses/2024_Remote_Sensing/styles/surface_temperature.qml'
if not st_b10_layer.loadNamedStyle(st_b10_style_path):
print("Failed to load st_b10 style!")
else:
print("st_b10 style loaded!")
# Load layout
layout = QgsPrintLayout(project)
layout.initializeDefaults()
# Map
map_item = QgsLayoutItemMap(layout)
map_item.attemptMove(QgsLayoutPoint(20, 30, QgsUnitTypes.LayoutMillimeters)) # Added space between top and map
map_item.attemptResize(QgsLayoutSize(200, 150, QgsUnitTypes.LayoutMillimeters)) # Reduced height for better spacing
map_item.zoomToExtent(st_b10_layer.extent())
layout.addLayoutItem(map_item)
# Add Coordinate Grid
grid = map_item.grid()
grid.setEnabled(True)
grid.setIntervalX(100000) # Set interval for grid lines in map units
grid.setIntervalY(100000)
grid.setAnnotationEnabled(True)
grid.setAnnotationPrecision(0) # Set annotation precision for grid labels
grid.setFrameStyle(QgsLayoutItemMapGrid.Zebra) # Optional grid style
# Label
title_label = QgsLayoutItemLabel(layout)
title_label.setText("Surace Temperautre B11 - Lab 2")
title_label.setFont(QFont("Arial", 16))
title_label.setHAlign(Qt.AlignCenter)
title_label.attemptMove(QgsLayoutPoint(105, 10, QgsUnitTypes.LayoutMillimeters))
title_label.adjustSizeToText()
layout.addLayoutItem(title_label)
# Legend
legend_item = QgsLayoutItemLegend(layout)
legend_item.setLinkedMap(map_item)
legend_item.setTitle("Legend")
legend_item.setFrameEnabled(True)
legend_item.attemptMove(QgsLayoutPoint(245, 30, QgsUnitTypes.LayoutMillimeters)) # Adjusted for better alignment and spacing
layout.addLayoutItem(legend_item)
# Scalebar
scalebar_item = QgsLayoutItemScaleBar(layout)
scalebar_item.setStyle('Single Box') # Change to 'Single Box' or 'Double Box' for a proper scalebar
scalebar_item.setLinkedMap(map_item)
scalebar_item.setUnitLabel('m') # Add unit label to make it informative
scalebar_item.setNumberOfSegments(4) # Specify the number of segments in the scalebar
scalebar_item.setNumberOfSegmentsLeft(0) # Segments to the left of zero (if any)
scalebar_item.setUnitsPerSegment(50000) # Set distance per segment in map units
scalebar_item.setFont(QFont('Arial', 10)) # Set font size for better readability
scalebar_item.setHeight(5) # Set the height of the scalebar
scalebar_item.applyDefaultSize()
scalebar_item.attemptMove(QgsLayoutPoint(20, 190, QgsUnitTypes.LayoutMillimeters)) # Moved below the map for better organization
layout.addLayoutItem(scalebar_item)
# North Arrow
north_arrow_item = QgsLayoutItemPicture(layout)
north_arrow_item.setPicturePath('/home/huaqo/dev/courses/2024_Remote_Sensing/styles/north_arrow.svg')
if not north_arrow_item.picturePath():
print("North arrow image failed to load!")
north_arrow_item.setReferencePoint(QgsLayoutItemPicture.UpperLeft)
north_arrow_item.attemptMove(QgsLayoutPoint(30, 40, QgsUnitTypes.LayoutMillimeters)) # Adjusted placement for better visibility
north_arrow_item.attemptResize(QgsLayoutSize(15, 15, QgsUnitTypes.LayoutMillimeters)) # Increased size for better visibility
layout.addLayoutItem(north_arrow_item)
# Author
info_label = QgsLayoutItemLabel(layout)
info_label.setText("Author: Joaquin Gottlebe")
info_label.setFont(QFont("Arial", 12))
info_label.setHAlign(Qt.AlignLeft)
info_label.attemptMove(QgsLayoutPoint(245, 100, QgsUnitTypes.LayoutMillimeters))
info_label.adjustSizeToText()
layout.addLayoutItem(info_label)
# Author
info_label = QgsLayoutItemLabel(layout)
info_label.setText("Date: 16.11.2025")
info_label.setFont(QFont("Arial", 12))
info_label.setHAlign(Qt.AlignLeft)
info_label.attemptMove(QgsLayoutPoint(245, 110, QgsUnitTypes.LayoutMillimeters))
info_label.adjustSizeToText()
layout.addLayoutItem(info_label)
# Coordinate System
info_label = QgsLayoutItemLabel(layout)
info_label.setText("CRS: EPSG 32633")
info_label.setFont(QFont("Arial", 12))
info_label.setHAlign(Qt.AlignLeft)
info_label.attemptMove(QgsLayoutPoint(245, 120, QgsUnitTypes.LayoutMillimeters))
info_label.adjustSizeToText()
layout.addLayoutItem(info_label)
# Export
export_path = "/home/huaqo/dev/courses/2024_Remote_Sensing/lab2/maps/surface_temp_b11.png"
exporter = QgsLayoutExporter(layout)
export_result = exporter.exportToImage(export_path, QgsLayoutExporter.ImageExportSettings())
if export_result != QgsLayoutExporter.Success:
print("Failed to export map!")
else:
print("Map exported to:", export_path)
-119
View File
@@ -1,119 +0,0 @@
# Cleanup
project = QgsProject.instance()
layer_ids = list(project.mapLayers().keys())
for layer_id in layer_ids:
project.removeMapLayer(layer_id)
# Loading B10 Layer
path_st_b10 = "/home/huaqo/dev/courses/2024_Remote_Sensing/lab2/true_color/true_color.tif"
st_b10_layer = QgsRasterLayer(path_st_b10, "True Color Composite")
if not st_b10_layer.isValid():
print("st_b10 layer failed to load!")
else:
QgsProject.instance().addMapLayer(st_b10_layer)
print("st_b10 Layer loaded!")
# Styling Layer
st_b10_style_path = '/home/huaqo/dev/courses/2024_Remote_Sensing/styles/true_color.qml'
if not st_b10_layer.loadNamedStyle(st_b10_style_path):
print("Failed to load st_b10 style!")
else:
print("st_b10 style loaded!")
# Load layout
layout = QgsPrintLayout(project)
layout.initializeDefaults()
# Map
map_item = QgsLayoutItemMap(layout)
map_item.attemptMove(QgsLayoutPoint(20, 30, QgsUnitTypes.LayoutMillimeters)) # Added space between top and map
map_item.attemptResize(QgsLayoutSize(200, 150, QgsUnitTypes.LayoutMillimeters)) # Reduced height for better spacing
map_item.zoomToExtent(st_b10_layer.extent())
layout.addLayoutItem(map_item)
# Add Coordinate Grid
grid = map_item.grid()
grid.setEnabled(True)
grid.setIntervalX(100000) # Set interval for grid lines in map units
grid.setIntervalY(100000)
grid.setAnnotationEnabled(True)
grid.setAnnotationPrecision(0) # Set annotation precision for grid labels
grid.setFrameStyle(QgsLayoutItemMapGrid.Zebra) # Optional grid style
# Label
title_label = QgsLayoutItemLabel(layout)
title_label.setText("True Color Composite - Lab 2")
title_label.setFont(QFont("Arial", 16))
title_label.setHAlign(Qt.AlignCenter)
title_label.attemptMove(QgsLayoutPoint(105, 10, QgsUnitTypes.LayoutMillimeters))
title_label.adjustSizeToText()
layout.addLayoutItem(title_label)
# Legend
legend_item = QgsLayoutItemLegend(layout)
legend_item.setLinkedMap(map_item)
legend_item.setTitle("Legend")
legend_item.setFrameEnabled(True)
legend_item.attemptMove(QgsLayoutPoint(245, 30, QgsUnitTypes.LayoutMillimeters)) # Adjusted for better alignment and spacing
layout.addLayoutItem(legend_item)
# Scalebar
scalebar_item = QgsLayoutItemScaleBar(layout)
scalebar_item.setStyle('Single Box') # Change to 'Single Box' or 'Double Box' for a proper scalebar
scalebar_item.setLinkedMap(map_item)
scalebar_item.setUnitLabel('m') # Add unit label to make it informative
scalebar_item.setNumberOfSegments(4) # Specify the number of segments in the scalebar
scalebar_item.setNumberOfSegmentsLeft(0) # Segments to the left of zero (if any)
scalebar_item.setUnitsPerSegment(50000) # Set distance per segment in map units
scalebar_item.setFont(QFont('Arial', 10)) # Set font size for better readability
scalebar_item.setHeight(5) # Set the height of the scalebar
scalebar_item.applyDefaultSize()
scalebar_item.attemptMove(QgsLayoutPoint(20, 190, QgsUnitTypes.LayoutMillimeters)) # Moved below the map for better organization
layout.addLayoutItem(scalebar_item)
# North Arrow
north_arrow_item = QgsLayoutItemPicture(layout)
north_arrow_item.setPicturePath('/home/huaqo/dev/courses/2024_Remote_Sensing/styles/north_arrow.svg')
if not north_arrow_item.picturePath():
print("North arrow image failed to load!")
north_arrow_item.setReferencePoint(QgsLayoutItemPicture.UpperLeft)
north_arrow_item.attemptMove(QgsLayoutPoint(30, 40, QgsUnitTypes.LayoutMillimeters)) # Adjusted placement for better visibility
north_arrow_item.attemptResize(QgsLayoutSize(15, 15, QgsUnitTypes.LayoutMillimeters)) # Increased size for better visibility
layout.addLayoutItem(north_arrow_item)
# Author
info_label = QgsLayoutItemLabel(layout)
info_label.setText("Author: Joaquin Gottlebe")
info_label.setFont(QFont("Arial", 12))
info_label.setHAlign(Qt.AlignLeft)
info_label.attemptMove(QgsLayoutPoint(245, 100, QgsUnitTypes.LayoutMillimeters))
info_label.adjustSizeToText()
layout.addLayoutItem(info_label)
# Author
info_label = QgsLayoutItemLabel(layout)
info_label.setText("Date: 16.11.2025")
info_label.setFont(QFont("Arial", 12))
info_label.setHAlign(Qt.AlignLeft)
info_label.attemptMove(QgsLayoutPoint(245, 110, QgsUnitTypes.LayoutMillimeters))
info_label.adjustSizeToText()
layout.addLayoutItem(info_label)
# Coordinate System
info_label = QgsLayoutItemLabel(layout)
info_label.setText("CRS: EPSG 32633")
info_label.setFont(QFont("Arial", 12))
info_label.setHAlign(Qt.AlignLeft)
info_label.attemptMove(QgsLayoutPoint(245, 120, QgsUnitTypes.LayoutMillimeters))
info_label.adjustSizeToText()
layout.addLayoutItem(info_label)
# Export
export_path = "/home/huaqo/dev/courses/2024_Remote_Sensing/lab2/maps/true_color.png"
exporter = QgsLayoutExporter(layout)
export_result = exporter.exportToImage(export_path, QgsLayoutExporter.ImageExportSettings())
if export_result != QgsLayoutExporter.Success:
print("Failed to export map!")
else:
print("Map exported to:", export_path)
-27
View File
@@ -1,27 +0,0 @@
# Lab 3
Name: Joaquin Gottlebe
Matrikelnummer: 829101
## Question 1
![](maps/ndwi.png)
## Question 2
![](maps/diff_ndwi.png)
![](plots/diff_hist.png)
Landsat 8 uses broader NIR and Green bands with a 30m resolution, while Sentinel-2 uses narrower bands with a 10m resolution. Differences in atmospheric correction methods and time of capture could also be factors.
## Question 3
For the third question i choose the Chacao Channel as it is also a very interesting region because of its national parks agriculture and abundance of waterbodies.
![](maps/ndvi2.png)
![](maps/ndwi2.png)
Here the symbology was reduced to 0-0.2 because the calculations resultet in a peak around this area and near to zero values till 1. Which doenst make much sense because the area has a lot of waterbodies. I couldnt find and error.
-44
View File
@@ -1,44 +0,0 @@
.PHONY: all preproc1 preproc2 proc proc2 maps export
ACTIVATE_SCRIPT = ~/miniforge3/bin/activate
CONDA_ENV_NAME = gdal_env
PANDOC=pandoc
all: preproc1 preproc2 proc proc2 maps export
preproc1:
gdal_translate -of GTiff /home/huaqo/dev/courses/2024_Remote_Sensing/lab3/S2A_MSIL2A_20170527T102031_N9999_R065_T33UUU_20191015T100203.SAFE/GRANULE/L2A_T33UUU_A010072_20170527T102301/IMG_DATA/R10m/T33UUU_20170527T102031_B02_10m.jp2 /home/huaqo/dev/courses/2024_Remote_Sensing/lab3/sen2tiff/B02.tif && \
gdal_translate -of GTiff /home/huaqo/dev/courses/2024_Remote_Sensing/lab3/S2A_MSIL2A_20170527T102031_N9999_R065_T33UUU_20191015T100203.SAFE/GRANULE/L2A_T33UUU_A010072_20170527T102301/IMG_DATA/R10m/T33UUU_20170527T102031_B03_10m.jp2 /home/huaqo/dev/courses/2024_Remote_Sensing/lab3/sen2tiff/B03.tif && \
gdal_translate -of GTiff /home/huaqo/dev/courses/2024_Remote_Sensing/lab3/S2A_MSIL2A_20170527T102031_N9999_R065_T33UUU_20191015T100203.SAFE/GRANULE/L2A_T33UUU_A010072_20170527T102301/IMG_DATA/R10m/T33UUU_20170527T102031_B04_10m.jp2 /home/huaqo/dev/courses/2024_Remote_Sensing/lab3/sen2tiff/B04.tif && \
gdal_translate -of GTiff /home/huaqo/dev/courses/2024_Remote_Sensing/lab3/S2A_MSIL2A_20170527T102031_N9999_R065_T33UUU_20191015T100203.SAFE/GRANULE/L2A_T33UUU_A010072_20170527T102301/IMG_DATA/R10m/T33UUU_20170527T102031_B08_10m.jp2 /home/huaqo/dev/courses/2024_Remote_Sensing/lab3/sen2tiff/B08.tif
preproc2:
gdal_translate -of GTiff /home/huaqo/dev/courses/2024_Remote_Sensing/lab3/S2A_MSIL2A_20170527T102031_N9999_R065_T33UUU_20191015T100203.SAFE/GRANULE/L2A_T33UUU_A010072_20170527T102301/IMG_DATA/R10m/T33UUU_20170527T102031_B02_10m.jp2 /home/huaqo/dev/courses/2024_Remote_Sensing/lab3/sen2tiff2/B02.tif && \
gdal_translate -of GTiff /home/huaqo/dev/courses/2024_Remote_Sensing/lab3/S2A_MSIL2A_20241118T143741_N0511_R096_T18GXU_20241118T201252.SAFE/GRANULE/L2A_T18GXU_A049142_20241118T144600/IMG_DATA/R10m/T18GXU_20241118T143741_B03_10m.jp2 /home/huaqo/dev/courses/2024_Remote_Sensing/lab3/sen2tiff2/B03.tif && \
gdal_translate -of GTiff /home/huaqo/dev/courses/2024_Remote_Sensing/lab3/S2A_MSIL2A_20241118T143741_N0511_R096_T18GXU_20241118T201252.SAFE/GRANULE/L2A_T18GXU_A049142_20241118T144600/IMG_DATA/R10m/T18GXU_20241118T143741_B04_10m.jp2 /home/huaqo/dev/courses/2024_Remote_Sensing/lab3/sen2tiff2/B04.tif && \
gdal_translate -of GTiff /home/huaqo/dev/courses/2024_Remote_Sensing/lab3/S2A_MSIL2A_20241118T143741_N0511_R096_T18GXU_20241118T201252.SAFE/GRANULE/L2A_T18GXU_A049142_20241118T144600/IMG_DATA/R10m/T18GXU_20241118T143741_B08_10m.jp2 /home/huaqo/dev/courses/2024_Remote_Sensing/lab3/sen2tiff2/B08.tif
proc:
@source $(ACTIVATE_SCRIPT) && conda activate $(CONDA_ENV_NAME) && \
python3 ndvi.py sen2tiff/B04.tif sen2tiff/B08.tif ndvi && \
python3 ndwi.py sen2tiff/B03.tif sen2tiff/B08.tif ndwi && \
python clip.py /home/huaqo/dev/courses/2024_Remote_Sensing/lab3/l8_ndvi/l8_ndvi.TIF /home/huaqo/dev/courses/2024_Remote_Sensing/lab3/ndvi/B04_ndvi.TIF /home/huaqo/dev/courses/2024_Remote_Sensing/lab3/clip/l8_ndvi.TIF /home/huaqo/dev/courses/2024_Remote_Sensing/lab3/clip/sen_ndvi.TIF && \
python diff.py /home/huaqo/dev/courses/2024_Remote_Sensing/lab3/clip/sen_ndvi.TIF /home/huaqo/dev/courses/2024_Remote_Sensing/lab3/clip/l8_ndvi.TIF /home/huaqo/dev/courses/2024_Remote_Sensing/lab3/diff/aligned.TIF /home/huaqo/dev/courses/2024_Remote_Sensing/lab3/diff/diff.TIF && \
python clip.py /home/huaqo/dev/courses/2024_Remote_Sensing/lab3/l8_ndwi/l8_ndwi.TIF /home/huaqo/dev/courses/2024_Remote_Sensing/lab3/ndwi/B03_ndwi.TIF /home/huaqo/dev/courses/2024_Remote_Sensing/lab3/clip/l8_ndwi.TIF /home/huaqo/dev/courses/2024_Remote_Sensing/lab3/clip/sen_ndwi.TIF && \
python diff.py /home/huaqo/dev/courses/2024_Remote_Sensing/lab3/clip/sen_ndwi.TIF /home/huaqo/dev/courses/2024_Remote_Sensing/lab3/clip/l8_ndwi.TIF /home/huaqo/dev/courses/2024_Remote_Sensing/lab3/diff/aligned_ndwi.TIF /home/huaqo/dev/courses/2024_Remote_Sensing/lab3/diff/diff_ndwi.TIF && \
python hist.py diff/diff_ndwi.TIF --output plots/diff_hist.png
proc2:
@source $(ACTIVATE_SCRIPT) && conda activate $(CONDA_ENV_NAME) && \
python3 ndvi.py sen2tiff2/B04.tif sen2tiff2/B08.tif ndvi2 && \
python3 ndwi.py sen2tiff2/B03.tif sen2tiff2/B08.tif ndwi2
maps:
python3 ndvi_map.py
python3 ndvi_map2.py
python3 ndwi_map.py
python3 ndwi_map2.py
python3 diff_map.py
export:
$(PANDOC) Lab3.md -o rcm01_2425_lab3_gottlebe_829101.pdf
-171
View File
@@ -1,171 +0,0 @@
from qgis.core import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5 import *
from datetime import datetime
import os
QGIS_PREFIX_PATH = "/usr/share/qgis"
LAYER_PATH = "/home/huaqo/dev/courses/2024_Remote_Sensing/lab3/diff/diff_ndwi.TIF"
STYLE_PATH = "/home/huaqo/dev/courses/2024_Remote_Sensing/styles/diff.qml"
EXPORT_PATH = "/home/huaqo/dev/courses/2024_Remote_Sensing/lab3/maps/diff_ndwi.png"
NORTH_ARROW_PATH = "/home/huaqo/dev/courses/2024_Remote_Sensing/styles/north_arrow.svg"
map_pos_x = 20
map_pos_y = 30
map_size_x = 200
map_size_y = 150
grid_interval_x = 100000
grid_interval_y = 100000
LAYER_NAME = "DIFF"
legend_pos_x = 245
legend_pos_y = 30
scalebar_pos_x = 20
scalebar_pos_y = 190
north_arrow_pos_x = 30
north_arrow_pos_y = 40
north_arrow_size_x = 15
north_arrow_size_y = 15
title_text = "Difference NDWI Landsat 8 and Sentinel 2 - Lab 3"
title_fontsize = 16
title_height = 10
author_text = "Author: Joaquin Gottlebe"
author_pos_y = 100
date_text = f"Date: {datetime.now().strftime('%d.%m.%Y')}"
date_pos_y = 110
crs_text = "CRS: EPSG 32633"
crs_pos_y = 120
fontfamily = "Arial"
info_font_size = 12
info_pos_x = legend_pos_x
# Initialize QGIS Application
QgsApplication.setPrefixPath(QGIS_PREFIX_PATH, True)
qgs = QgsApplication([], False)
qgs.initQgis()
# Cleanup
project = QgsProject.instance()
layer_ids = list(project.mapLayers().keys())
for layer_id in layer_ids:
project.removeMapLayer(layer_id)
# Load Layer
raster_layer = QgsRasterLayer(LAYER_PATH, LAYER_NAME)
if not raster_layer.isValid():
raise Exception(f"{LAYER_NAME} layer failed to load!")
QgsProject.instance().addMapLayer(raster_layer)
if not raster_layer.loadNamedStyle(STYLE_PATH):
raise Exception(f"Style {STYLE_PATH} failed to load")
# Create Layout
layout = QgsPrintLayout(project)
layout.initializeDefaults()
# Map
map_item = QgsLayoutItemMap(layout)
map_item.attemptMove(QgsLayoutPoint(map_pos_x,map_pos_y, QgsUnitTypes.LayoutMillimeters))
map_item.attemptResize(QgsLayoutSize(map_size_x, map_size_y, QgsUnitTypes.LayoutMillimeters))
map_item.zoomToExtent(raster_layer.extent())
layout.addLayoutItem(map_item)
# Add Coordinate Grid
grid = map_item.grid()
grid.setEnabled(True)
grid.setIntervalX(grid_interval_x)
grid.setIntervalY(grid_interval_y)
grid.setAnnotationEnabled(True)
grid.setAnnotationPrecision(0)
grid.setFrameStyle(QgsLayoutItemMapGrid.Zebra)
# Label
title_label = QgsLayoutItemLabel(layout)
title_label.setText(title_text)
title_label.setFont(QFont(fontfamily, title_fontsize))
title_label.setHAlign(Qt.AlignCenter)
title_label.adjustSizeToText()
layout_width = layout.pageCollection().page(0).pageSize().width()
title_width = title_label.rectWithFrame().width()
center_x = (layout_width - title_width) / 2
title_label.attemptMove(QgsLayoutPoint(center_x, title_height, QgsUnitTypes.LayoutMillimeters))
layout.addLayoutItem(title_label)
# Legend
legend_item = QgsLayoutItemLegend(layout)
legend_item.setLinkedMap(map_item)
legend_item.setTitle("Legend")
legend_item.setFrameEnabled(True)
legend_item.attemptMove(QgsLayoutPoint(legend_pos_x,legend_pos_y, QgsUnitTypes.LayoutMillimeters))
layout.addLayoutItem(legend_item)
# Scalebar
scalebar_item = QgsLayoutItemScaleBar(layout)
scalebar_item.setStyle('Single Box')
scalebar_item.setLinkedMap(map_item)
scalebar_item.setUnitLabel('m')
scalebar_item.setNumberOfSegments(4)
scalebar_item.setNumberOfSegmentsLeft(0)
scalebar_item.setUnitsPerSegment(50000)
scalebar_item.applyDefaultSize()
scalebar_item.attemptMove(QgsLayoutPoint(scalebar_pos_x,scalebar_pos_y, QgsUnitTypes.LayoutMillimeters))
layout.addLayoutItem(scalebar_item)
# North Arrow
north_arrow_item = QgsLayoutItemPicture(layout)
north_arrow_item.setPicturePath(NORTH_ARROW_PATH)
if not north_arrow_item.picturePath():
print("North arrow image failed to load!")
north_arrow_item.setReferencePoint(QgsLayoutItemPicture.UpperLeft)
north_arrow_item.attemptMove(QgsLayoutPoint(north_arrow_pos_x,north_arrow_pos_y,QgsUnitTypes.LayoutMillimeters))
north_arrow_item.attemptResize(QgsLayoutSize(north_arrow_size_x,north_arrow_size_y,QgsUnitTypes.LayoutMillimeters))
layout.addLayoutItem(north_arrow_item)
# Author Info
info_label = QgsLayoutItemLabel(layout)
info_label.setText(author_text)
info_label.setFont(QFont(fontfamily, info_font_size))
info_label.setHAlign(Qt.AlignLeft)
info_label.attemptMove(QgsLayoutPoint(info_pos_x, author_pos_y, QgsUnitTypes.LayoutMillimeters))
info_label.adjustSizeToText()
layout.addLayoutItem(info_label)
# Date Info
info_label = QgsLayoutItemLabel(layout)
info_label.setText(date_text)
info_label.setFont(QFont(fontfamily, info_font_size))
info_label.setHAlign(Qt.AlignLeft)
info_label.attemptMove(QgsLayoutPoint(info_pos_x, date_pos_y, QgsUnitTypes.LayoutMillimeters))
info_label.adjustSizeToText()
layout.addLayoutItem(info_label)
# CRS Info
info_label = QgsLayoutItemLabel(layout)
info_label.setText(crs_text)
info_label.setFont(QFont(fontfamily, info_font_size))
info_label.setHAlign(Qt.AlignLeft)
info_label.attemptMove(QgsLayoutPoint(info_pos_x, crs_pos_y, QgsUnitTypes.LayoutMillimeters))
info_label.adjustSizeToText()
layout.addLayoutItem(info_label)
# Export Map
exporter = QgsLayoutExporter(layout)
if os.path.exists(EXPORT_PATH):
os.remove(EXPORT_PATH)
export_result = exporter.exportToImage(EXPORT_PATH, QgsLayoutExporter.ImageExportSettings())
if export_result != QgsLayoutExporter.Success:
print(f"Failed to export {LAYER_NAME} map!")
else:
print(f"Map exported to: {EXPORT_PATH}")
# Cleanup QGIS
qgs.exitQgis()
-171
View File
@@ -1,171 +0,0 @@
from qgis.core import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5 import *
from datetime import datetime
import os
QGIS_PREFIX_PATH = "/usr/share/qgis"
LAYER_PATH = "/home/huaqo/dev/courses/2024_Remote_Sensing/lab3/ndvi/B04_ndvi.TIF"
STYLE_PATH = "/home/huaqo/dev/courses/2024_Remote_Sensing/styles/ndvi.qml"
EXPORT_PATH = "/home/huaqo/dev/courses/2024_Remote_Sensing/lab3/maps/ndvi.png"
NORTH_ARROW_PATH = "/home/huaqo/dev/courses/2024_Remote_Sensing/styles/north_arrow.svg"
map_pos_x = 20
map_pos_y = 30
map_size_x = 200
map_size_y = 150
grid_interval_x = 100000
grid_interval_y = 100000
LAYER_NAME = "NDVI"
legend_pos_x = 245
legend_pos_y = 30
scalebar_pos_x = 20
scalebar_pos_y = 190
north_arrow_pos_x = 30
north_arrow_pos_y = 40
north_arrow_size_x = 15
north_arrow_size_y = 15
title_text = "NDVI - Lab 3"
title_fontsize = 16
title_height = 10
author_text = "Author: Joaquin Gottlebe"
author_pos_y = 100
date_text = f"Date: {datetime.now().strftime('%d.%m.%Y')}"
date_pos_y = 110
crs_text = "CRS: EPSG 32633"
crs_pos_y = 120
fontfamily = "Arial"
info_font_size = 12
info_pos_x = legend_pos_x
# Initialize QGIS Application
QgsApplication.setPrefixPath(QGIS_PREFIX_PATH, True)
qgs = QgsApplication([], False)
qgs.initQgis()
# Cleanup
project = QgsProject.instance()
layer_ids = list(project.mapLayers().keys())
for layer_id in layer_ids:
project.removeMapLayer(layer_id)
# Load Layer
raster_layer = QgsRasterLayer(LAYER_PATH, LAYER_NAME)
if not raster_layer.isValid():
raise Exception(f"{LAYER_NAME} layer failed to load!")
QgsProject.instance().addMapLayer(raster_layer)
if not raster_layer.loadNamedStyle(STYLE_PATH):
raise Exception(f"Style {STYLE_PATH} failed to load")
# Create Layout
layout = QgsPrintLayout(project)
layout.initializeDefaults()
# Map
map_item = QgsLayoutItemMap(layout)
map_item.attemptMove(QgsLayoutPoint(map_pos_x,map_pos_y, QgsUnitTypes.LayoutMillimeters))
map_item.attemptResize(QgsLayoutSize(map_size_x, map_size_y, QgsUnitTypes.LayoutMillimeters))
map_item.zoomToExtent(raster_layer.extent())
layout.addLayoutItem(map_item)
# Add Coordinate Grid
grid = map_item.grid()
grid.setEnabled(True)
grid.setIntervalX(grid_interval_x)
grid.setIntervalY(grid_interval_y)
grid.setAnnotationEnabled(True)
grid.setAnnotationPrecision(0)
grid.setFrameStyle(QgsLayoutItemMapGrid.Zebra)
# Label
title_label = QgsLayoutItemLabel(layout)
title_label.setText(title_text)
title_label.setFont(QFont(fontfamily, title_fontsize))
title_label.setHAlign(Qt.AlignCenter)
title_label.adjustSizeToText()
layout_width = layout.pageCollection().page(0).pageSize().width()
title_width = title_label.rectWithFrame().width()
center_x = (layout_width - title_width) / 2
title_label.attemptMove(QgsLayoutPoint(center_x, title_height, QgsUnitTypes.LayoutMillimeters))
layout.addLayoutItem(title_label)
# Legend
legend_item = QgsLayoutItemLegend(layout)
legend_item.setLinkedMap(map_item)
legend_item.setTitle("Legend")
legend_item.setFrameEnabled(True)
legend_item.attemptMove(QgsLayoutPoint(legend_pos_x,legend_pos_y, QgsUnitTypes.LayoutMillimeters))
layout.addLayoutItem(legend_item)
# Scalebar
scalebar_item = QgsLayoutItemScaleBar(layout)
scalebar_item.setStyle('Single Box')
scalebar_item.setLinkedMap(map_item)
scalebar_item.setUnitLabel('m')
scalebar_item.setNumberOfSegments(4)
scalebar_item.setNumberOfSegmentsLeft(0)
scalebar_item.setUnitsPerSegment(50000)
scalebar_item.applyDefaultSize()
scalebar_item.attemptMove(QgsLayoutPoint(scalebar_pos_x,scalebar_pos_y, QgsUnitTypes.LayoutMillimeters))
layout.addLayoutItem(scalebar_item)
# North Arrow
north_arrow_item = QgsLayoutItemPicture(layout)
north_arrow_item.setPicturePath(NORTH_ARROW_PATH)
if not north_arrow_item.picturePath():
print("North arrow image failed to load!")
north_arrow_item.setReferencePoint(QgsLayoutItemPicture.UpperLeft)
north_arrow_item.attemptMove(QgsLayoutPoint(north_arrow_pos_x,north_arrow_pos_y,QgsUnitTypes.LayoutMillimeters))
north_arrow_item.attemptResize(QgsLayoutSize(north_arrow_size_x,north_arrow_size_y,QgsUnitTypes.LayoutMillimeters))
layout.addLayoutItem(north_arrow_item)
# Author Info
info_label = QgsLayoutItemLabel(layout)
info_label.setText(author_text)
info_label.setFont(QFont(fontfamily, info_font_size))
info_label.setHAlign(Qt.AlignLeft)
info_label.attemptMove(QgsLayoutPoint(info_pos_x, author_pos_y, QgsUnitTypes.LayoutMillimeters))
info_label.adjustSizeToText()
layout.addLayoutItem(info_label)
# Date Info
info_label = QgsLayoutItemLabel(layout)
info_label.setText(date_text)
info_label.setFont(QFont(fontfamily, info_font_size))
info_label.setHAlign(Qt.AlignLeft)
info_label.attemptMove(QgsLayoutPoint(info_pos_x, date_pos_y, QgsUnitTypes.LayoutMillimeters))
info_label.adjustSizeToText()
layout.addLayoutItem(info_label)
# CRS Info
info_label = QgsLayoutItemLabel(layout)
info_label.setText(crs_text)
info_label.setFont(QFont(fontfamily, info_font_size))
info_label.setHAlign(Qt.AlignLeft)
info_label.attemptMove(QgsLayoutPoint(info_pos_x, crs_pos_y, QgsUnitTypes.LayoutMillimeters))
info_label.adjustSizeToText()
layout.addLayoutItem(info_label)
# Export Map
exporter = QgsLayoutExporter(layout)
if os.path.exists(EXPORT_PATH):
os.remove(EXPORT_PATH)
export_result = exporter.exportToImage(EXPORT_PATH, QgsLayoutExporter.ImageExportSettings())
if export_result != QgsLayoutExporter.Success:
print(f"Failed to export {LAYER_NAME} map!")
else:
print(f"Map exported to: {EXPORT_PATH}")
# Cleanup QGIS
qgs.exitQgis()
-171
View File
@@ -1,171 +0,0 @@
from qgis.core import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5 import *
from datetime import datetime
import os
QGIS_PREFIX_PATH = "/usr/share/qgis"
LAYER_PATH = "/home/huaqo/dev/courses/2024_Remote_Sensing/lab3/ndvi2/B04_ndvi.TIF"
STYLE_PATH = "/home/huaqo/dev/courses/2024_Remote_Sensing/styles/ndvi2.qml"
EXPORT_PATH = "/home/huaqo/dev/courses/2024_Remote_Sensing/lab3/maps/ndvi2.png"
NORTH_ARROW_PATH = "/home/huaqo/dev/courses/2024_Remote_Sensing/styles/north_arrow.svg"
map_pos_x = 20
map_pos_y = 30
map_size_x = 200
map_size_y = 150
grid_interval_x = 100000
grid_interval_y = 100000
LAYER_NAME = "NDVI"
legend_pos_x = 245
legend_pos_y = 30
scalebar_pos_x = 20
scalebar_pos_y = 190
north_arrow_pos_x = 30
north_arrow_pos_y = 40
north_arrow_size_x = 15
north_arrow_size_y = 15
title_text = "Chacao Channel 18.11.24 NDVI - Lab 3"
title_fontsize = 16
title_height = 10
author_text = "Author: Joaquin Gottlebe"
author_pos_y = 100
date_text = f"Date: {datetime.now().strftime('%d.%m.%Y')}"
date_pos_y = 110
crs_text = "CRS: EPSG 32633"
crs_pos_y = 120
fontfamily = "Arial"
info_font_size = 12
info_pos_x = legend_pos_x
# Initialize QGIS Application
QgsApplication.setPrefixPath(QGIS_PREFIX_PATH, True)
qgs = QgsApplication([], False)
qgs.initQgis()
# Cleanup
project = QgsProject.instance()
layer_ids = list(project.mapLayers().keys())
for layer_id in layer_ids:
project.removeMapLayer(layer_id)
# Load Layer
raster_layer = QgsRasterLayer(LAYER_PATH, LAYER_NAME)
if not raster_layer.isValid():
raise Exception(f"{LAYER_NAME} layer failed to load!")
QgsProject.instance().addMapLayer(raster_layer)
if not raster_layer.loadNamedStyle(STYLE_PATH):
raise Exception(f"Style {STYLE_PATH} failed to load")
# Create Layout
layout = QgsPrintLayout(project)
layout.initializeDefaults()
# Map
map_item = QgsLayoutItemMap(layout)
map_item.attemptMove(QgsLayoutPoint(map_pos_x,map_pos_y, QgsUnitTypes.LayoutMillimeters))
map_item.attemptResize(QgsLayoutSize(map_size_x, map_size_y, QgsUnitTypes.LayoutMillimeters))
map_item.zoomToExtent(raster_layer.extent())
layout.addLayoutItem(map_item)
# Add Coordinate Grid
grid = map_item.grid()
grid.setEnabled(True)
grid.setIntervalX(grid_interval_x)
grid.setIntervalY(grid_interval_y)
grid.setAnnotationEnabled(True)
grid.setAnnotationPrecision(0)
grid.setFrameStyle(QgsLayoutItemMapGrid.Zebra)
# Label
title_label = QgsLayoutItemLabel(layout)
title_label.setText(title_text)
title_label.setFont(QFont(fontfamily, title_fontsize))
title_label.setHAlign(Qt.AlignCenter)
title_label.adjustSizeToText()
layout_width = layout.pageCollection().page(0).pageSize().width()
title_width = title_label.rectWithFrame().width()
center_x = (layout_width - title_width) / 2
title_label.attemptMove(QgsLayoutPoint(center_x, title_height, QgsUnitTypes.LayoutMillimeters))
layout.addLayoutItem(title_label)
# Legend
legend_item = QgsLayoutItemLegend(layout)
legend_item.setLinkedMap(map_item)
legend_item.setTitle("Legend")
legend_item.setFrameEnabled(True)
legend_item.attemptMove(QgsLayoutPoint(legend_pos_x,legend_pos_y, QgsUnitTypes.LayoutMillimeters))
layout.addLayoutItem(legend_item)
# Scalebar
scalebar_item = QgsLayoutItemScaleBar(layout)
scalebar_item.setStyle('Single Box')
scalebar_item.setLinkedMap(map_item)
scalebar_item.setUnitLabel('m')
scalebar_item.setNumberOfSegments(4)
scalebar_item.setNumberOfSegmentsLeft(0)
scalebar_item.setUnitsPerSegment(50000)
scalebar_item.applyDefaultSize()
scalebar_item.attemptMove(QgsLayoutPoint(scalebar_pos_x,scalebar_pos_y, QgsUnitTypes.LayoutMillimeters))
layout.addLayoutItem(scalebar_item)
# North Arrow
north_arrow_item = QgsLayoutItemPicture(layout)
north_arrow_item.setPicturePath(NORTH_ARROW_PATH)
if not north_arrow_item.picturePath():
print("North arrow image failed to load!")
north_arrow_item.setReferencePoint(QgsLayoutItemPicture.UpperLeft)
north_arrow_item.attemptMove(QgsLayoutPoint(north_arrow_pos_x,north_arrow_pos_y,QgsUnitTypes.LayoutMillimeters))
north_arrow_item.attemptResize(QgsLayoutSize(north_arrow_size_x,north_arrow_size_y,QgsUnitTypes.LayoutMillimeters))
layout.addLayoutItem(north_arrow_item)
# Author Info
info_label = QgsLayoutItemLabel(layout)
info_label.setText(author_text)
info_label.setFont(QFont(fontfamily, info_font_size))
info_label.setHAlign(Qt.AlignLeft)
info_label.attemptMove(QgsLayoutPoint(info_pos_x, author_pos_y, QgsUnitTypes.LayoutMillimeters))
info_label.adjustSizeToText()
layout.addLayoutItem(info_label)
# Date Info
info_label = QgsLayoutItemLabel(layout)
info_label.setText(date_text)
info_label.setFont(QFont(fontfamily, info_font_size))
info_label.setHAlign(Qt.AlignLeft)
info_label.attemptMove(QgsLayoutPoint(info_pos_x, date_pos_y, QgsUnitTypes.LayoutMillimeters))
info_label.adjustSizeToText()
layout.addLayoutItem(info_label)
# CRS Info
info_label = QgsLayoutItemLabel(layout)
info_label.setText(crs_text)
info_label.setFont(QFont(fontfamily, info_font_size))
info_label.setHAlign(Qt.AlignLeft)
info_label.attemptMove(QgsLayoutPoint(info_pos_x, crs_pos_y, QgsUnitTypes.LayoutMillimeters))
info_label.adjustSizeToText()
layout.addLayoutItem(info_label)
# Export Map
exporter = QgsLayoutExporter(layout)
if os.path.exists(EXPORT_PATH):
os.remove(EXPORT_PATH)
export_result = exporter.exportToImage(EXPORT_PATH, QgsLayoutExporter.ImageExportSettings())
if export_result != QgsLayoutExporter.Success:
print(f"Failed to export {LAYER_NAME} map!")
else:
print(f"Map exported to: {EXPORT_PATH}")
# Cleanup QGIS
qgs.exitQgis()
-171
View File
@@ -1,171 +0,0 @@
from qgis.core import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5 import *
from datetime import datetime
import os
QGIS_PREFIX_PATH = "/usr/share/qgis"
LAYER_PATH = "/home/huaqo/dev/courses/2024_Remote_Sensing/lab3/ndwi/B03_ndwi.TIF"
STYLE_PATH = "/home/huaqo/dev/courses/2024_Remote_Sensing/styles/ndwi.qml"
EXPORT_PATH = "/home/huaqo/dev/courses/2024_Remote_Sensing/lab3/maps/ndwi.png"
NORTH_ARROW_PATH = "/home/huaqo/dev/courses/2024_Remote_Sensing/styles/north_arrow.svg"
map_pos_x = 20
map_pos_y = 30
map_size_x = 200
map_size_y = 150
grid_interval_x = 100000
grid_interval_y = 100000
LAYER_NAME = "NDWI"
legend_pos_x = 245
legend_pos_y = 30
scalebar_pos_x = 20
scalebar_pos_y = 190
north_arrow_pos_x = 30
north_arrow_pos_y = 40
north_arrow_size_x = 15
north_arrow_size_y = 15
title_text = "NDWI - Lab 3"
title_fontsize = 16
title_height = 10
author_text = "Author: Joaquin Gottlebe"
author_pos_y = 100
date_text = f"Date: {datetime.now().strftime('%d.%m.%Y')}"
date_pos_y = 110
crs_text = "CRS: EPSG 32633"
crs_pos_y = 120
info_font_size = 12
info_pos_x = legend_pos_x
fontfamily = "Arial"
# Initialize QGIS Application
QgsApplication.setPrefixPath(QGIS_PREFIX_PATH, True)
qgs = QgsApplication([], False)
qgs.initQgis()
# Cleanup
project = QgsProject.instance()
layer_ids = list(project.mapLayers().keys())
for layer_id in layer_ids:
project.removeMapLayer(layer_id)
# Load Layer
raster_layer = QgsRasterLayer(LAYER_PATH, LAYER_NAME)
if not raster_layer.isValid():
raise Exception(f"{LAYER_NAME} layer failed to load!")
QgsProject.instance().addMapLayer(raster_layer)
if not raster_layer.loadNamedStyle(STYLE_PATH):
raise Exception(f"Style {STYLE_PATH} failed to load")
# Create Layout
layout = QgsPrintLayout(project)
layout.initializeDefaults()
# Map
map_item = QgsLayoutItemMap(layout)
map_item.attemptMove(QgsLayoutPoint(map_pos_x,map_pos_y, QgsUnitTypes.LayoutMillimeters))
map_item.attemptResize(QgsLayoutSize(map_size_x, map_size_y, QgsUnitTypes.LayoutMillimeters))
map_item.zoomToExtent(raster_layer.extent())
layout.addLayoutItem(map_item)
# Add Coordinate Grid
grid = map_item.grid()
grid.setEnabled(True)
grid.setIntervalX(grid_interval_x)
grid.setIntervalY(grid_interval_y)
grid.setAnnotationEnabled(True)
grid.setAnnotationPrecision(0)
grid.setFrameStyle(QgsLayoutItemMapGrid.Zebra)
# Label
title_label = QgsLayoutItemLabel(layout)
title_label.setText(title_text)
title_label.setFont(QFont(fontfamily, title_fontsize))
title_label.setHAlign(Qt.AlignCenter)
title_label.adjustSizeToText()
layout_width = layout.pageCollection().page(0).pageSize().width()
title_width = title_label.rectWithFrame().width()
center_x = (layout_width - title_width) / 2
title_label.attemptMove(QgsLayoutPoint(center_x, title_height, QgsUnitTypes.LayoutMillimeters))
layout.addLayoutItem(title_label)
# Legend
legend_item = QgsLayoutItemLegend(layout)
legend_item.setLinkedMap(map_item)
legend_item.setTitle("Legend")
legend_item.setFrameEnabled(True)
legend_item.attemptMove(QgsLayoutPoint(legend_pos_x,legend_pos_y, QgsUnitTypes.LayoutMillimeters))
layout.addLayoutItem(legend_item)
# Scalebar
scalebar_item = QgsLayoutItemScaleBar(layout)
scalebar_item.setStyle('Single Box')
scalebar_item.setLinkedMap(map_item)
scalebar_item.setUnitLabel('m')
scalebar_item.setNumberOfSegments(4)
scalebar_item.setNumberOfSegmentsLeft(0)
scalebar_item.setUnitsPerSegment(50000)
scalebar_item.applyDefaultSize()
scalebar_item.attemptMove(QgsLayoutPoint(scalebar_pos_x,scalebar_pos_y, QgsUnitTypes.LayoutMillimeters))
layout.addLayoutItem(scalebar_item)
# North Arrow
north_arrow_item = QgsLayoutItemPicture(layout)
north_arrow_item.setPicturePath(NORTH_ARROW_PATH)
if not north_arrow_item.picturePath():
print("North arrow image failed to load!")
north_arrow_item.setReferencePoint(QgsLayoutItemPicture.UpperLeft)
north_arrow_item.attemptMove(QgsLayoutPoint(north_arrow_pos_x,north_arrow_pos_y,QgsUnitTypes.LayoutMillimeters))
north_arrow_item.attemptResize(QgsLayoutSize(north_arrow_size_x,north_arrow_size_y,QgsUnitTypes.LayoutMillimeters))
layout.addLayoutItem(north_arrow_item)
# Author Info
info_label = QgsLayoutItemLabel(layout)
info_label.setText(author_text)
info_label.setFont(QFont(fontfamily, info_font_size))
info_label.setHAlign(Qt.AlignLeft)
info_label.attemptMove(QgsLayoutPoint(info_pos_x, author_pos_y, QgsUnitTypes.LayoutMillimeters))
info_label.adjustSizeToText()
layout.addLayoutItem(info_label)
# Date Info
info_label = QgsLayoutItemLabel(layout)
info_label.setText(date_text)
info_label.setFont(QFont(fontfamily, info_font_size))
info_label.setHAlign(Qt.AlignLeft)
info_label.attemptMove(QgsLayoutPoint(info_pos_x, date_pos_y, QgsUnitTypes.LayoutMillimeters))
info_label.adjustSizeToText()
layout.addLayoutItem(info_label)
# CRS Info
info_label = QgsLayoutItemLabel(layout)
info_label.setText(crs_text)
info_label.setFont(QFont(fontfamily, info_font_size))
info_label.setHAlign(Qt.AlignLeft)
info_label.attemptMove(QgsLayoutPoint(info_pos_x, crs_pos_y, QgsUnitTypes.LayoutMillimeters))
info_label.adjustSizeToText()
layout.addLayoutItem(info_label)
# Export Map
exporter = QgsLayoutExporter(layout)
if os.path.exists(EXPORT_PATH):
os.remove(EXPORT_PATH)
export_result = exporter.exportToImage(EXPORT_PATH, QgsLayoutExporter.ImageExportSettings())
if export_result != QgsLayoutExporter.Success:
print(f"Failed to export {LAYER_NAME} map!")
else:
print(f"Map exported to: {EXPORT_PATH}")
# Cleanup QGIS
qgs.exitQgis()
-171
View File
@@ -1,171 +0,0 @@
from qgis.core import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5 import *
from datetime import datetime
import os
QGIS_PREFIX_PATH = "/usr/share/qgis"
LAYER_PATH = "/home/huaqo/dev/courses/2024_Remote_Sensing/lab3/ndwi2/B03_ndwi.TIF"
STYLE_PATH = "/home/huaqo/dev/courses/2024_Remote_Sensing/styles/ndwi2.qml"
EXPORT_PATH = "/home/huaqo/dev/courses/2024_Remote_Sensing/lab3/maps/ndwi2.png"
NORTH_ARROW_PATH = "/home/huaqo/dev/courses/2024_Remote_Sensing/styles/north_arrow.svg"
map_pos_x = 20
map_pos_y = 30
map_size_x = 200
map_size_y = 150
grid_interval_x = 100000
grid_interval_y = 100000
LAYER_NAME = "NDWI"
legend_pos_x = 245
legend_pos_y = 30
scalebar_pos_x = 20
scalebar_pos_y = 190
north_arrow_pos_x = 30
north_arrow_pos_y = 40
north_arrow_size_x = 15
north_arrow_size_y = 15
title_text = "Chacao Channel 18.11.24 NDWI - Lab 3"
title_fontsize = 16
title_height = 10
author_text = "Author: Joaquin Gottlebe"
author_pos_y = 100
date_text = f"Date: {datetime.now().strftime('%d.%m.%Y')}"
date_pos_y = 110
crs_text = "CRS: EPSG 32633"
crs_pos_y = 120
info_font_size = 12
info_pos_x = legend_pos_x
fontfamily = "Arial"
# Initialize QGIS Application
QgsApplication.setPrefixPath(QGIS_PREFIX_PATH, True)
qgs = QgsApplication([], False)
qgs.initQgis()
# Cleanup
project = QgsProject.instance()
layer_ids = list(project.mapLayers().keys())
for layer_id in layer_ids:
project.removeMapLayer(layer_id)
# Load Layer
raster_layer = QgsRasterLayer(LAYER_PATH, LAYER_NAME)
if not raster_layer.isValid():
raise Exception(f"{LAYER_NAME} layer failed to load!")
QgsProject.instance().addMapLayer(raster_layer)
if not raster_layer.loadNamedStyle(STYLE_PATH):
raise Exception(f"Style {STYLE_PATH} failed to load")
# Create Layout
layout = QgsPrintLayout(project)
layout.initializeDefaults()
# Map
map_item = QgsLayoutItemMap(layout)
map_item.attemptMove(QgsLayoutPoint(map_pos_x,map_pos_y, QgsUnitTypes.LayoutMillimeters))
map_item.attemptResize(QgsLayoutSize(map_size_x, map_size_y, QgsUnitTypes.LayoutMillimeters))
map_item.zoomToExtent(raster_layer.extent())
layout.addLayoutItem(map_item)
# Add Coordinate Grid
grid = map_item.grid()
grid.setEnabled(True)
grid.setIntervalX(grid_interval_x)
grid.setIntervalY(grid_interval_y)
grid.setAnnotationEnabled(True)
grid.setAnnotationPrecision(0)
grid.setFrameStyle(QgsLayoutItemMapGrid.Zebra)
# Label
title_label = QgsLayoutItemLabel(layout)
title_label.setText(title_text)
title_label.setFont(QFont(fontfamily, title_fontsize))
title_label.setHAlign(Qt.AlignCenter)
title_label.adjustSizeToText()
layout_width = layout.pageCollection().page(0).pageSize().width()
title_width = title_label.rectWithFrame().width()
center_x = (layout_width - title_width) / 2
title_label.attemptMove(QgsLayoutPoint(center_x, title_height, QgsUnitTypes.LayoutMillimeters))
layout.addLayoutItem(title_label)
# Legend
legend_item = QgsLayoutItemLegend(layout)
legend_item.setLinkedMap(map_item)
legend_item.setTitle("Legend")
legend_item.setFrameEnabled(True)
legend_item.attemptMove(QgsLayoutPoint(legend_pos_x,legend_pos_y, QgsUnitTypes.LayoutMillimeters))
layout.addLayoutItem(legend_item)
# Scalebar
scalebar_item = QgsLayoutItemScaleBar(layout)
scalebar_item.setStyle('Single Box')
scalebar_item.setLinkedMap(map_item)
scalebar_item.setUnitLabel('m')
scalebar_item.setNumberOfSegments(4)
scalebar_item.setNumberOfSegmentsLeft(0)
scalebar_item.setUnitsPerSegment(50000)
scalebar_item.applyDefaultSize()
scalebar_item.attemptMove(QgsLayoutPoint(scalebar_pos_x,scalebar_pos_y, QgsUnitTypes.LayoutMillimeters))
layout.addLayoutItem(scalebar_item)
# North Arrow
north_arrow_item = QgsLayoutItemPicture(layout)
north_arrow_item.setPicturePath(NORTH_ARROW_PATH)
if not north_arrow_item.picturePath():
print("North arrow image failed to load!")
north_arrow_item.setReferencePoint(QgsLayoutItemPicture.UpperLeft)
north_arrow_item.attemptMove(QgsLayoutPoint(north_arrow_pos_x,north_arrow_pos_y,QgsUnitTypes.LayoutMillimeters))
north_arrow_item.attemptResize(QgsLayoutSize(north_arrow_size_x,north_arrow_size_y,QgsUnitTypes.LayoutMillimeters))
layout.addLayoutItem(north_arrow_item)
# Author Info
info_label = QgsLayoutItemLabel(layout)
info_label.setText(author_text)
info_label.setFont(QFont(fontfamily, info_font_size))
info_label.setHAlign(Qt.AlignLeft)
info_label.attemptMove(QgsLayoutPoint(info_pos_x, author_pos_y, QgsUnitTypes.LayoutMillimeters))
info_label.adjustSizeToText()
layout.addLayoutItem(info_label)
# Date Info
info_label = QgsLayoutItemLabel(layout)
info_label.setText(date_text)
info_label.setFont(QFont(fontfamily, info_font_size))
info_label.setHAlign(Qt.AlignLeft)
info_label.attemptMove(QgsLayoutPoint(info_pos_x, date_pos_y, QgsUnitTypes.LayoutMillimeters))
info_label.adjustSizeToText()
layout.addLayoutItem(info_label)
# CRS Info
info_label = QgsLayoutItemLabel(layout)
info_label.setText(crs_text)
info_label.setFont(QFont(fontfamily, info_font_size))
info_label.setHAlign(Qt.AlignLeft)
info_label.attemptMove(QgsLayoutPoint(info_pos_x, crs_pos_y, QgsUnitTypes.LayoutMillimeters))
info_label.adjustSizeToText()
layout.addLayoutItem(info_label)
# Export Map
exporter = QgsLayoutExporter(layout)
if os.path.exists(EXPORT_PATH):
os.remove(EXPORT_PATH)
export_result = exporter.exportToImage(EXPORT_PATH, QgsLayoutExporter.ImageExportSettings())
if export_result != QgsLayoutExporter.Success:
print(f"Failed to export {LAYER_NAME} map!")
else:
print(f"Map exported to: {EXPORT_PATH}")
# Cleanup QGIS
qgs.exitQgis()
View File
+107
View File
@@ -0,0 +1,107 @@
import rasterio
import numpy as np
from shapely.geometry import mapping
from rasterio.features import geometry_mask
import geopandas as gpd
# Step 1: Load Raster Data
def load_raster(raster_path):
with rasterio.open(raster_path) as src:
bands = [src.read(i) for i in range(1, src.count + 1)]
profile = src.profile
return np.stack(bands, axis=-1), profile
# Step 2: Extract Training Data
def extract_training_data(raster, training_shapefile, profile):
training_labels = gpd.read_file(training_shapefile)
class_data = {}
for _, row in training_labels.iterrows():
class_id = row['class_id']
geom = [mapping(row['geometry'])]
mask = geometry_mask(
geom, transform=profile['transform'], invert=True, out_shape=(profile['height'], profile['width'])
)
masked_pixels = raster[mask]
if class_id not in class_data:
class_data[class_id] = []
class_data[class_id].append(masked_pixels)
# Aggregate class data
for class_id in class_data.keys():
class_data[class_id] = np.vstack(class_data[class_id])
return class_data
# Step 3: Calculate Mean and Covariance for Each Class
def compute_statistics(class_data):
statistics = {}
for class_id, pixels in class_data.items():
mean_vector = np.mean(pixels, axis=0)
covariance_matrix = np.cov(pixels, rowvar=False)
statistics[class_id] = {
"mean": mean_vector,
"covariance": covariance_matrix
}
return statistics
# Step 4: Maximum Likelihood Calculation
def calculate_likelihood(pixel, mean, covariance):
# Multivariate normal distribution likelihood
dim = len(pixel)
det_cov = np.linalg.det(covariance)
inv_cov = np.linalg.inv(covariance)
diff = pixel - mean
exponent = -0.5 * np.dot(diff.T, np.dot(inv_cov, diff))
likelihood = (1.0 / ((2 * np.pi) ** (dim / 2) * (det_cov ** 0.5))) * np.exp(exponent)
return likelihood
def classify_with_maximum_likelihood(raster, statistics):
rows, cols, bands = raster.shape
classified_image = np.full((rows, cols), fill_value=255, dtype=np.uint8) # 255 as nodata
for i in range(rows):
for j in range(cols):
pixel_spectrum = raster[i, j, :]
likelihoods = {
class_id: calculate_likelihood(pixel_spectrum, stats["mean"], stats["covariance"])
for class_id, stats in statistics.items()
}
classified_image[i, j] = max(likelihoods, key=likelihoods.get) # Class with maximum likelihood
return classified_image
# Step 5: Save Classified Image
def save_classified_image(classified_image, profile, output_path):
profile.update(count=1, dtype=rasterio.uint8, nodata=255)
with rasterio.open(output_path, "w", **profile) as dst:
dst.write(classified_image, 1)
# Main Execution
if __name__ == "__main__":
# File paths
raster_path = "stacked/stacked.tif"
training_shapefile = "training/training.shp"
output_path = "classified/maxlike.tif"
# Load raster and metadata
raster, profile = load_raster(raster_path)
# Extract training data
print("Extracting training data...")
class_data = extract_training_data(raster, training_shapefile, profile)
# Compute class statistics
print("Computing class statistics...")
statistics = compute_statistics(class_data)
# Classify raster using Maximum Likelihood
print("Classifying with Maximum Likelihood...")
classified_image = classify_with_maximum_likelihood(raster, statistics)
# Save the classified image
save_classified_image(classified_image, profile, output_path)
print(f"Classified image saved to {output_path}")
+77
View File
@@ -0,0 +1,77 @@
import rasterio
import numpy as np
from shapely.geometry import mapping
from rasterio.features import geometry_mask
import geopandas as gpd
# Step 1: Load Raster Data
def load_raster(raster_path):
with rasterio.open(raster_path) as src:
bands = [src.read(i) for i in range(1, src.count + 1)]
profile = src.profile
return np.stack(bands, axis=-1), profile
# Step 2: Extract Reference Spectra
def extract_reference_spectra(raster, training_shapefile, profile):
training_labels = gpd.read_file(training_shapefile)
reference_spectra = {}
for _, row in training_labels.iterrows():
class_id = row['class_id']
geom = [mapping(row['geometry'])]
mask = geometry_mask(
geom, transform=profile['transform'], invert=True, out_shape=(profile['height'], profile['width'])
)
masked_pixels = raster[mask]
mean_spectrum = np.mean(masked_pixels, axis=0) # Calculate mean spectrum for the class
reference_spectra[class_id] = mean_spectrum
return reference_spectra
# Step 3: Minimum Distance Classification
def minimum_distance(pixel_spectrum, reference_spectra):
distances = {class_id: np.linalg.norm(pixel_spectrum - ref_spectrum)
for class_id, ref_spectrum in reference_spectra.items()}
return min(distances, key=distances.get) # Return the class with the smallest distance
def classify_with_min_distance(raster, reference_spectra):
rows, cols, bands = raster.shape
classified_image = np.full((rows, cols), fill_value=255, dtype=np.uint8) # 255 as nodata
for i in range(rows):
for j in range(cols):
pixel_spectrum = raster[i, j, :]
classified_image[i, j] = minimum_distance(pixel_spectrum, reference_spectra)
return classified_image
# Step 4: Save Classified Image
def save_classified_image(classified_image, profile, output_path):
profile.update(count=1, dtype=rasterio.uint8, nodata=255)
with rasterio.open(output_path, "w", **profile) as dst:
dst.write(classified_image, 1)
# Main Execution
if __name__ == "__main__":
# File paths
raster_path = "stacked/stacked.tif"
training_shapefile = "training/training.shp"
output_path = "classified/mindist.tif"
# Load raster and metadata
raster, profile = load_raster(raster_path)
# Extract reference spectra
print("Extracting reference spectra...")
reference_spectra = extract_reference_spectra(raster, training_shapefile, profile)
# Classify raster using Minimum Distance
print("Classifying with Minimum Distance...")
classified_image = classify_with_min_distance(raster, reference_spectra)
# Save the classified image
save_classified_image(classified_image, profile, output_path)
print(f"Classified image saved to {output_path}")
+32
View File
@@ -0,0 +1,32 @@
import sys
import rasterio
import numpy as np
def normalize_tif(input_tif, output_tif):
with rasterio.open(input_tif) as src:
data = src.read(1) # Reading the first band
profile = src.profile
# Handle potential NoData values
valid_mask = data != src.nodata if src.nodata is not None else np.ones_like(data, dtype=bool)
data_min, data_max = data[valid_mask].min(), data[valid_mask].max()
# Normalize data
normalized_data = (data - data_min) / (data_max - data_min)
normalized_data[~valid_mask] = src.nodata # Retain NoData values
profile.update(dtype=rasterio.float32)
with rasterio.open(output_tif, 'w', **profile) as dst:
dst.write(normalized_data.astype(rasterio.float32), 1)
if __name__ == "__main__":
if len(sys.argv) != 3:
print("Usage: python3 norm.py <input_tif> <output_tif>")
sys.exit(1)
input_file = sys.argv[1]
output_file = sys.argv[2]
normalize_tif(input_file, output_file)
print(f"Normalized file saved to {output_file}")
+89
View File
@@ -0,0 +1,89 @@
import rasterio
import geopandas as gpd
import numpy as np
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from rasterio.features import geometry_mask
from shapely.geometry import mapping
# Step 1: Load the Raster Data
def load_raster(raster_path):
with rasterio.open(raster_path) as src:
bands = [src.read(i) for i in range(1, src.count + 1)]
profile = src.profile
return np.stack(bands, axis=-1), profile
# Step 2: Extract Features and Labels from Training Data
def extract_training_data(raster, training_shapefile, profile):
training_labels = gpd.read_file(training_shapefile)
features = []
labels = []
for _, row in training_labels.iterrows():
class_id = row['class_id'] # Ensure 'class_id' column exists in the shapefile
geom = [mapping(row['geometry'])]
mask = geometry_mask(
geom, transform=profile['transform'], invert=True, out_shape=(profile['height'], profile['width'])
)
masked_pixels = raster[mask]
features.append(masked_pixels)
labels.append(np.full(masked_pixels.shape[0], class_id))
return np.vstack(features), np.hstack(labels)
# Step 3: Train the Random Forest Classifier
def train_classifier(features, labels):
X_train, X_test, y_train, y_test = train_test_split(features, labels, test_size=0.3, random_state=42)
classifier = RandomForestClassifier(n_estimators=100, random_state=42)
classifier.fit(X_train, y_train)
y_pred = classifier.predict(X_test)
print("Classification Report:")
print(classification_report(y_test, y_pred))
return classifier
# Step 4: Classify the Entire Raster
def classify_raster(raster, classifier, profile, output_path):
rows, cols, bands = raster.shape
flattened_data = raster.reshape(-1, bands)
predictions = classifier.predict(flattened_data)
classified_image = predictions.reshape(rows, cols)
profile.update(
count=1,
dtype=rasterio.uint8,
nodata=255)
with rasterio.open(output_path, "w", **profile) as dst:
dst.write(classified_image.astype(rasterio.uint8), 1)
return classified_image
# Main Execution
if __name__ == "__main__":
# Paths to your files
raster_path = "stacked/stacked.tif"
training_shapefile = "training/training.shp"
output_path = "classified/randomforest.tif"
# Load raster and metadata
raster, profile = load_raster(raster_path)
# Extract training data
print("Extracting training data...")
features, labels = extract_training_data(raster, training_shapefile, profile)
# Train the classifier
print("Training the classifier...")
classifier = train_classifier(features, labels)
# Classify the raster
print("Classifying the raster...")
classified_image = classify_raster(raster, classifier, profile, output_path)
+100
View File
@@ -0,0 +1,100 @@
import rasterio
import numpy as np
import pandas as pd
def map_two_digit_code(code: int) -> str:
"""
Returns a string label like 'Water -> Agriculture'
by interpreting the tens digit as the 'from' class
and the ones digit as the 'to' class.
Example:
code = 34
tens_digit = 3 -> 'Forest'
ones_digit = 4 -> 'Agriculture'
return 'Forest -> Agriculture'
"""
# Define what each digit means
digit_to_label = {
1: "Water",
2: "Urban",
3: "Forest",
4: "Agriculture"
}
# Tens digit = 'from' class
tens_digit = code // 10
from_label = digit_to_label.get(tens_digit, "Unknown")
# Ones digit = 'to' class
ones_digit = code % 10
to_label = digit_to_label.get(ones_digit, "Unknown")
return f"{from_label} -> {to_label}"
def generate_change_detection_report(tif_path: str, output_csv_path: str = None) -> pd.DataFrame:
"""
Reads a single-band change-detection GeoTIFF with classes from 11 to 44,
generates a report of pixel counts, area, and applies a label for every code.
:param tif_path: Path to the input GeoTIFF.
:param output_csv_path: If provided, saves the report as a CSV file.
:return: A pandas DataFrame with columns: ['Class_Value', 'Pixel_Count', 'Area', 'Label'].
"""
# 1. Open the raster
with rasterio.open(tif_path) as src:
band = src.read(1)
transform = src.transform
# Compute pixel area
pixel_width = transform[0]
pixel_height = -transform[4] # Typically negative
pixel_area = pixel_width * pixel_height
# 2. Count unique class values
unique_vals, counts = np.unique(band, return_counts=True)
# 3. Filter classes from 11 to 44
valid_mask = (unique_vals >= 11) & (unique_vals <= 44)
filtered_classes = unique_vals[valid_mask]
filtered_counts = counts[valid_mask]
# 4. Calculate area per class
areas = filtered_counts * pixel_area
# 5. Create a DataFrame
df_report = pd.DataFrame({
"Class_Value": filtered_classes,
"Pixel_Count": filtered_counts,
"Area": areas
})
# 6. Apply the custom mapping function to get a text label (e.g., 'Water -> Agriculture')
df_report["Label"] = df_report["Class_Value"].apply(map_two_digit_code)
# 7. (Optional) sort by Class_Value
df_report.sort_values(by="Class_Value", inplace=True)
# 8. Optionally save the DataFrame to a CSV file
if output_csv_path:
df_report.to_csv(output_csv_path, index=False)
return df_report
# ---------------
# Example usage:
if __name__ == "__main__":
input_tif = "change_detected/change_detection.tif" # Update path as needed
report_df = generate_change_detection_report(
tif_path=input_tif,
output_csv_path="report/change_detection_report.csv"
)
print("Detailed Report (11–44):")
print(report_df)
# Optional: Summarize area by the Label column
summary = report_df.groupby("Label")["Area"].sum().reset_index()
summary.columns = ["Label", "Total_Area"]
print("\nArea Summary by Label:")
print(summary)
+93
View File
@@ -0,0 +1,93 @@
import rasterio
import numpy as np
from shapely.geometry import mapping
from rasterio.features import geometry_mask
# Step 1: Load Raster Data
def load_raster(raster_path):
with rasterio.open(raster_path) as src:
bands = [src.read(i) for i in range(1, src.count + 1)]
profile = src.profile
return np.stack(bands, axis=-1), profile
# Step 2: Extract Reference Spectra
def extract_reference_spectra(raster, training_shapefile, profile):
import geopandas as gpd
training_labels = gpd.read_file(training_shapefile)
reference_spectra = {}
for _, row in training_labels.iterrows():
class_id = row['class_id']
geom = [mapping(row['geometry'])]
mask = geometry_mask(
geom, transform=profile['transform'], invert=True, out_shape=(profile['height'], profile['width'])
)
masked_pixels = raster[mask]
mean_spectrum = np.mean(masked_pixels, axis=0)
reference_spectra[class_id] = mean_spectrum
return reference_spectra
# Step 3: Spectral Angle Mapping
def spectral_angle(pixel_spectrum, reference_spectrum):
# Avoid zero vectors
pixel_norm = np.linalg.norm(pixel_spectrum)
reference_norm = np.linalg.norm(reference_spectrum)
if pixel_norm == 0 or reference_norm == 0:
return np.pi # Maximum angle (180 degrees)
numerator = np.dot(pixel_spectrum, reference_spectrum)
denominator = pixel_norm * reference_norm
# Clip to avoid numerical issues with arccos
cosine_similarity = numerator / denominator
cosine_similarity = np.clip(cosine_similarity, -1.0, 1.0)
angle = np.arccos(cosine_similarity)
return angle
def classify_with_sam(raster, reference_spectra):
rows, cols, bands = raster.shape
classified_image = np.full((rows, cols), fill_value=255, dtype=np.uint8) # 255 as nodata
for i in range(rows):
for j in range(cols):
pixel_spectrum = raster[i, j, :]
angles = {class_id: spectral_angle(pixel_spectrum, ref_spectrum)
for class_id, ref_spectrum in reference_spectra.items()}
classified_image[i, j] = min(angles, key=angles.get) # Class with smallest angle
return classified_image
# Step 4: Save Classified Image
def save_classified_image(classified_image, profile, output_path):
profile.update(count=1, dtype=rasterio.uint8, nodata=255)
with rasterio.open(output_path, "w", **profile) as dst:
dst.write(classified_image, 1)
# Main Execution
if __name__ == "__main__":
# File paths
raster_path = "stacked/stacked.tif"
training_shapefile = "training/training.shp"
output_path = "classified/sam.tif"
# Load raster and metadata
raster, profile = load_raster(raster_path)
# Extract reference spectra
print("Extracting reference spectra...")
reference_spectra = extract_reference_spectra(raster, training_shapefile, profile)
# Classify raster using SAM
print("Classifying with SAM...")
classified_image = classify_with_sam(raster, reference_spectra)
# Save the classified image
save_classified_image(classified_image, profile, output_path)
print(f"Classified image saved to {output_path}")
+27
View File
@@ -0,0 +1,27 @@
import rasterio
import numpy as np
import argparse
def stack_bands(input_files, output_file):
bands = []
metadata = None
for band_file in input_files:
with rasterio.open(band_file) as src:
if metadata is None:
metadata = src.meta
metadata.update(count=len(input_files))
bands.append(src.read(1))
stacked_data = np.stack(bands)
with rasterio.open(output_file, 'w', **metadata) as dst:
for i in range(stacked_data.shape[0]):
dst.write(stacked_data[i, :, :], i + 1)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Stack multiple raster bands into a single .tif file.")
parser.add_argument("input_files", nargs='+', help="Paths to the input .tif files (one for each band).")
parser.add_argument("output_file", type=str, help="Path to save the stacked .tif file.")
args = parser.parse_args()
stack_bands(args.input_files, args.output_file)
-223
View File
@@ -1,223 +0,0 @@
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
<qgis minScale="1e+08" maxScale="0" styleCategories="AllStyleCategories" version="3.34.12-Prizren" hasScaleBasedVisibilityFlag="0" autoRefreshMode="Disabled" autoRefreshTime="0">
<flags>
<Identifiable>1</Identifiable>
<Removable>1</Removable>
<Searchable>1</Searchable>
<Private>0</Private>
</flags>
<temporal mode="0" enabled="0" fetchMode="0">
<fixedRange>
<start></start>
<end></end>
</fixedRange>
</temporal>
<elevation band="1" enabled="0" symbology="Line" zscale="1" zoffset="0">
<data-defined-properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
</Option>
</data-defined-properties>
<profileLineSymbol>
<symbol type="line" is_animated="0" clip_to_extent="1" force_rhr="0" name="" alpha="1" frame_rate="10">
<data_defined_properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
</Option>
</data_defined_properties>
<layer locked="0" pass="0" class="SimpleLine" id="{90717ec5-4c44-421e-8dcf-9d35d592e70c}" enabled="1">
<Option type="Map">
<Option type="QString" name="align_dash_pattern" value="0"/>
<Option type="QString" name="capstyle" value="square"/>
<Option type="QString" name="customdash" value="5;2"/>
<Option type="QString" name="customdash_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="customdash_unit" value="MM"/>
<Option type="QString" name="dash_pattern_offset" value="0"/>
<Option type="QString" name="dash_pattern_offset_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="dash_pattern_offset_unit" value="MM"/>
<Option type="QString" name="draw_inside_polygon" value="0"/>
<Option type="QString" name="joinstyle" value="bevel"/>
<Option type="QString" name="line_color" value="183,72,75,255"/>
<Option type="QString" name="line_style" value="solid"/>
<Option type="QString" name="line_width" value="0.6"/>
<Option type="QString" name="line_width_unit" value="MM"/>
<Option type="QString" name="offset" value="0"/>
<Option type="QString" name="offset_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="offset_unit" value="MM"/>
<Option type="QString" name="ring_filter" value="0"/>
<Option type="QString" name="trim_distance_end" value="0"/>
<Option type="QString" name="trim_distance_end_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="trim_distance_end_unit" value="MM"/>
<Option type="QString" name="trim_distance_start" value="0"/>
<Option type="QString" name="trim_distance_start_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="trim_distance_start_unit" value="MM"/>
<Option type="QString" name="tweak_dash_pattern_on_corners" value="0"/>
<Option type="QString" name="use_custom_dash" value="0"/>
<Option type="QString" name="width_map_unit_scale" value="3x:0,0,0,0,0,0"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</profileLineSymbol>
<profileFillSymbol>
<symbol type="fill" is_animated="0" clip_to_extent="1" force_rhr="0" name="" alpha="1" frame_rate="10">
<data_defined_properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
</Option>
</data_defined_properties>
<layer locked="0" pass="0" class="SimpleFill" id="{7e66c755-dd91-48e4-9d02-6cc4716ca573}" enabled="1">
<Option type="Map">
<Option type="QString" name="border_width_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="color" value="183,72,75,255"/>
<Option type="QString" name="joinstyle" value="bevel"/>
<Option type="QString" name="offset" value="0,0"/>
<Option type="QString" name="offset_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="offset_unit" value="MM"/>
<Option type="QString" name="outline_color" value="35,35,35,255"/>
<Option type="QString" name="outline_style" value="no"/>
<Option type="QString" name="outline_width" value="0.26"/>
<Option type="QString" name="outline_width_unit" value="MM"/>
<Option type="QString" name="style" value="solid"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</profileFillSymbol>
</elevation>
<customproperties>
<Option type="Map">
<Option type="bool" name="WMSBackgroundLayer" value="false"/>
<Option type="bool" name="WMSPublishDataSourceUrl" value="false"/>
<Option type="int" name="embeddedWidgets/count" value="0"/>
<Option type="QString" name="identify/format" value="Value"/>
</Option>
</customproperties>
<mapTip enabled="1"></mapTip>
<pipe-data-defined-properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
</Option>
</pipe-data-defined-properties>
<pipe>
<provider>
<resampling maxOversampling="2" zoomedOutResamplingMethod="nearestNeighbour" enabled="false" zoomedInResamplingMethod="nearestNeighbour"/>
</provider>
<rasterrenderer opacity="1" alphaBand="-1" type="singlebandpseudocolor" band="1" classificationMin="-1" classificationMax="1" nodataColor="">
<rasterTransparency/>
<minMaxOrigin>
<limits>None</limits>
<extent>WholeRaster</extent>
<statAccuracy>Estimated</statAccuracy>
<cumulativeCutLower>0.02</cumulativeCutLower>
<cumulativeCutUpper>0.98</cumulativeCutUpper>
<stdDevFactor>2</stdDevFactor>
</minMaxOrigin>
<rastershader>
<colorrampshader clip="0" labelPrecision="4" minimumValue="-1" colorRampType="INTERPOLATED" maximumValue="1" classificationMode="1">
<colorramp type="gradient" name="[source]">
<Option type="Map">
<Option type="QString" name="color1" value="0,0,4,255"/>
<Option type="QString" name="color2" value="252,255,164,255"/>
<Option type="QString" name="direction" value="ccw"/>
<Option type="QString" name="discrete" value="0"/>
<Option type="QString" name="rampType" value="gradient"/>
<Option type="QString" name="spec" value="rgb"/>
<Option type="QString" name="stops" value="0.0196078;2,2,12,255;rgb;ccw:0.0392157;5,4,23,255;rgb;ccw:0.0588235;10,7,34,255;rgb;ccw:0.0784314;16,9,45,255;rgb;ccw:0.0980392;22,11,57,255;rgb;ccw:0.117647;30,12,69,255;rgb;ccw:0.137255;38,12,81,255;rgb;ccw:0.156863;47,10,91,255;rgb;ccw:0.176471;56,9,98,255;rgb;ccw:0.196078;64,10,103,255;rgb;ccw:0.215686;73,11,106,255;rgb;ccw:0.235294;81,14,108,255;rgb;ccw:0.254902;89,16,110,255;rgb;ccw:0.27451;97,19,110,255;rgb;ccw:0.294118;105,22,110,255;rgb;ccw:0.313725;113,25,110,255;rgb;ccw:0.333333;120,28,109,255;rgb;ccw:0.352941;128,31,108,255;rgb;ccw:0.372549;136,34,106,255;rgb;ccw:0.392157;144,37,104,255;rgb;ccw:0.411765;152,39,102,255;rgb;ccw:0.431373;160,42,99,255;rgb;ccw:0.45098;168,46,95,255;rgb;ccw:0.470588;176,49,91,255;rgb;ccw:0.490196;183,53,87,255;rgb;ccw:0.509804;191,57,82,255;rgb;ccw:0.529412;198,61,77,255;rgb;ccw:0.54902;204,66,72,255;rgb;ccw:0.568627;211,71,67,255;rgb;ccw:0.588235;217,77,61,255;rgb;ccw:0.607843;223,83,55,255;rgb;ccw:0.627451;228,90,49,255;rgb;ccw:0.647059;233,97,43,255;rgb;ccw:0.666667;237,105,37,255;rgb;ccw:0.686275;241,113,31,255;rgb;ccw:0.705882;244,121,24,255;rgb;ccw:0.72549;247,130,18,255;rgb;ccw:0.745098;249,139,11,255;rgb;ccw:0.764706;250,148,7,255;rgb;ccw:0.784314;251,157,7,255;rgb;ccw:0.803922;252,166,12,255;rgb;ccw:0.823529;252,176,20,255;rgb;ccw:0.843137;251,186,31,255;rgb;ccw:0.862745;250,196,42,255;rgb;ccw:0.882353;248,205,55,255;rgb;ccw:0.901961;246,215,70,255;rgb;ccw:0.921569;244,225,86,255;rgb;ccw:0.941176;242,234,105,255;rgb;ccw:0.960784;242,242,125,255;rgb;ccw:0.980392;245,249,146,255;rgb;ccw"/>
</Option>
</colorramp>
<item color="#000004" label="-1.0000" alpha="255" value="-1"/>
<item color="#02020c" label="-0.9608" alpha="255" value="-0.9607844"/>
<item color="#050417" label="-0.9216" alpha="255" value="-0.9215686"/>
<item color="#0a0722" label="-0.8824" alpha="255" value="-0.882353"/>
<item color="#10092d" label="-0.8431" alpha="255" value="-0.8431372"/>
<item color="#160b39" label="-0.8039" alpha="255" value="-0.8039216"/>
<item color="#1e0c45" label="-0.7647" alpha="255" value="-0.764706"/>
<item color="#260c51" label="-0.7255" alpha="255" value="-0.72549"/>
<item color="#2f0a5b" label="-0.6863" alpha="255" value="-0.686274"/>
<item color="#380962" label="-0.6471" alpha="255" value="-0.647058"/>
<item color="#400a67" label="-0.6078" alpha="255" value="-0.607844"/>
<item color="#490b6a" label="-0.5686" alpha="255" value="-0.568628"/>
<item color="#510e6c" label="-0.5294" alpha="255" value="-0.529412"/>
<item color="#59106e" label="-0.4902" alpha="255" value="-0.490196"/>
<item color="#61136e" label="-0.4510" alpha="255" value="-0.45098"/>
<item color="#69166e" label="-0.4118" alpha="255" value="-0.411764"/>
<item color="#71196e" label="-0.3726" alpha="255" value="-0.37255"/>
<item color="#781c6d" label="-0.3333" alpha="255" value="-0.333334"/>
<item color="#801f6c" label="-0.2941" alpha="255" value="-0.294118"/>
<item color="#88226a" label="-0.2549" alpha="255" value="-0.254902"/>
<item color="#902568" label="-0.2157" alpha="255" value="-0.215686"/>
<item color="#982766" label="-0.1765" alpha="255" value="-0.17647"/>
<item color="#a02a63" label="-0.1373" alpha="255" value="-0.137254"/>
<item color="#a82e5f" label="-0.0980" alpha="255" value="-0.09804"/>
<item color="#b0315b" label="-0.0588" alpha="255" value="-0.058824"/>
<item color="#b73557" label="-0.0196" alpha="255" value="-0.019608"/>
<item color="#bf3952" label="0.0196" alpha="255" value="0.0196080000000001"/>
<item color="#c63d4d" label="0.0588" alpha="255" value="0.058824"/>
<item color="#cc4248" label="0.0980" alpha="255" value="0.0980399999999999"/>
<item color="#d34743" label="0.1373" alpha="255" value="0.137254"/>
<item color="#d94d3d" label="0.1765" alpha="255" value="0.17647"/>
<item color="#df5337" label="0.2157" alpha="255" value="0.215686"/>
<item color="#e45a31" label="0.2549" alpha="255" value="0.254902"/>
<item color="#e9612b" label="0.2941" alpha="255" value="0.294118"/>
<item color="#ed6925" label="0.3333" alpha="255" value="0.333334"/>
<item color="#f1711f" label="0.3725" alpha="255" value="0.37255"/>
<item color="#f47918" label="0.4118" alpha="255" value="0.411764"/>
<item color="#f78212" label="0.4510" alpha="255" value="0.45098"/>
<item color="#f98b0b" label="0.4902" alpha="255" value="0.490196"/>
<item color="#fa9407" label="0.5294" alpha="255" value="0.529412"/>
<item color="#fb9d07" label="0.5686" alpha="255" value="0.568628"/>
<item color="#fca60c" label="0.6078" alpha="255" value="0.607844"/>
<item color="#fcb014" label="0.6471" alpha="255" value="0.647058"/>
<item color="#fbba1f" label="0.6863" alpha="255" value="0.686274"/>
<item color="#fac42a" label="0.7255" alpha="255" value="0.72549"/>
<item color="#f8cd37" label="0.7647" alpha="255" value="0.764706"/>
<item color="#f6d746" label="0.8039" alpha="255" value="0.803922"/>
<item color="#f4e156" label="0.8431" alpha="255" value="0.843138"/>
<item color="#f2ea69" label="0.8824" alpha="255" value="0.882352"/>
<item color="#f2f27d" label="0.9216" alpha="255" value="0.921568"/>
<item color="#f5f992" label="0.9608" alpha="255" value="0.960784"/>
<item color="#fcffa4" label="1.0000" alpha="255" value="1"/>
<rampLegendSettings maximumLabel="" useContinuousLegend="1" direction="0" orientation="2" minimumLabel="" suffix="" prefix="">
<numericFormat id="basic">
<Option type="Map">
<Option type="invalid" name="decimal_separator"/>
<Option type="int" name="decimals" value="6"/>
<Option type="int" name="rounding_type" value="0"/>
<Option type="bool" name="show_plus" value="false"/>
<Option type="bool" name="show_thousand_separator" value="true"/>
<Option type="bool" name="show_trailing_zeros" value="false"/>
<Option type="invalid" name="thousand_separator"/>
</Option>
</numericFormat>
</rampLegendSettings>
</colorrampshader>
</rastershader>
</rasterrenderer>
<brightnesscontrast gamma="1" contrast="0" brightness="0"/>
<huesaturation colorizeGreen="128" colorizeBlue="128" colorizeOn="0" grayscaleMode="0" colorizeRed="255" colorizeStrength="100" saturation="0" invertColors="0"/>
<rasterresampler maxOversampling="2"/>
<resamplingStage>resamplingFilter</resamplingStage>
</pipe>
<blendMode>0</blendMode>
</qgis>
-158
View File
@@ -1,158 +0,0 @@
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
<qgis version="3.34.12-Prizren" hasScaleBasedVisibilityFlag="0" styleCategories="AllStyleCategories" minScale="1e+08" maxScale="0" autoRefreshMode="Disabled" autoRefreshTime="0">
<flags>
<Identifiable>1</Identifiable>
<Removable>1</Removable>
<Searchable>1</Searchable>
<Private>0</Private>
</flags>
<temporal enabled="0" mode="0" fetchMode="0">
<fixedRange>
<start></start>
<end></end>
</fixedRange>
</temporal>
<elevation band="1" enabled="0" zoffset="0" zscale="1" symbology="Line">
<data-defined-properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</data-defined-properties>
<profileLineSymbol>
<symbol name="" is_animated="0" alpha="1" clip_to_extent="1" force_rhr="0" type="line" frame_rate="10">
<data_defined_properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</data_defined_properties>
<layer class="SimpleLine" locked="0" enabled="1" pass="0" id="{3d86879d-0528-4a95-93c6-173beb7dfe55}">
<Option type="Map">
<Option name="align_dash_pattern" value="0" type="QString"/>
<Option name="capstyle" value="square" type="QString"/>
<Option name="customdash" value="5;2" type="QString"/>
<Option name="customdash_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="customdash_unit" value="MM" type="QString"/>
<Option name="dash_pattern_offset" value="0" type="QString"/>
<Option name="dash_pattern_offset_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="dash_pattern_offset_unit" value="MM" type="QString"/>
<Option name="draw_inside_polygon" value="0" type="QString"/>
<Option name="joinstyle" value="bevel" type="QString"/>
<Option name="line_color" value="243,166,178,255" type="QString"/>
<Option name="line_style" value="solid" type="QString"/>
<Option name="line_width" value="0.6" type="QString"/>
<Option name="line_width_unit" value="MM" type="QString"/>
<Option name="offset" value="0" type="QString"/>
<Option name="offset_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="offset_unit" value="MM" type="QString"/>
<Option name="ring_filter" value="0" type="QString"/>
<Option name="trim_distance_end" value="0" type="QString"/>
<Option name="trim_distance_end_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="trim_distance_end_unit" value="MM" type="QString"/>
<Option name="trim_distance_start" value="0" type="QString"/>
<Option name="trim_distance_start_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="trim_distance_start_unit" value="MM" type="QString"/>
<Option name="tweak_dash_pattern_on_corners" value="0" type="QString"/>
<Option name="use_custom_dash" value="0" type="QString"/>
<Option name="width_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</profileLineSymbol>
<profileFillSymbol>
<symbol name="" is_animated="0" alpha="1" clip_to_extent="1" force_rhr="0" type="fill" frame_rate="10">
<data_defined_properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</data_defined_properties>
<layer class="SimpleFill" locked="0" enabled="1" pass="0" id="{6c6808b7-5fd3-4cca-9202-5fcfee4e7b68}">
<Option type="Map">
<Option name="border_width_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="color" value="243,166,178,255" type="QString"/>
<Option name="joinstyle" value="bevel" type="QString"/>
<Option name="offset" value="0,0" type="QString"/>
<Option name="offset_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="offset_unit" value="MM" type="QString"/>
<Option name="outline_color" value="35,35,35,255" type="QString"/>
<Option name="outline_style" value="no" type="QString"/>
<Option name="outline_width" value="0.26" type="QString"/>
<Option name="outline_width_unit" value="MM" type="QString"/>
<Option name="style" value="solid" type="QString"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</profileFillSymbol>
</elevation>
<customproperties>
<Option type="Map">
<Option name="WMSBackgroundLayer" value="false" type="bool"/>
<Option name="WMSPublishDataSourceUrl" value="false" type="bool"/>
<Option name="embeddedWidgets/count" value="0" type="int"/>
<Option name="identify/format" value="Value" type="QString"/>
</Option>
</customproperties>
<mapTip enabled="1"></mapTip>
<pipe-data-defined-properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</pipe-data-defined-properties>
<pipe>
<provider>
<resampling maxOversampling="2" enabled="false" zoomedInResamplingMethod="nearestNeighbour" zoomedOutResamplingMethod="nearestNeighbour"/>
</provider>
<rasterrenderer nodataColor="" redBand="3" alphaBand="-1" blueBand="1" type="multibandcolor" opacity="1" greenBand="2">
<rasterTransparency/>
<minMaxOrigin>
<limits>CumulativeCut</limits>
<extent>WholeRaster</extent>
<statAccuracy>Estimated</statAccuracy>
<cumulativeCutLower>0.02</cumulativeCutLower>
<cumulativeCutUpper>0.98</cumulativeCutUpper>
<stdDevFactor>2</stdDevFactor>
</minMaxOrigin>
<redContrastEnhancement>
<minValue>-0.119304</minValue>
<maxValue>0.514984</maxValue>
<algorithm>StretchToMinimumMaximum</algorithm>
</redContrastEnhancement>
<greenContrastEnhancement>
<minValue>-0.119304</minValue>
<maxValue>0.168884</maxValue>
<algorithm>StretchToMinimumMaximum</algorithm>
</greenContrastEnhancement>
<blueContrastEnhancement>
<minValue>-0.119304</minValue>
<maxValue>0.149555</maxValue>
<algorithm>StretchToMinimumMaximum</algorithm>
</blueContrastEnhancement>
</rasterrenderer>
<brightnesscontrast gamma="1" contrast="0" brightness="0"/>
<huesaturation invertColors="0" grayscaleMode="0" colorizeStrength="100" colorizeOn="0" colorizeRed="255" colorizeGreen="128" colorizeBlue="128" saturation="0"/>
<rasterresampler maxOversampling="2"/>
<resamplingStage>resamplingFilter</resamplingStage>
</pipe>
<blendMode>0</blendMode>
</qgis>
-176
View File
@@ -1,176 +0,0 @@
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
<qgis minScale="1e+08" maxScale="0" styleCategories="AllStyleCategories" version="3.34.12-Prizren" hasScaleBasedVisibilityFlag="0" autoRefreshMode="Disabled" autoRefreshTime="0">
<flags>
<Identifiable>1</Identifiable>
<Removable>1</Removable>
<Searchable>1</Searchable>
<Private>0</Private>
</flags>
<temporal mode="0" enabled="0" fetchMode="0">
<fixedRange>
<start></start>
<end></end>
</fixedRange>
</temporal>
<elevation band="1" enabled="0" symbology="Line" zscale="1" zoffset="0">
<data-defined-properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
</Option>
</data-defined-properties>
<profileLineSymbol>
<symbol type="line" is_animated="0" clip_to_extent="1" force_rhr="0" name="" alpha="1" frame_rate="10">
<data_defined_properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
</Option>
</data_defined_properties>
<layer locked="0" pass="0" class="SimpleLine" id="{aaa7f6dd-c35e-4d35-8e65-5347167a8568}" enabled="1">
<Option type="Map">
<Option type="QString" name="align_dash_pattern" value="0"/>
<Option type="QString" name="capstyle" value="square"/>
<Option type="QString" name="customdash" value="5;2"/>
<Option type="QString" name="customdash_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="customdash_unit" value="MM"/>
<Option type="QString" name="dash_pattern_offset" value="0"/>
<Option type="QString" name="dash_pattern_offset_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="dash_pattern_offset_unit" value="MM"/>
<Option type="QString" name="draw_inside_polygon" value="0"/>
<Option type="QString" name="joinstyle" value="bevel"/>
<Option type="QString" name="line_color" value="164,113,88,255"/>
<Option type="QString" name="line_style" value="solid"/>
<Option type="QString" name="line_width" value="0.6"/>
<Option type="QString" name="line_width_unit" value="MM"/>
<Option type="QString" name="offset" value="0"/>
<Option type="QString" name="offset_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="offset_unit" value="MM"/>
<Option type="QString" name="ring_filter" value="0"/>
<Option type="QString" name="trim_distance_end" value="0"/>
<Option type="QString" name="trim_distance_end_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="trim_distance_end_unit" value="MM"/>
<Option type="QString" name="trim_distance_start" value="0"/>
<Option type="QString" name="trim_distance_start_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="trim_distance_start_unit" value="MM"/>
<Option type="QString" name="tweak_dash_pattern_on_corners" value="0"/>
<Option type="QString" name="use_custom_dash" value="0"/>
<Option type="QString" name="width_map_unit_scale" value="3x:0,0,0,0,0,0"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</profileLineSymbol>
<profileFillSymbol>
<symbol type="fill" is_animated="0" clip_to_extent="1" force_rhr="0" name="" alpha="1" frame_rate="10">
<data_defined_properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
</Option>
</data_defined_properties>
<layer locked="0" pass="0" class="SimpleFill" id="{b695104e-c25e-4ec7-bd5b-303e06061048}" enabled="1">
<Option type="Map">
<Option type="QString" name="border_width_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="color" value="164,113,88,255"/>
<Option type="QString" name="joinstyle" value="bevel"/>
<Option type="QString" name="offset" value="0,0"/>
<Option type="QString" name="offset_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="offset_unit" value="MM"/>
<Option type="QString" name="outline_color" value="35,35,35,255"/>
<Option type="QString" name="outline_style" value="no"/>
<Option type="QString" name="outline_width" value="0.26"/>
<Option type="QString" name="outline_width_unit" value="MM"/>
<Option type="QString" name="style" value="solid"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</profileFillSymbol>
</elevation>
<customproperties>
<Option type="Map">
<Option type="bool" name="WMSBackgroundLayer" value="false"/>
<Option type="bool" name="WMSPublishDataSourceUrl" value="false"/>
<Option type="int" name="embeddedWidgets/count" value="0"/>
<Option type="QString" name="identify/format" value="Value"/>
</Option>
</customproperties>
<mapTip enabled="1"></mapTip>
<pipe-data-defined-properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
</Option>
</pipe-data-defined-properties>
<pipe>
<provider>
<resampling maxOversampling="2" zoomedOutResamplingMethod="nearestNeighbour" enabled="false" zoomedInResamplingMethod="nearestNeighbour"/>
</provider>
<rasterrenderer opacity="1" alphaBand="-1" type="singlebandpseudocolor" band="1" classificationMin="0" classificationMax="1" nodataColor="">
<rasterTransparency/>
<minMaxOrigin>
<limits>None</limits>
<extent>WholeRaster</extent>
<statAccuracy>Estimated</statAccuracy>
<cumulativeCutLower>0.02</cumulativeCutLower>
<cumulativeCutUpper>0.98</cumulativeCutUpper>
<stdDevFactor>2</stdDevFactor>
</minMaxOrigin>
<rastershader>
<colorrampshader clip="0" labelPrecision="4" minimumValue="0" colorRampType="INTERPOLATED" maximumValue="1" classificationMode="1">
<colorramp type="gradient" name="[source]">
<Option type="Map">
<Option type="QString" name="color1" value="215,25,28,255"/>
<Option type="QString" name="color2" value="26,150,65,255"/>
<Option type="QString" name="direction" value="ccw"/>
<Option type="QString" name="discrete" value="0"/>
<Option type="QString" name="rampType" value="gradient"/>
<Option type="QString" name="spec" value="rgb"/>
<Option type="QString" name="stops" value="0.25;253,174,97,255;rgb;ccw:0.5;255,255,192,255;rgb;ccw:0.75;166,217,106,255;rgb;ccw"/>
</Option>
</colorramp>
<item color="#d7191c" label="0.0000" alpha="255" value="0"/>
<item color="#fdae61" label="0.2500" alpha="255" value="0.25"/>
<item color="#ffffc0" label="0.5000" alpha="255" value="0.5"/>
<item color="#a6d96a" label="0.7500" alpha="255" value="0.75"/>
<item color="#1a9641" label="1.0000" alpha="255" value="1"/>
<rampLegendSettings maximumLabel="" useContinuousLegend="1" direction="0" orientation="2" minimumLabel="" suffix="" prefix="">
<numericFormat id="basic">
<Option type="Map">
<Option type="invalid" name="decimal_separator"/>
<Option type="int" name="decimals" value="6"/>
<Option type="int" name="rounding_type" value="0"/>
<Option type="bool" name="show_plus" value="false"/>
<Option type="bool" name="show_thousand_separator" value="true"/>
<Option type="bool" name="show_trailing_zeros" value="false"/>
<Option type="invalid" name="thousand_separator"/>
</Option>
</numericFormat>
</rampLegendSettings>
</colorrampshader>
</rastershader>
</rasterrenderer>
<brightnesscontrast gamma="1" contrast="0" brightness="0"/>
<huesaturation colorizeGreen="128" colorizeBlue="128" colorizeOn="0" grayscaleMode="0" colorizeRed="255" colorizeStrength="100" saturation="0" invertColors="0"/>
<rasterresampler maxOversampling="2"/>
<resamplingStage>resamplingFilter</resamplingStage>
</pipe>
<blendMode>0</blendMode>
</qgis>
-176
View File
@@ -1,176 +0,0 @@
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
<qgis minScale="1e+08" autoRefreshTime="0" maxScale="0" version="3.34.12-Prizren" hasScaleBasedVisibilityFlag="0" styleCategories="AllStyleCategories" autoRefreshMode="Disabled">
<flags>
<Identifiable>1</Identifiable>
<Removable>1</Removable>
<Searchable>1</Searchable>
<Private>0</Private>
</flags>
<temporal fetchMode="0" enabled="0" mode="0">
<fixedRange>
<start></start>
<end></end>
</fixedRange>
</temporal>
<elevation symbology="Line" zscale="1" enabled="0" zoffset="0" band="1">
<data-defined-properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</data-defined-properties>
<profileLineSymbol>
<symbol force_rhr="0" name="" clip_to_extent="1" frame_rate="10" type="line" alpha="1" is_animated="0">
<data_defined_properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</data_defined_properties>
<layer id="{aaa7f6dd-c35e-4d35-8e65-5347167a8568}" enabled="1" class="SimpleLine" pass="0" locked="0">
<Option type="Map">
<Option name="align_dash_pattern" value="0" type="QString"/>
<Option name="capstyle" value="square" type="QString"/>
<Option name="customdash" value="5;2" type="QString"/>
<Option name="customdash_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="customdash_unit" value="MM" type="QString"/>
<Option name="dash_pattern_offset" value="0" type="QString"/>
<Option name="dash_pattern_offset_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="dash_pattern_offset_unit" value="MM" type="QString"/>
<Option name="draw_inside_polygon" value="0" type="QString"/>
<Option name="joinstyle" value="bevel" type="QString"/>
<Option name="line_color" value="164,113,88,255" type="QString"/>
<Option name="line_style" value="solid" type="QString"/>
<Option name="line_width" value="0.6" type="QString"/>
<Option name="line_width_unit" value="MM" type="QString"/>
<Option name="offset" value="0" type="QString"/>
<Option name="offset_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="offset_unit" value="MM" type="QString"/>
<Option name="ring_filter" value="0" type="QString"/>
<Option name="trim_distance_end" value="0" type="QString"/>
<Option name="trim_distance_end_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="trim_distance_end_unit" value="MM" type="QString"/>
<Option name="trim_distance_start" value="0" type="QString"/>
<Option name="trim_distance_start_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="trim_distance_start_unit" value="MM" type="QString"/>
<Option name="tweak_dash_pattern_on_corners" value="0" type="QString"/>
<Option name="use_custom_dash" value="0" type="QString"/>
<Option name="width_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</profileLineSymbol>
<profileFillSymbol>
<symbol force_rhr="0" name="" clip_to_extent="1" frame_rate="10" type="fill" alpha="1" is_animated="0">
<data_defined_properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</data_defined_properties>
<layer id="{b695104e-c25e-4ec7-bd5b-303e06061048}" enabled="1" class="SimpleFill" pass="0" locked="0">
<Option type="Map">
<Option name="border_width_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="color" value="164,113,88,255" type="QString"/>
<Option name="joinstyle" value="bevel" type="QString"/>
<Option name="offset" value="0,0" type="QString"/>
<Option name="offset_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="offset_unit" value="MM" type="QString"/>
<Option name="outline_color" value="35,35,35,255" type="QString"/>
<Option name="outline_style" value="no" type="QString"/>
<Option name="outline_width" value="0.26" type="QString"/>
<Option name="outline_width_unit" value="MM" type="QString"/>
<Option name="style" value="solid" type="QString"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</profileFillSymbol>
</elevation>
<customproperties>
<Option type="Map">
<Option name="WMSBackgroundLayer" value="false" type="bool"/>
<Option name="WMSPublishDataSourceUrl" value="false" type="bool"/>
<Option name="embeddedWidgets/count" value="0" type="int"/>
<Option name="identify/format" value="Value" type="QString"/>
</Option>
</customproperties>
<mapTip enabled="1"></mapTip>
<pipe-data-defined-properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</pipe-data-defined-properties>
<pipe>
<provider>
<resampling maxOversampling="2" enabled="false" zoomedInResamplingMethod="nearestNeighbour" zoomedOutResamplingMethod="nearestNeighbour"/>
</provider>
<rasterrenderer opacity="1" classificationMin="0" classificationMax="0.7596869" nodataColor="" type="singlebandpseudocolor" alphaBand="-1" band="1">
<rasterTransparency/>
<minMaxOrigin>
<limits>None</limits>
<extent>WholeRaster</extent>
<statAccuracy>Estimated</statAccuracy>
<cumulativeCutLower>0.02</cumulativeCutLower>
<cumulativeCutUpper>0.98</cumulativeCutUpper>
<stdDevFactor>2</stdDevFactor>
</minMaxOrigin>
<rastershader>
<colorrampshader maximumValue="0.75968690000000005" labelPrecision="4" colorRampType="INTERPOLATED" minimumValue="0" clip="0" classificationMode="1">
<colorramp name="[source]" type="gradient">
<Option type="Map">
<Option name="color1" value="215,25,28,255" type="QString"/>
<Option name="color2" value="26,150,65,255" type="QString"/>
<Option name="direction" value="ccw" type="QString"/>
<Option name="discrete" value="0" type="QString"/>
<Option name="rampType" value="gradient" type="QString"/>
<Option name="spec" value="rgb" type="QString"/>
<Option name="stops" value="0.25;253,174,97,255;rgb;ccw:0.5;255,255,192,255;rgb;ccw:0.75;166,217,106,255;rgb;ccw" type="QString"/>
</Option>
</colorramp>
<item value="0" color="#d7191c" label="0.0000" alpha="255"/>
<item value="0.189921721816063" color="#fdae61" label="0.1899" alpha="255"/>
<item value="0.379843443632125" color="#ffffc0" label="0.3798" alpha="255"/>
<item value="0.569765165448188" color="#a6d96a" label="0.5698" alpha="255"/>
<item value="0.75968688726425" color="#1a9641" label="0.7597" alpha="255"/>
<rampLegendSettings orientation="2" maximumLabel="" suffix="" prefix="" useContinuousLegend="1" minimumLabel="" direction="0">
<numericFormat id="basic">
<Option type="Map">
<Option name="decimal_separator" type="invalid"/>
<Option name="decimals" value="6" type="int"/>
<Option name="rounding_type" value="0" type="int"/>
<Option name="show_plus" value="false" type="bool"/>
<Option name="show_thousand_separator" value="true" type="bool"/>
<Option name="show_trailing_zeros" value="false" type="bool"/>
<Option name="thousand_separator" type="invalid"/>
</Option>
</numericFormat>
</rampLegendSettings>
</colorrampshader>
</rastershader>
</rasterrenderer>
<brightnesscontrast gamma="1" contrast="0" brightness="0"/>
<huesaturation invertColors="0" grayscaleMode="0" colorizeRed="255" colorizeOn="0" colorizeBlue="128" saturation="0" colorizeGreen="128" colorizeStrength="100"/>
<rasterresampler maxOversampling="2"/>
<resamplingStage>resamplingFilter</resamplingStage>
</pipe>
<blendMode>0</blendMode>
</qgis>
-172
View File
@@ -1,172 +0,0 @@
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
<qgis hasScaleBasedVisibilityFlag="0" minScale="1e+08" maxScale="0" autoRefreshMode="Disabled" autoRefreshTime="0" version="3.34.12-Prizren" styleCategories="AllStyleCategories">
<flags>
<Identifiable>1</Identifiable>
<Removable>1</Removable>
<Searchable>1</Searchable>
<Private>0</Private>
</flags>
<temporal fetchMode="0" enabled="0" mode="0">
<fixedRange>
<start></start>
<end></end>
</fixedRange>
</temporal>
<elevation band="1" enabled="0" zscale="1" zoffset="0" symbology="Line">
<data-defined-properties>
<Option type="Map">
<Option value="" name="name" type="QString"/>
<Option name="properties"/>
<Option value="collection" name="type" type="QString"/>
</Option>
</data-defined-properties>
<profileLineSymbol>
<symbol is_animated="0" name="" type="line" alpha="1" clip_to_extent="1" force_rhr="0" frame_rate="10">
<data_defined_properties>
<Option type="Map">
<Option value="" name="name" type="QString"/>
<Option name="properties"/>
<Option value="collection" name="type" type="QString"/>
</Option>
</data_defined_properties>
<layer enabled="1" class="SimpleLine" locked="0" pass="0" id="{99ba9813-b865-4da2-bbb6-acad204f8b25}">
<Option type="Map">
<Option value="0" name="align_dash_pattern" type="QString"/>
<Option value="square" name="capstyle" type="QString"/>
<Option value="5;2" name="customdash" type="QString"/>
<Option value="3x:0,0,0,0,0,0" name="customdash_map_unit_scale" type="QString"/>
<Option value="MM" name="customdash_unit" type="QString"/>
<Option value="0" name="dash_pattern_offset" type="QString"/>
<Option value="3x:0,0,0,0,0,0" name="dash_pattern_offset_map_unit_scale" type="QString"/>
<Option value="MM" name="dash_pattern_offset_unit" type="QString"/>
<Option value="0" name="draw_inside_polygon" type="QString"/>
<Option value="bevel" name="joinstyle" type="QString"/>
<Option value="243,166,178,255" name="line_color" type="QString"/>
<Option value="solid" name="line_style" type="QString"/>
<Option value="0.6" name="line_width" type="QString"/>
<Option value="MM" name="line_width_unit" type="QString"/>
<Option value="0" name="offset" type="QString"/>
<Option value="3x:0,0,0,0,0,0" name="offset_map_unit_scale" type="QString"/>
<Option value="MM" name="offset_unit" type="QString"/>
<Option value="0" name="ring_filter" type="QString"/>
<Option value="0" name="trim_distance_end" type="QString"/>
<Option value="3x:0,0,0,0,0,0" name="trim_distance_end_map_unit_scale" type="QString"/>
<Option value="MM" name="trim_distance_end_unit" type="QString"/>
<Option value="0" name="trim_distance_start" type="QString"/>
<Option value="3x:0,0,0,0,0,0" name="trim_distance_start_map_unit_scale" type="QString"/>
<Option value="MM" name="trim_distance_start_unit" type="QString"/>
<Option value="0" name="tweak_dash_pattern_on_corners" type="QString"/>
<Option value="0" name="use_custom_dash" type="QString"/>
<Option value="3x:0,0,0,0,0,0" name="width_map_unit_scale" type="QString"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option value="" name="name" type="QString"/>
<Option name="properties"/>
<Option value="collection" name="type" type="QString"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</profileLineSymbol>
<profileFillSymbol>
<symbol is_animated="0" name="" type="fill" alpha="1" clip_to_extent="1" force_rhr="0" frame_rate="10">
<data_defined_properties>
<Option type="Map">
<Option value="" name="name" type="QString"/>
<Option name="properties"/>
<Option value="collection" name="type" type="QString"/>
</Option>
</data_defined_properties>
<layer enabled="1" class="SimpleFill" locked="0" pass="0" id="{fd457c65-1070-4be2-a580-abb79399910b}">
<Option type="Map">
<Option value="3x:0,0,0,0,0,0" name="border_width_map_unit_scale" type="QString"/>
<Option value="243,166,178,255" name="color" type="QString"/>
<Option value="bevel" name="joinstyle" type="QString"/>
<Option value="0,0" name="offset" type="QString"/>
<Option value="3x:0,0,0,0,0,0" name="offset_map_unit_scale" type="QString"/>
<Option value="MM" name="offset_unit" type="QString"/>
<Option value="35,35,35,255" name="outline_color" type="QString"/>
<Option value="no" name="outline_style" type="QString"/>
<Option value="0.26" name="outline_width" type="QString"/>
<Option value="MM" name="outline_width_unit" type="QString"/>
<Option value="solid" name="style" type="QString"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option value="" name="name" type="QString"/>
<Option name="properties"/>
<Option value="collection" name="type" type="QString"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</profileFillSymbol>
</elevation>
<customproperties>
<Option type="Map">
<Option value="false" name="WMSBackgroundLayer" type="bool"/>
<Option value="false" name="WMSPublishDataSourceUrl" type="bool"/>
<Option value="0" name="embeddedWidgets/count" type="int"/>
<Option value="Value" name="identify/format" type="QString"/>
</Option>
</customproperties>
<mapTip enabled="1"></mapTip>
<pipe-data-defined-properties>
<Option type="Map">
<Option value="" name="name" type="QString"/>
<Option name="properties"/>
<Option value="collection" name="type" type="QString"/>
</Option>
</pipe-data-defined-properties>
<pipe>
<provider>
<resampling enabled="false" zoomedOutResamplingMethod="nearestNeighbour" zoomedInResamplingMethod="nearestNeighbour" maxOversampling="2"/>
</provider>
<rasterrenderer band="1" alphaBand="-1" classificationMin="0.3" classificationMax="1" opacity="1" nodataColor="" type="singlebandpseudocolor">
<rasterTransparency/>
<minMaxOrigin>
<limits>None</limits>
<extent>WholeRaster</extent>
<statAccuracy>Estimated</statAccuracy>
<cumulativeCutLower>0.02</cumulativeCutLower>
<cumulativeCutUpper>0.98</cumulativeCutUpper>
<stdDevFactor>2</stdDevFactor>
</minMaxOrigin>
<rastershader>
<colorrampshader minimumValue="0.29999999999999999" labelPrecision="4" colorRampType="DISCRETE" classificationMode="2" maximumValue="1" clip="0">
<colorramp name="[source]" type="gradient">
<Option type="Map">
<Option value="215,25,28,0" name="color1" type="QString"/>
<Option value="29,10,150,255" name="color2" type="QString"/>
<Option value="ccw" name="direction" type="QString"/>
<Option value="0" name="discrete" type="QString"/>
<Option value="gradient" name="rampType" type="QString"/>
<Option value="rgb" name="spec" type="QString"/>
</Option>
</colorramp>
<item value="0.3" color="#d7191c" label="&lt;= 0.3000" alpha="0"/>
<item value="1" color="#1d0a96" label="0.3000 - 1.0000" alpha="255"/>
<rampLegendSettings maximumLabel="" suffix="" orientation="2" prefix="" useContinuousLegend="1" minimumLabel="" direction="0">
<numericFormat id="basic">
<Option type="Map">
<Option name="decimal_separator" type="invalid"/>
<Option value="6" name="decimals" type="int"/>
<Option value="0" name="rounding_type" type="int"/>
<Option value="false" name="show_plus" type="bool"/>
<Option value="true" name="show_thousand_separator" type="bool"/>
<Option value="false" name="show_trailing_zeros" type="bool"/>
<Option name="thousand_separator" type="invalid"/>
</Option>
</numericFormat>
</rampLegendSettings>
</colorrampshader>
</rastershader>
</rasterrenderer>
<brightnesscontrast gamma="1" contrast="0" brightness="0"/>
<huesaturation colorizeGreen="128" colorizeRed="255" colorizeBlue="128" colorizeOn="0" grayscaleMode="0" colorizeStrength="100" saturation="0" invertColors="0"/>
<rasterresampler maxOversampling="2"/>
<resamplingStage>resamplingFilter</resamplingStage>
</pipe>
<blendMode>0</blendMode>
</qgis>
-180
View File
@@ -1,180 +0,0 @@
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
<qgis minScale="1e+08" autoRefreshTime="0" maxScale="0" version="3.34.12-Prizren" hasScaleBasedVisibilityFlag="0" styleCategories="AllStyleCategories" autoRefreshMode="Disabled">
<flags>
<Identifiable>1</Identifiable>
<Removable>1</Removable>
<Searchable>1</Searchable>
<Private>0</Private>
</flags>
<temporal fetchMode="0" enabled="0" mode="0">
<fixedRange>
<start></start>
<end></end>
</fixedRange>
</temporal>
<elevation symbology="Line" zscale="1" enabled="0" zoffset="0" band="1">
<data-defined-properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</data-defined-properties>
<profileLineSymbol>
<symbol force_rhr="0" name="" clip_to_extent="1" frame_rate="10" type="line" alpha="1" is_animated="0">
<data_defined_properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</data_defined_properties>
<layer id="{f0727dba-6c15-410e-a4de-645ce35a3a77}" enabled="1" class="SimpleLine" pass="0" locked="0">
<Option type="Map">
<Option name="align_dash_pattern" value="0" type="QString"/>
<Option name="capstyle" value="square" type="QString"/>
<Option name="customdash" value="5;2" type="QString"/>
<Option name="customdash_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="customdash_unit" value="MM" type="QString"/>
<Option name="dash_pattern_offset" value="0" type="QString"/>
<Option name="dash_pattern_offset_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="dash_pattern_offset_unit" value="MM" type="QString"/>
<Option name="draw_inside_polygon" value="0" type="QString"/>
<Option name="joinstyle" value="bevel" type="QString"/>
<Option name="line_color" value="231,113,72,255" type="QString"/>
<Option name="line_style" value="solid" type="QString"/>
<Option name="line_width" value="0.6" type="QString"/>
<Option name="line_width_unit" value="MM" type="QString"/>
<Option name="offset" value="0" type="QString"/>
<Option name="offset_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="offset_unit" value="MM" type="QString"/>
<Option name="ring_filter" value="0" type="QString"/>
<Option name="trim_distance_end" value="0" type="QString"/>
<Option name="trim_distance_end_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="trim_distance_end_unit" value="MM" type="QString"/>
<Option name="trim_distance_start" value="0" type="QString"/>
<Option name="trim_distance_start_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="trim_distance_start_unit" value="MM" type="QString"/>
<Option name="tweak_dash_pattern_on_corners" value="0" type="QString"/>
<Option name="use_custom_dash" value="0" type="QString"/>
<Option name="width_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</profileLineSymbol>
<profileFillSymbol>
<symbol force_rhr="0" name="" clip_to_extent="1" frame_rate="10" type="fill" alpha="1" is_animated="0">
<data_defined_properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</data_defined_properties>
<layer id="{9c243aaf-373e-405c-9930-44db50dc2819}" enabled="1" class="SimpleFill" pass="0" locked="0">
<Option type="Map">
<Option name="border_width_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="color" value="231,113,72,255" type="QString"/>
<Option name="joinstyle" value="bevel" type="QString"/>
<Option name="offset" value="0,0" type="QString"/>
<Option name="offset_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="offset_unit" value="MM" type="QString"/>
<Option name="outline_color" value="35,35,35,255" type="QString"/>
<Option name="outline_style" value="no" type="QString"/>
<Option name="outline_width" value="0.26" type="QString"/>
<Option name="outline_width_unit" value="MM" type="QString"/>
<Option name="style" value="solid" type="QString"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</profileFillSymbol>
</elevation>
<customproperties>
<Option type="Map">
<Option name="WMSBackgroundLayer" value="false" type="bool"/>
<Option name="WMSPublishDataSourceUrl" value="false" type="bool"/>
<Option name="embeddedWidgets/count" value="0" type="int"/>
<Option name="identify/format" value="Value" type="QString"/>
</Option>
</customproperties>
<mapTip enabled="1"></mapTip>
<pipe-data-defined-properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</pipe-data-defined-properties>
<pipe>
<provider>
<resampling maxOversampling="2" enabled="false" zoomedInResamplingMethod="nearestNeighbour" zoomedOutResamplingMethod="nearestNeighbour"/>
</provider>
<rasterrenderer opacity="1" classificationMin="0" classificationMax="0.2" nodataColor="" type="singlebandpseudocolor" alphaBand="-1" band="1">
<rasterTransparency/>
<minMaxOrigin>
<limits>None</limits>
<extent>WholeRaster</extent>
<statAccuracy>Estimated</statAccuracy>
<cumulativeCutLower>0.02</cumulativeCutLower>
<cumulativeCutUpper>0.98</cumulativeCutUpper>
<stdDevFactor>2</stdDevFactor>
</minMaxOrigin>
<rastershader>
<colorrampshader maximumValue="0.20000000000000001" labelPrecision="4" colorRampType="INTERPOLATED" minimumValue="0" clip="0" classificationMode="1">
<colorramp name="[source]" type="gradient">
<Option type="Map">
<Option name="color1" value="247,251,255,255" type="QString"/>
<Option name="color2" value="8,48,107,255" type="QString"/>
<Option name="direction" value="ccw" type="QString"/>
<Option name="discrete" value="0" type="QString"/>
<Option name="rampType" value="gradient" type="QString"/>
<Option name="spec" value="rgb" type="QString"/>
<Option name="stops" value="0.13;222,235,247,255;rgb;ccw:0.26;198,219,239,255;rgb;ccw:0.39;158,202,225,255;rgb;ccw:0.52;107,174,214,255;rgb;ccw:0.65;66,146,198,255;rgb;ccw:0.78;33,113,181,255;rgb;ccw:0.9;8,81,156,255;rgb;ccw" type="QString"/>
</Option>
</colorramp>
<item value="0" color="#f7fbff" label="0.0000" alpha="255"/>
<item value="0.026" color="#deebf7" label="0.0260" alpha="255"/>
<item value="0.052" color="#c6dbef" label="0.0520" alpha="255"/>
<item value="0.078" color="#9ecae1" label="0.0780" alpha="255"/>
<item value="0.104" color="#6baed6" label="0.1040" alpha="255"/>
<item value="0.13" color="#4292c6" label="0.1300" alpha="255"/>
<item value="0.156" color="#2171b5" label="0.1560" alpha="255"/>
<item value="0.18" color="#08519c" label="0.1800" alpha="255"/>
<item value="0.2" color="#08306b" label="0.2000" alpha="255"/>
<rampLegendSettings orientation="2" maximumLabel="" suffix="" prefix="" useContinuousLegend="1" minimumLabel="" direction="0">
<numericFormat id="basic">
<Option type="Map">
<Option name="decimal_separator" type="invalid"/>
<Option name="decimals" value="6" type="int"/>
<Option name="rounding_type" value="0" type="int"/>
<Option name="show_plus" value="false" type="bool"/>
<Option name="show_thousand_separator" value="true" type="bool"/>
<Option name="show_trailing_zeros" value="false" type="bool"/>
<Option name="thousand_separator" type="invalid"/>
</Option>
</numericFormat>
</rampLegendSettings>
</colorrampshader>
</rastershader>
</rasterrenderer>
<brightnesscontrast gamma="1" contrast="0" brightness="0"/>
<huesaturation invertColors="0" grayscaleMode="0" colorizeRed="255" colorizeOn="0" colorizeBlue="128" saturation="0" colorizeGreen="128" colorizeStrength="100"/>
<rasterresampler maxOversampling="2"/>
<resamplingStage>resamplingFilter</resamplingStage>
</pipe>
<blendMode>0</blendMode>
</qgis>
@@ -1,5 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" height="348" width="226">
<path d="M5.53,240.17l108.38-113.54,106.91,112.07-106.91-229.3z" stroke="#000" stroke-width="6" fill="none"/>
<path d="m113.91,9.2162,0,117.41,106.36,111.33z"/>
<path d="m145.05,321.47-10.375,0-44.125-74.375,0.125,5.625c0.12498,2.1251,0.18748,3.9167,0.1875,5.375v63.375h-8.625v-85.312h13.375l41.25,69.562-0.125-5.9375c-0.0834-2.3333-0.12506-4.3958-0.125-6.1875v-57.438h8.4375z"/>
</svg>

Before

Width:  |  Height:  |  Size: 455 B

@@ -1,176 +0,0 @@
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
<qgis version="3.34.12-Prizren" hasScaleBasedVisibilityFlag="0" styleCategories="AllStyleCategories" minScale="1e+08" maxScale="0" autoRefreshMode="Disabled" autoRefreshTime="0">
<flags>
<Identifiable>1</Identifiable>
<Removable>1</Removable>
<Searchable>1</Searchable>
<Private>0</Private>
</flags>
<temporal enabled="0" mode="0" fetchMode="0">
<fixedRange>
<start></start>
<end></end>
</fixedRange>
</temporal>
<elevation band="1" enabled="0" zoffset="0" zscale="1" symbology="Line">
<data-defined-properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</data-defined-properties>
<profileLineSymbol>
<symbol name="" is_animated="0" alpha="1" clip_to_extent="1" force_rhr="0" type="line" frame_rate="10">
<data_defined_properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</data_defined_properties>
<layer class="SimpleLine" locked="0" enabled="1" pass="0" id="{cb94a686-abc6-45a2-b47c-962b72fe165b}">
<Option type="Map">
<Option name="align_dash_pattern" value="0" type="QString"/>
<Option name="capstyle" value="square" type="QString"/>
<Option name="customdash" value="5;2" type="QString"/>
<Option name="customdash_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="customdash_unit" value="MM" type="QString"/>
<Option name="dash_pattern_offset" value="0" type="QString"/>
<Option name="dash_pattern_offset_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="dash_pattern_offset_unit" value="MM" type="QString"/>
<Option name="draw_inside_polygon" value="0" type="QString"/>
<Option name="joinstyle" value="bevel" type="QString"/>
<Option name="line_color" value="190,178,151,255" type="QString"/>
<Option name="line_style" value="solid" type="QString"/>
<Option name="line_width" value="0.6" type="QString"/>
<Option name="line_width_unit" value="MM" type="QString"/>
<Option name="offset" value="0" type="QString"/>
<Option name="offset_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="offset_unit" value="MM" type="QString"/>
<Option name="ring_filter" value="0" type="QString"/>
<Option name="trim_distance_end" value="0" type="QString"/>
<Option name="trim_distance_end_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="trim_distance_end_unit" value="MM" type="QString"/>
<Option name="trim_distance_start" value="0" type="QString"/>
<Option name="trim_distance_start_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="trim_distance_start_unit" value="MM" type="QString"/>
<Option name="tweak_dash_pattern_on_corners" value="0" type="QString"/>
<Option name="use_custom_dash" value="0" type="QString"/>
<Option name="width_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</profileLineSymbol>
<profileFillSymbol>
<symbol name="" is_animated="0" alpha="1" clip_to_extent="1" force_rhr="0" type="fill" frame_rate="10">
<data_defined_properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</data_defined_properties>
<layer class="SimpleFill" locked="0" enabled="1" pass="0" id="{b9a48ebb-e4c4-4d4e-bda2-50e4d13036b9}">
<Option type="Map">
<Option name="border_width_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="color" value="190,178,151,255" type="QString"/>
<Option name="joinstyle" value="bevel" type="QString"/>
<Option name="offset" value="0,0" type="QString"/>
<Option name="offset_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="offset_unit" value="MM" type="QString"/>
<Option name="outline_color" value="35,35,35,255" type="QString"/>
<Option name="outline_style" value="no" type="QString"/>
<Option name="outline_width" value="0.26" type="QString"/>
<Option name="outline_width_unit" value="MM" type="QString"/>
<Option name="style" value="solid" type="QString"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</profileFillSymbol>
</elevation>
<customproperties>
<Option type="Map">
<Option name="WMSBackgroundLayer" value="false" type="bool"/>
<Option name="WMSPublishDataSourceUrl" value="false" type="bool"/>
<Option name="embeddedWidgets/count" value="0" type="int"/>
<Option name="identify/format" value="Value" type="QString"/>
</Option>
</customproperties>
<mapTip enabled="1"></mapTip>
<pipe-data-defined-properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</pipe-data-defined-properties>
<pipe>
<provider>
<resampling maxOversampling="2" enabled="false" zoomedInResamplingMethod="nearestNeighbour" zoomedOutResamplingMethod="nearestNeighbour"/>
</provider>
<rasterrenderer nodataColor="" band="1" alphaBand="-1" classificationMin="0" classificationMax="44.2479858" type="singlebandpseudocolor" opacity="1">
<rasterTransparency/>
<minMaxOrigin>
<limits>None</limits>
<extent>WholeRaster</extent>
<statAccuracy>Estimated</statAccuracy>
<cumulativeCutLower>0.02</cumulativeCutLower>
<cumulativeCutUpper>0.98</cumulativeCutUpper>
<stdDevFactor>2</stdDevFactor>
</minMaxOrigin>
<rastershader>
<colorrampshader classificationMode="1" maximumValue="44.247985800000002" colorRampType="INTERPOLATED" labelPrecision="4" minimumValue="0" clip="0">
<colorramp name="[source]" type="gradient">
<Option type="Map">
<Option name="color1" value="5,113,176,0" type="QString"/>
<Option name="color2" value="202,0,32,255" type="QString"/>
<Option name="direction" value="ccw" type="QString"/>
<Option name="discrete" value="0" type="QString"/>
<Option name="rampType" value="gradient" type="QString"/>
<Option name="spec" value="rgb" type="QString"/>
<Option name="stops" value="0.25;146,197,222,255;rgb;ccw:0.5;247,247,247,255;rgb;ccw:0.75;244,165,130,255;rgb;ccw" type="QString"/>
</Option>
</colorramp>
<item label="0.0000" alpha="0" value="0" color="#0571b0"/>
<item label="11.0620" alpha="255" value="11.06199645" color="#92c5de"/>
<item label="22.1240" alpha="255" value="22.1239929" color="#f7f7f7"/>
<item label="33.1860" alpha="255" value="33.18598935" color="#f4a582"/>
<item label="44.2480" alpha="255" value="44.2479858" color="#ca0020"/>
<rampLegendSettings minimumLabel="" useContinuousLegend="1" maximumLabel="" direction="0" suffix="" orientation="2" prefix="">
<numericFormat id="basic">
<Option type="Map">
<Option name="decimal_separator" type="invalid"/>
<Option name="decimals" value="6" type="int"/>
<Option name="rounding_type" value="0" type="int"/>
<Option name="show_plus" value="false" type="bool"/>
<Option name="show_thousand_separator" value="true" type="bool"/>
<Option name="show_trailing_zeros" value="false" type="bool"/>
<Option name="thousand_separator" type="invalid"/>
</Option>
</numericFormat>
</rampLegendSettings>
</colorrampshader>
</rastershader>
</rasterrenderer>
<brightnesscontrast gamma="1" contrast="0" brightness="0"/>
<huesaturation invertColors="0" grayscaleMode="0" colorizeStrength="100" colorizeOn="0" colorizeRed="255" colorizeGreen="128" colorizeBlue="128" saturation="0"/>
<rasterresampler maxOversampling="2"/>
<resamplingStage>resamplingFilter</resamplingStage>
</pipe>
<blendMode>0</blendMode>
</qgis>
-158
View File
@@ -1,158 +0,0 @@
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
<qgis version="3.34.12-Prizren" hasScaleBasedVisibilityFlag="0" styleCategories="AllStyleCategories" minScale="1e+08" maxScale="0" autoRefreshMode="Disabled" autoRefreshTime="0">
<flags>
<Identifiable>1</Identifiable>
<Removable>1</Removable>
<Searchable>1</Searchable>
<Private>0</Private>
</flags>
<temporal enabled="0" mode="0" fetchMode="0">
<fixedRange>
<start></start>
<end></end>
</fixedRange>
</temporal>
<elevation band="1" enabled="0" zoffset="0" zscale="1" symbology="Line">
<data-defined-properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</data-defined-properties>
<profileLineSymbol>
<symbol name="" is_animated="0" alpha="1" clip_to_extent="1" force_rhr="0" type="line" frame_rate="10">
<data_defined_properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</data_defined_properties>
<layer class="SimpleLine" locked="0" enabled="1" pass="0" id="{42348ace-1922-48ab-bbe5-7063be49abaf}">
<Option type="Map">
<Option name="align_dash_pattern" value="0" type="QString"/>
<Option name="capstyle" value="square" type="QString"/>
<Option name="customdash" value="5;2" type="QString"/>
<Option name="customdash_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="customdash_unit" value="MM" type="QString"/>
<Option name="dash_pattern_offset" value="0" type="QString"/>
<Option name="dash_pattern_offset_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="dash_pattern_offset_unit" value="MM" type="QString"/>
<Option name="draw_inside_polygon" value="0" type="QString"/>
<Option name="joinstyle" value="bevel" type="QString"/>
<Option name="line_color" value="152,125,183,255" type="QString"/>
<Option name="line_style" value="solid" type="QString"/>
<Option name="line_width" value="0.6" type="QString"/>
<Option name="line_width_unit" value="MM" type="QString"/>
<Option name="offset" value="0" type="QString"/>
<Option name="offset_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="offset_unit" value="MM" type="QString"/>
<Option name="ring_filter" value="0" type="QString"/>
<Option name="trim_distance_end" value="0" type="QString"/>
<Option name="trim_distance_end_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="trim_distance_end_unit" value="MM" type="QString"/>
<Option name="trim_distance_start" value="0" type="QString"/>
<Option name="trim_distance_start_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="trim_distance_start_unit" value="MM" type="QString"/>
<Option name="tweak_dash_pattern_on_corners" value="0" type="QString"/>
<Option name="use_custom_dash" value="0" type="QString"/>
<Option name="width_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</profileLineSymbol>
<profileFillSymbol>
<symbol name="" is_animated="0" alpha="1" clip_to_extent="1" force_rhr="0" type="fill" frame_rate="10">
<data_defined_properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</data_defined_properties>
<layer class="SimpleFill" locked="0" enabled="1" pass="0" id="{3c87b40f-2c76-4731-b363-09dce0e2f69b}">
<Option type="Map">
<Option name="border_width_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="color" value="152,125,183,255" type="QString"/>
<Option name="joinstyle" value="bevel" type="QString"/>
<Option name="offset" value="0,0" type="QString"/>
<Option name="offset_map_unit_scale" value="3x:0,0,0,0,0,0" type="QString"/>
<Option name="offset_unit" value="MM" type="QString"/>
<Option name="outline_color" value="35,35,35,255" type="QString"/>
<Option name="outline_style" value="no" type="QString"/>
<Option name="outline_width" value="0.26" type="QString"/>
<Option name="outline_width_unit" value="MM" type="QString"/>
<Option name="style" value="solid" type="QString"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</profileFillSymbol>
</elevation>
<customproperties>
<Option type="Map">
<Option name="WMSBackgroundLayer" value="false" type="bool"/>
<Option name="WMSPublishDataSourceUrl" value="false" type="bool"/>
<Option name="embeddedWidgets/count" value="0" type="int"/>
<Option name="identify/format" value="Value" type="QString"/>
</Option>
</customproperties>
<mapTip enabled="1"></mapTip>
<pipe-data-defined-properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</pipe-data-defined-properties>
<pipe>
<provider>
<resampling maxOversampling="2" enabled="false" zoomedInResamplingMethod="nearestNeighbour" zoomedOutResamplingMethod="nearestNeighbour"/>
</provider>
<rasterrenderer nodataColor="" redBand="3" alphaBand="-1" blueBand="1" type="multibandcolor" opacity="1" greenBand="2">
<rasterTransparency/>
<minMaxOrigin>
<limits>CumulativeCut</limits>
<extent>WholeRaster</extent>
<statAccuracy>Estimated</statAccuracy>
<cumulativeCutLower>0.02</cumulativeCutLower>
<cumulativeCutUpper>0.98</cumulativeCutUpper>
<stdDevFactor>2</stdDevFactor>
</minMaxOrigin>
<redContrastEnhancement>
<minValue>-0.119304</minValue>
<maxValue>0.168884</maxValue>
<algorithm>StretchToMinimumMaximum</algorithm>
</redContrastEnhancement>
<greenContrastEnhancement>
<minValue>-0.119304</minValue>
<maxValue>0.149555</maxValue>
<algorithm>StretchToMinimumMaximum</algorithm>
</greenContrastEnhancement>
<blueContrastEnhancement>
<minValue>-0.119304</minValue>
<maxValue>0.143137</maxValue>
<algorithm>StretchToMinimumMaximum</algorithm>
</blueContrastEnhancement>
</rasterrenderer>
<brightnesscontrast gamma="1" contrast="0" brightness="0"/>
<huesaturation invertColors="0" grayscaleMode="0" colorizeStrength="100" colorizeOn="0" colorizeRed="255" colorizeGreen="128" colorizeBlue="128" saturation="0"/>
<rasterresampler maxOversampling="2"/>
<resamplingStage>resamplingFilter</resamplingStage>
</pipe>
<blendMode>0</blendMode>
</qgis>
@@ -14,19 +14,16 @@ def tif_to_array(path):
return data, array
def handle_nodata(array):
# Replace only negative values with NaN
clean_array = np.where(array < 0, np.nan, array)
return clean_array
def reflectance_calc(array, reflectance_mult, reflectance_add, sun_elevation):
# Debugging print statements
print(f"Reflectance Mult: {reflectance_mult}, Reflectance Add: {reflectance_add}, Sun Elevation: {sun_elevation}")
print(f"Array Sample Before: {array[:5, :5]}") # Print a small portion of the array for inspection
print(f"Array Sample Before: {array[:5, :5]}")
result = ((array * reflectance_mult) + reflectance_add) / math.sin(math.radians(sun_elevation))
# Debugging print statements
print(f"Array Sample After: {result[:5, :5]}") # Print a small portion of the result for inspection
print(f"Array Sample After: {result[:5, :5]}")
return result
def save_tif(array, data, output_path):
@@ -44,7 +41,6 @@ def save_tif(array, data, output_path):
def get_output_path(output_dir, input_path, suffix):
basename = os.path.basename(input_path)
basename_no_ext = os.path.splitext(basename)[0]
# basename_no_ext = re.sub(r'_B[1-9]|_B10|_B11', '', basename_no_ext)
path = os.path.join(output_dir, f"{basename_no_ext}_{suffix}.TIF")
return path
@@ -66,11 +62,9 @@ def get_reflectance_params(band_number, metadata_lines):
return reflectance_mult, reflectance_add
def process_bands(band_paths, metadata_path, output_dir):
# Read metadata
with open(metadata_path, "r") as file:
metadata_lines = file.readlines()
# Extract sun elevation
sun_elevation = None
for line in metadata_lines:
if "SUN_ELEVATION" in line:
@@ -81,30 +75,23 @@ def process_bands(band_paths, metadata_path, output_dir):
if sun_elevation is None:
raise ValueError("Sun elevation not found in metadata.")
# Debugging sun elevation value
print(f"Sun Elevation: {sun_elevation}, Sun Elevation Radians: {math.radians(sun_elevation)}")
# Process each band
for band_path in band_paths:
band_number = int(re.search(r'_B(\d+)', band_path).group(1))
data, array = tif_to_array(band_path)
array = handle_nodata(array)
# Get reflectance parameters for the band
reflectance_mult, reflectance_add = get_reflectance_params(band_number, metadata_lines)
# Calculate reflectance for the band
reflectance = reflectance_calc(array, reflectance_mult, reflectance_add, sun_elevation)
# Create output directory if it doesn't exist
if not os.path.exists(output_dir):
os.makedirs(output_dir)
# Save Top of Atmosphere (TOA) reflectance for the band
output_path = get_output_path(output_dir, band_path, f"toa")
save_tif(reflectance, data, output_path)
# Print min and max for the reflectance band
print_min_max(reflectance, f"Band {band_number} Reflectance")
def main():