/
DiHASTRO
/
pp-heat-map
Обзор
Документация
Войти
/
DiHASTRO
/
pp-heat-map
Код
Запросы
3
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
scripts/Sentinel_Hub.py
149 строк
5 KB
karabin
.
13 окт 2025, 17:31
13 окт 2025, 17:31
3921e76
Код
Авторство
О чём код?
import os from math import cos, radians import datetime import numpy as np from sentinelhub import ( SHConfig, MimeType, CRS, BBox, SentinelHubRequest, DataCollection, bbox_to_dimensions, SentinelHubCatalog ) from PIL import Image # ========= НАСТРОЙКИ ========= config = SHConfig() config.sh_client_id = "ID" #id https://apps.sentinel-hub.com/ config.sh_client_secret = "СЕКРЕТ" #secret https://apps.sentinel-hub.com/ date = "2025-10-08" # дата lon = 60.653987 # долгота lat = 56.844014 # широта folder = "scripts/static" # место выгрузки buffer_km = 2 # размер фото(максимальное качество при buffer_km < 25 и resolution = 10) resolution = 10 # разрешение 1 пикселя = resolution метров(min = 10) max_resolution = 2500 # ограничение разрешния фото(максимальное разрешение которое может выдавать sentinel = 2500) max_days = 5 # диапазон дней для проверки наличия снимка band_list = [ ("B08", "B8_NIR"), ("B11", "B11_SWIR1"), ("B12", "B12_SWIR2"), ] evalscript_single = """ //VERSION=3 function setup() {{ return {{ input: ["{band}"], output: {{ bands: 1 }} }}; }} function evaluatePixel(sample) {{ return [sample.{band}]; }} """ evalscript_composite = """ //VERSION=3 function setup() { return { input: ["B12", "B11", "B08"], output: { bands: 3 } }; } function evaluatePixel(sample) { return [sample.B12, sample.B11, sample.B08]; } """ evalscript_natural = """ //VERSION=3 function setup() { return { input: ["B04", "B03", "B02"], output: { bands: 3 } }; } function evaluatePixel(sample) { return [sample.B04, sample.B03, sample.B02]; } """ # поиск ближайшего снимка def find_closest_date(bbox): catalog = SentinelHubCatalog(config=config) time_from = (datetime.datetime.fromisoformat(date) - datetime.timedelta(days=max_days)).strftime("%Y-%m-%d") time_to = date search_iterator = catalog.search( DataCollection.SENTINEL2_L2A, bbox=bbox, time=(time_from, time_to), fields={"include": ["id", "properties.datetime"], "exclude": []} ) results = list(search_iterator) if not results: return None # берём самый свежий снимок перед указанной датой results = sorted(results, key=lambda r: r["properties"]["datetime"], reverse=True) return results[0]["properties"]["datetime"][:10] # 10 длинна YYYY-MM-DD # перевод в 8 бит def normalize_for_display(data): p2, p98 = np.percentile(data, (2, 98)) # 2 и 98 растяжка контраста 2% самых тёмных и 2% самых ярких пикселей игнорируются img = (np.clip((data - p2) / (p98 - p2), 0, 1) * 255).astype(np.uint8) # перевод в 8bit return img # основная функция def download_sentinel_images(): os.makedirs(folder, exist_ok=True) # строим bbox вокруг точки dlat = buffer_km / 111 # 1 градус примерно 111 км dlon = buffer_km / (111 * cos(radians(lat))) bbox = BBox([lon - dlon, lat - dlat, lon + dlon, lat + dlat], crs=CRS.WGS84) # ищем ближайший снимок closest_date = find_closest_date(bbox) if closest_date is None: print("Нет снимков за указанный период") return print(f"Берем снимок за {closest_date}") # ограничение размеров width, height = bbox_to_dimensions(bbox, resolution) if width > max_resolution or height > max_resolution: scale = min(max_resolution / width, max_resolution / height) width, height = int(width * scale), int(height * scale) size = (width, height) # вспомогательная функция для выгрузки def get_image(evalscript, name): request = SentinelHubRequest( evalscript=evalscript, input_data=[SentinelHubRequest.input_data(DataCollection.SENTINEL2_L2A, time_interval=(closest_date, closest_date))], responses=[SentinelHubRequest.output_response("default", MimeType.TIFF)], bbox=bbox, size=size, config=config, ) data = request.get_data()[0] img = normalize_for_display(data) filename = f"{closest_date}_{lat:.4f}_{lon:.4f}_{name}.png" path = os.path.join(folder, filename) Image.fromarray(img).save(path) print("Сохранено:", path) for band, name in band_list: evalscript = evalscript_single.format(band=band) get_image(evalscript, name) get_image(evalscript_composite, "B12_B11_B8_FireComposite") get_image(evalscript_natural, "NaturalColor") if __name__ == "__main__": download_sentinel_images()