Spaces:
Sleeping
Sleeping
Update lib.py
Browse files
lib.py
CHANGED
|
@@ -1,14 +1,10 @@
|
|
| 1 |
import os
|
| 2 |
import ee
|
| 3 |
-
import
|
| 4 |
-
import
|
| 5 |
-
from matplotlib import pyplot as plt
|
| 6 |
-
import requests
|
| 7 |
|
| 8 |
-
#
|
| 9 |
-
|
| 10 |
-
# Connect GEE API
|
| 11 |
-
GEE_CREDENTIALS_FILE = "./data/gee/geospatial_api_key.json"
|
| 12 |
if not os.path.exists(GEE_CREDENTIALS_FILE):
|
| 13 |
credentials = ee.ServiceAccountCredentials(None, key_data=os.getenv("geospatial_api_key"))
|
| 14 |
else:
|
|
@@ -17,205 +13,126 @@ else:
|
|
| 17 |
ee.Initialize(credentials)
|
| 18 |
|
| 19 |
|
| 20 |
-
#
|
| 21 |
-
ROI = ee.Geometry.Polygon([[37.279358,36.412414],[37.279358, 39.925815],[42.393494, 39.925815],[42.393494, 36.412414],[37.279358, 36.412414]])
|
| 22 |
-
|
| 23 |
CLASSES = {
|
| 24 |
-
"names"
|
| 25 |
-
"colors"
|
| 26 |
}
|
| 27 |
-
|
| 28 |
-
CLD_PRB_THRESH = 50
|
| 29 |
-
NIR_DRK_THRESH = 0.15
|
| 30 |
-
CLD_PRJ_DIST = 1
|
| 31 |
-
BUFFER = 50
|
| 32 |
CLOUDY_PIXEL_PERCENTAGE = 12
|
| 33 |
S2_START_DATE = "2023-08-01"
|
| 34 |
S2_END_DATE = "2023-08-31"
|
| 35 |
S2_LULC_START_DATE = "2023-01-01"
|
| 36 |
S2_LULC_END_DATE = "2023-12-31"
|
| 37 |
|
| 38 |
-
S2_VIS_PARAMS = {
|
| 39 |
-
"bands": ["B4", "B3", "B2"],
|
| 40 |
-
"min": 0,
|
| 41 |
-
"max": 3000,
|
| 42 |
-
"gamma": [1, 1, 1],
|
| 43 |
-
}
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
##! --------------- Functions --------------- !##
|
| 49 |
-
def VisualizeMatplot(image, roi):
|
| 50 |
-
"""Görüntüyü numpy array olarak alma"""
|
| 51 |
-
image = geemap.ee_to_numpy(image, region=roi, bands=["B4", "B3", "B2"])
|
| 52 |
-
|
| 53 |
-
plt.figure(figsize=(10, 10))
|
| 54 |
-
plt.imshow(image)
|
| 55 |
-
plt.axis("off")
|
| 56 |
-
plt.show()
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
def GMap2Gradio(image, vis_params):
|
| 60 |
-
# Görüntüyü RGB bantları ile görselleştirme
|
| 61 |
-
vis_params = {"bands": ["B4", "B3", "B2"], "min": 0, "max": 3000}
|
| 62 |
-
gMap = geemap.Map()
|
| 63 |
-
gMap.add_layer(image, vis_params, "Sentinel-2 Image")
|
| 64 |
-
return gMap.to_gradio()
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
def ApplyBasicS2CloudMask(image):
|
| 68 |
-
cloud_mask = image.select("MSK_CLASSI_CIRRUS").lt(1)
|
| 69 |
-
return image.updateMask(cloud_mask)
|
| 70 |
|
| 71 |
|
|
|
|
| 72 |
def ApplyBitwiseS2CloudMask(image):
|
|
|
|
| 73 |
qa = image.select("QA60")
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
cloudBitMask = 1 << 10
|
| 77 |
-
|
| 78 |
-
cirrusBitMask = 1 << 11
|
| 79 |
-
|
| 80 |
mask = qa.bitwiseAnd(cloudBitMask).eq(0).And(qa.bitwiseAnd(cirrusBitMask).eq(0))
|
| 81 |
-
|
| 82 |
-
return image.updateMask(mask) #.divide(10000)
|
| 83 |
|
| 84 |
|
| 85 |
def ReColormap(image, old_colors: list, new_colors: list):
|
|
|
|
| 86 |
return image.remap(old_colors, new_colors)
|
| 87 |
|
| 88 |
|
| 89 |
-
def
|
| 90 |
-
|
| 91 |
-
reducer=ee.Reducer.count(),
|
| 92 |
-
geometry=roi,
|
| 93 |
-
scale=10,
|
| 94 |
-
maxPixels=1e9
|
| 95 |
-
)
|
| 96 |
-
count = ee.Number(intersection.get("B4")) # B4 bandı kullanılıyor
|
| 97 |
-
return image.set("overlap", count)
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
def GetS2SRCloudCollection(s2_collection: ee.ImageCollection, roi: ee.Geometry, start_date: str, end_date: str):
|
| 101 |
-
s2_cloudless_col = (ee.ImageCollection("COPERNICUS/S2_CLOUD_PROBABILITY")
|
| 102 |
-
.filterBounds(roi)
|
| 103 |
-
.filterDate(start_date, end_date))
|
| 104 |
-
|
| 105 |
-
return ee.ImageCollection(ee.Join.saveFirst("s2cloudless")
|
| 106 |
-
.apply(
|
| 107 |
-
primary=s2_collection,
|
| 108 |
-
secondary=s2_cloudless_col,
|
| 109 |
-
condition=ee.Filter.equals(leftField="system:index", rightField="system:index")
|
| 110 |
-
)
|
| 111 |
-
)
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
# Her bir görüntü için alanı hesapla ve NoData piksellerini dışla
|
| 116 |
-
def add_area_attribute(image, roi):
|
| 117 |
-
# Belirli geometri içindeki piksel alanlarını hesapla
|
| 118 |
-
pixel_area = image.select(0).multiply(ee.Image.pixelArea())
|
| 119 |
-
|
| 120 |
-
# Hesaplanan alanı, istenen geometri içinde özetle
|
| 121 |
-
region_area = pixel_area.reduceRegion(
|
| 122 |
-
reducer=ee.Reducer.sum(),
|
| 123 |
-
geometry=roi,
|
| 124 |
-
scale=10, # Sentinel-2 için 10 metre çözünürlük
|
| 125 |
-
maxPixels=1e13
|
| 126 |
-
).get("B1") # Burada B1 rastgele bir banttır. İlgili bantlardan biri kullanılabilir
|
| 127 |
-
|
| 128 |
-
# Yeni bir attribute olarak alanı ekle
|
| 129 |
-
return image.set("REGION_AREA", region_area)
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
def CalculateIntersectionArea(image, roi):
|
| 133 |
-
# Görüntüyü maskele ve konveks kaplamasını hesapla
|
| 134 |
convex_hull = image.geometry().convexHull()
|
| 135 |
-
|
| 136 |
-
# Konveks kaplaman��n region ile kesişimini hesapla
|
| 137 |
intersection = convex_hull.intersection(roi)
|
| 138 |
-
|
| 139 |
-
# Kesişimin alanını hesapla
|
| 140 |
-
intersection_area = intersection.area()
|
| 141 |
-
|
| 142 |
-
# Yeni bir attribute olarak kesişim alanını ekle
|
| 143 |
-
return image.set("INTERSECTION_AREA", intersection_area)
|
| 144 |
-
|
| 145 |
|
| 146 |
|
| 147 |
def FilterBestAreaOfMGRSJoin(image):
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 152 |
|
| 153 |
|
| 154 |
-
def RequestFunction(
|
| 155 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 156 |
return None
|
| 157 |
|
| 158 |
-
roi = ee.Geometry.Polygon(
|
| 159 |
|
| 160 |
-
#
|
| 161 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 162 |
S2Collection = (
|
| 163 |
ee.ImageCollection("COPERNICUS/S2_HARMONIZED")
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
|
| 168 |
)
|
| 169 |
|
| 170 |
-
#
|
| 171 |
-
esriLULCCollection = ee.ImageCollection("projects/sat-io/open-datasets/landcover/ESRI_Global-LULC_10m_TS").filterDate(
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
|
|
|
| 175 |
)
|
| 176 |
|
| 177 |
-
#
|
| 178 |
-
image_info = S2Collection.first().getInfo()
|
| 179 |
-
print(list(zip(list(image_info["properties"].keys()), list(image_info["properties"].values()))))
|
| 180 |
-
print(image_info["bands"])
|
| 181 |
-
|
| 182 |
-
# Cloud Masking
|
| 183 |
S2Collection = S2Collection.map(ApplyBitwiseS2CloudMask)
|
| 184 |
|
| 185 |
-
#
|
| 186 |
-
S2Collection = S2Collection.map(lambda
|
| 187 |
-
|
| 188 |
-
# MGRS_TILE Match
|
| 189 |
joinCol = ee.Join.saveAll("mgrs_tile_match").apply(
|
| 190 |
-
S2Collection.distinct("MGRS_TILE"),
|
| 191 |
-
S2Collection,
|
| 192 |
-
ee.Filter.equals(leftField="MGRS_TILE", rightField="MGRS_TILE")
|
| 193 |
)
|
| 194 |
|
| 195 |
bestCollection = ee.ImageCollection(joinCol.map(FilterBestAreaOfMGRSJoin))
|
| 196 |
s2Image = bestCollection.mosaic().clip(roi)
|
| 197 |
-
# print(bestCollection.aggregate_array("INTERSECTION_AREA").getInfo())
|
| 198 |
|
| 199 |
-
|
| 200 |
-
#! --------------- Mask Match --------------- !##
|
| 201 |
esriLULCImage = esriLULCCollection.first().updateMask(s2Image.select("B4").gt(0))
|
| 202 |
|
|
|
|
|
|
|
| 203 |
|
| 204 |
-
#
|
| 205 |
-
|
| 206 |
-
|
| 207 |
-
|
| 208 |
-
map.add_layer(esriLULCImage, {"min": 1, "max": 9, "palette": CLASSES["colors"]}, "LULC")
|
| 209 |
-
|
| 210 |
-
return map
|
| 211 |
-
|
| 212 |
|
|
|
|
|
|
|
|
|
|
| 213 |
|
| 214 |
-
|
|
|
|
|
|
|
| 215 |
|
| 216 |
-
|
|
|
|
|
|
|
| 217 |
|
| 218 |
-
|
| 219 |
-
|
| 220 |
|
| 221 |
-
|
|
|
|
| 1 |
import os
|
| 2 |
import ee
|
| 3 |
+
import folium
|
| 4 |
+
import folium.plugins as plugins
|
|
|
|
|
|
|
| 5 |
|
| 6 |
+
# GEE Authentication
|
| 7 |
+
GEE_CREDENTIALS_FILE = "./data/key/geospatial.json"
|
|
|
|
|
|
|
| 8 |
if not os.path.exists(GEE_CREDENTIALS_FILE):
|
| 9 |
credentials = ee.ServiceAccountCredentials(None, key_data=os.getenv("geospatial_api_key"))
|
| 10 |
else:
|
|
|
|
| 13 |
ee.Initialize(credentials)
|
| 14 |
|
| 15 |
|
| 16 |
+
# Constants
|
|
|
|
|
|
|
| 17 |
CLASSES = {
|
| 18 |
+
"names": ["Water", "Trees", "Flooded Vegetation", "Crops", "Built Area", "Bare Ground", "Snow/Ice", "Clouds", "Rangeland"],
|
| 19 |
+
"colors": ["1a5bab", "358221", "87d19e", "ffdb5c", "ed022a", "ede9e4", "f2faff", "c8c8c8", "c6ad8d"],
|
| 20 |
}
|
| 21 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
CLOUDY_PIXEL_PERCENTAGE = 12
|
| 23 |
S2_START_DATE = "2023-08-01"
|
| 24 |
S2_END_DATE = "2023-08-31"
|
| 25 |
S2_LULC_START_DATE = "2023-01-01"
|
| 26 |
S2_LULC_END_DATE = "2023-12-31"
|
| 27 |
|
| 28 |
+
S2_VIS_PARAMS = {"bands": ["B4", "B3", "B2"], "min": 0, "max": 3000, "gamma": [1, 1, 1]}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
|
| 30 |
|
| 31 |
+
# UTILS
|
| 32 |
def ApplyBitwiseS2CloudMask(image):
|
| 33 |
+
"""QA60 bandı üzerinden bitwise bulut maskesi uygular."""
|
| 34 |
qa = image.select("QA60")
|
| 35 |
+
cloudBitMask = 1 << 10 # Bit 10: yoğun bulut
|
| 36 |
+
cirrusBitMask = 1 << 11 # Bit 11: cirrus bulut
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
mask = qa.bitwiseAnd(cloudBitMask).eq(0).And(qa.bitwiseAnd(cirrusBitMask).eq(0))
|
| 38 |
+
return image.updateMask(mask)
|
|
|
|
| 39 |
|
| 40 |
|
| 41 |
def ReColormap(image, old_colors: list, new_colors: list):
|
| 42 |
+
"""LULC sınıf değerlerini yeniden eşler."""
|
| 43 |
return image.remap(old_colors, new_colors)
|
| 44 |
|
| 45 |
|
| 46 |
+
def CalculateIntersectionArea(image, roi: ee.Geometry):
|
| 47 |
+
"""Görüntü geometrisi ile ROI arasındaki kesişim alanını hesaplar."""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
convex_hull = image.geometry().convexHull()
|
|
|
|
|
|
|
| 49 |
intersection = convex_hull.intersection(roi)
|
| 50 |
+
return image.set("INTERSECTION_AREA", intersection.area())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
|
| 52 |
|
| 53 |
def FilterBestAreaOfMGRSJoin(image):
|
| 54 |
+
"""Aynı MGRS tile içinden en büyük kesişim alanına sahip görüntüyü seçer."""
|
| 55 |
+
return ee.ImageCollection.fromImages(image.get("mgrs_tile_match")).sort("INTERSECTION_AREA", False).first()
|
| 56 |
+
|
| 57 |
|
| 58 |
+
def AddGEELayer(fmap: folium.Map, ee_image, vis_params: dict, name: str, show: bool = True):
|
| 59 |
+
"""GEE imajını folium haritasına tile katmanı olarak ekler."""
|
| 60 |
+
map_id = ee_image.getMapId(vis_params)
|
| 61 |
+
tile_url = map_id["tile_fetcher"].url_format
|
| 62 |
+
folium.TileLayer(tiles=tile_url, attr="Google Earth Engine", name=name, overlay=True, control=True, show=show).add_to(fmap)
|
| 63 |
|
| 64 |
|
| 65 |
+
def RequestFunction(roi_coords: list) -> folium.Map:
|
| 66 |
+
"""
|
| 67 |
+
Verilen koordinat listesinden Sentinel-2 ve ESRI LULC katmanlarını
|
| 68 |
+
içeren bir Folium haritası döndürür.
|
| 69 |
+
"""
|
| 70 |
+
if not roi_coords:
|
| 71 |
return None
|
| 72 |
|
| 73 |
+
roi = ee.Geometry.Polygon(roi_coords)
|
| 74 |
|
| 75 |
+
# ROI merkezini hesapla (harita başlangıç konumu)
|
| 76 |
+
centroid = roi.centroid().getInfo()["coordinates"]
|
| 77 |
+
center_lat = centroid[1]
|
| 78 |
+
center_lon = centroid[0]
|
| 79 |
+
|
| 80 |
+
# Sentinel-2 koleksiyonu
|
| 81 |
S2Collection = (
|
| 82 |
ee.ImageCollection("COPERNICUS/S2_HARMONIZED")
|
| 83 |
+
.filterBounds(roi)
|
| 84 |
+
.filterDate(S2_START_DATE, S2_END_DATE)
|
| 85 |
+
.filter(ee.Filter.lt("CLOUDY_PIXEL_PERCENTAGE", CLOUDY_PIXEL_PERCENTAGE))
|
| 86 |
+
.sort("CLOUDY_PIXEL_PERCENTAGE", ascending=True)
|
| 87 |
)
|
| 88 |
|
| 89 |
+
# ESRI LULC koleksiyonu
|
| 90 |
+
esriLULCCollection = ee.ImageCollection("projects/sat-io/open-datasets/landcover/ESRI_Global-LULC_10m_TS").filterDate(
|
| 91 |
+
S2_LULC_START_DATE, S2_LULC_END_DATE
|
| 92 |
+
)
|
| 93 |
+
esriLULCCollection = ee.ImageCollection(esriLULCCollection.mosaic().clip(roi)).map(
|
| 94 |
+
lambda img: ReColormap(img, [1, 2, 4, 5, 7, 8, 9, 10, 11], [1, 2, 3, 4, 5, 6, 7, 8, 9])
|
| 95 |
)
|
| 96 |
|
| 97 |
+
# Bulut maskeleme
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 98 |
S2Collection = S2Collection.map(ApplyBitwiseS2CloudMask)
|
| 99 |
|
| 100 |
+
# Alan hesaplama ve MGRS tile eşleştirme
|
| 101 |
+
S2Collection = S2Collection.map(lambda img: CalculateIntersectionArea(img, roi)).sort("INTERSECTION_AREA", False)
|
| 102 |
+
|
|
|
|
| 103 |
joinCol = ee.Join.saveAll("mgrs_tile_match").apply(
|
| 104 |
+
primary=S2Collection.distinct("MGRS_TILE"),
|
| 105 |
+
secondary=S2Collection,
|
| 106 |
+
condition=ee.Filter.equals(leftField="MGRS_TILE", rightField="MGRS_TILE"),
|
| 107 |
)
|
| 108 |
|
| 109 |
bestCollection = ee.ImageCollection(joinCol.map(FilterBestAreaOfMGRSJoin))
|
| 110 |
s2Image = bestCollection.mosaic().clip(roi)
|
|
|
|
| 111 |
|
| 112 |
+
# LULC maskesi: yalnızca geçerli S2 piksellerini göster
|
|
|
|
| 113 |
esriLULCImage = esriLULCCollection.first().updateMask(s2Image.select("B4").gt(0))
|
| 114 |
|
| 115 |
+
# Folium MAP
|
| 116 |
+
fmap = folium.Map(location=[center_lat, center_lon], zoom_start=10, tiles=None)
|
| 117 |
|
| 118 |
+
# Temel katman
|
| 119 |
+
folium.TileLayer(tiles="https://tile.openstreetmap.org/{z}/{x}/{y}.png", attr="OpenStreetMap", name="OpenStreetMap", show=True).add_to(
|
| 120 |
+
fmap
|
| 121 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 122 |
|
| 123 |
+
folium.TileLayer(
|
| 124 |
+
tiles="https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}", attr="Esri", name="Esri Uydu"
|
| 125 |
+
).add_to(fmap)
|
| 126 |
|
| 127 |
+
# ROI sınırı
|
| 128 |
+
roi_geojson = roi.getInfo()
|
| 129 |
+
folium.GeoJson(roi_geojson, name="Pilot Bölge", style_function=lambda x: {"color": "black", "weight": 2, "fillOpacity": 0}).add_to(fmap)
|
| 130 |
|
| 131 |
+
# GEE katmanları
|
| 132 |
+
AddGEELayer(fmap, s2Image, S2_VIS_PARAMS, "Sentinel-2 RGB")
|
| 133 |
+
AddGEELayer(fmap, esriLULCImage, {"min": 1, "max": 9, "palette": CLASSES["colors"]}, "ESRI LULC")
|
| 134 |
|
| 135 |
+
folium.LayerControl(position="bottomleft").add_to(fmap)
|
| 136 |
+
plugins.Fullscreen(position="topright").add_to(fmap)
|
| 137 |
|
| 138 |
+
return fmap
|