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

|
||||
|
||||
## 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
|
||||
|
||||

|
||||
|
||||
## Question 2
|
||||
|
||||

|
||||
@@ -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
|
||||
@@ -1,31 +0,0 @@
|
||||
# Lab Assignment 2
|
||||
|
||||
Name: Joaquin Gottlebe
|
||||
Matrikelnummer: 829101
|
||||
|
||||
## Question 1
|
||||
|
||||

|
||||
|
||||
## Question 2
|
||||
|
||||

|
||||

|
||||
|
||||
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
|
||||
|
||||

|
||||

|
||||
|
||||
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
|
||||
|
||||

|
||||

|
||||
|
||||
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.
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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()
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -1,27 +0,0 @@
|
||||
# Lab 3
|
||||
|
||||
Name: Joaquin Gottlebe
|
||||
|
||||
Matrikelnummer: 829101
|
||||
|
||||
## Question 1
|
||||
|
||||

|
||||
|
||||
## Question 2
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
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.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
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.
|
||||
@@ -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
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
@@ -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}")
|
||||
@@ -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}")
|
||||
@@ -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}")
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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}")
|
||||
@@ -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)
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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="<= 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>
|
||||
@@ -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>
|
||||
@@ -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():
|
||||
Reference in New Issue
Block a user