- BrainTools - https://www.braintools.ru -
Грибов в этом году у нас было мало. То ли весенние заморозки, то ли сухое лето, то ли дожди, которые под конец, наоборот, лили без остановки. Не поймёшь. Только к концу августа мне начали попадаться первые сообщения: в лесах Ленинградской области наконец пошли боровики. Моя супруга боровики очень любит, и каждую осень мне приходится искать места их обитания.
В этот раз на «тихую охоту» оставалось совсем немного времени — ну, три пары выходных, не больше, как мне тогда казалось. Конкуренция в сезон почище, чем за вакансии на HH, а тратить эти считанные дни на прогулки с пустой корзиной не хотелось.
Первый боровик вылез прямо у нас на дачном участке. Восприняли как сигнал: пора.

Первым делом мы отправились в сторону Алёховщины — проверять сосновые боры и беломошники. С точки зрения [1] грибника именно такой лес и мечтаешь увидеть: стройные сосны, сухой песок, светло, а под ногами белёсый хрустящий ковёр, на котором так и представляешь крепкий боровик с тёмно-каштановой шляпкой.
Беломошник — название народное и немного обманчивое: этот светлый покров образуют преимущественно лишайники (в основном родов Cladonia [2] и Cetraria), а вовсе не мох. Ходить по такому бору — чистое эстетическое удовольствие.

Грибов не было. Совсем.
В тот же день двинулись дальше, в сторону Олонца. Проверили места, кторые заприметили две недели назад по дороге на терский берег и рассчитывали на них, — тоже пусто. На обратном пути я решил наугад свернуть к Нижне-Свирскому заповеднику. Без всякого чёткого плана и уже без больших надежд. И там, в придорожной канаве у второстепенной грунтовки, в совершенно случайном даже не очень то и сосняке, мы набрали две полные корзины за час.
После такой поездки (четыре часа непрерывной рулёжки в одну сторону как-никак) появился чисто айтишный интерес [3]: как выбирать точки для следующего выезда, чтобы не стрелять вхолостую? Почему в хрестоматийном лесу с открытки — шаром покати, а там где совсем грибов не ждешь их с избытком? Хотелось уменьшить фактор случайности [4] в этом итак небыстром процессе.
Пытливый мозг [5], грибной Инстаграмм (экстремисткая секта, всячески порицаю) и прошлый опыт [6] намекали: существует прямая связь между сосной, грибницей и песком. И тогда я решил построить карту пригодных биотопов.
Отдельный гриб на спутниковом снимке, само собой, не разглядишь — разрешение не то. Но можно попробовать найти подходящий для него лес. Поиски начались с микобиологии.
Прежде чем загонять спутники в алгоритмы, стоило уточнить сам объект поиска. Я ориентировался на белый гриб сосновый — Boletus pinophilus [7]. Поручил Клоду собрать научные статьи по теме и ушел пить чай.
Его самостоятельность подтверждается молекулярным филогенетическим исследованием Beugelsdijk et al. (2008) [8]: анализ участков ДНК (дезоксирибонуклеиновой кислоты) — ITS (Internal Transcribed Spacer, внутреннего транскрибируемого спейсера рибосомной РНК [9]) и GAPDH (Glyceraldehyde-3-Phosphate Dehydrogenase, гена фермента глицеральдегид-3-фосфатдегидрогеназы) — надёжно выделил этот вид в отдельную эволюционную ветвь внутри секции Boletus.
Для моей задачи особенно полезна экологическая характеристика: вид образует эктомикоризу преимущественно с сосной обыкновенной (Pinus sylvestris) и приурочен к сухим, кислым, дренированным песчаным и супесчаным почвам. Среди морфологических маркеров — мясистая бугорчатая шляпка тёмного винно-красно-коричневого оттенка и выраженная рельефная сеточка в верхней части массивной ножки.
При этом исследование предостерегает от поверхностных выводов:
Связь с сосной не абсолютна: зафиксированы находки микоризы в еловых насаждениях.
Белый гриб под сосной — не обязательно B. pinophilus. Авторы описали образцы, собранные на песчаных почвах под соснами, которые фенотипически и по биотопу напоминали сосновый боровик, но по ДНК оказались экологической формой обычного белого гриба — Boletus edulis (в микологических статьях после первого упоминания род сокращается: B. pinophilus, B. edulis).
Так с помощью ложки заварки родилась рабочая гипотеза проекта: сочетание чистого сосняка и бедной песчаной почвы позволяет очертить приоритетные полигоны для полевой разведки. Это метод косвенного моделирования пригодности местообитаний (Habitat Suitability Modelling [10]). Он не гарантирует присутствие мицелия и тем более не обещает слой грибов к выходным, но резко отсекает заведомо бесперспективные площади.
Первыми источниками данных стали:
Почвенная карта РСФСР 1988 года под редакцией В. М. Фридланда (масштаб 1:2 500 000);
Слой хвойных лесов глобального мониторинга Copernicus Global Land Service (CGLS) [11];
Краудсорсинговая картографическая база OpenStreetMap (OSM) [12], откуда выгружались участки с отметками типов растительности.
У каждого источника была своя задача. Карта Фридланда указывала на кислые почвы борового ряда. Спутниковый продукт показывал массивы деревьев. А в OSM энтузиасты вручную размечают участки леса. Не то, чтобы всё это было категорически необходимо в поездке, но если уж начал….

На портале soil-db.ru [13] оцифрованная институтом им. Докучаева карта Фридланда не отдаётся готовым файлом. Она работает в веб-интерфейсе через фреймворк Livewire [14]: при панорамировании окна браузер отправляет метод loadFeatures, а сервер шлёт геометрию полигонов в событии livewire-map:add-features.
Я написал сборщик на базе протокола Chrome DevTools Protocol (CDP) [15], который прошёл всю Ленинградскую область сеткой из 55 перекрывающихся окон зума 9, вытянул векторные контуры и слил их в единый GeoJSON (RFC 7946) [16] — формат хранения географических объектов на базе синтаксиса JSON.
Снапшот состояния, скопированный из активного окна, содержал кэш loadedIds — сервер считал эти участки уже загруженными и наотрез отказывался отдавать центральное окно Петербурга и Карельского перешейка. Пришлось сбрасывать идентификаторы и догружать недостающие 60 полигонов отдельным проходом. Итог: 364 полигона, 25 почвенных разностей. Главный фаворит — иллювиально-железистые подзолы (), визитная карточка сосновых боров на песках.
Для лесного покрова я взял продукт CGLS-LC100 (Buchhorn et al., 2020) [17] за 2019 год. Это глобальный растр с шагом 100 м. Качать весь файл (около гигабайта) не потребовалось: GeoTIFF был оформлен по стандарту Cloud-Optimized GeoTIFF (COG) [18].
С помощью библиотеки GDAL [19] и её виртуальной файловой системы /vsicurl [20] в связке с Python-библиотекой rasterio [21] можно читать растр напрямую из удалённого хранилища через HTTP-запросы диапазонов байтов (range-requests). Скрипт вырезал ровно географическую рамку Ленобласти.
Далее пиксели класса 1 (вечнозелёный хвойный лес) были векторизованы функцией rasterio.features.shapes: получилось 3044 контура площадью более 1 км².
Ориентироваться только на теги OSM (leaf_type=needleleaved [22] — тег, означающий иглолистную хвою вообще, а не конкретно сосну) не позволяла фрагментарность покрытия.
Собранное вместе это позволило получить первый прототип карты, который оказался не плох в ретроспективе.
Вооружившись первой версией карты, на следующие выходные мы позвали друзей и махнули под Лугу.
Есть особое чувство безответственности, когда везешь людей за 150 км под вечер, основываясь на только что склеенном скриптом файле. Но карта и бородатые мужики из инстаграмма как будто намекали нам: на песчаных террасах реки Луги хвойный лес совпадает с нужными подзолами.
Первая точка у самой реки встретила нас красивейшим пейзажем, но грибы были не те: разномастные сыроежки и пара старых моховиков. Закрались сомнения…
Переезжаем на вторую точку, углубляемся в массив — и попадаем в безупречный, хрестоматийный беломошник. Светлый просторный сосновый бор, чистый белый лишайниковый ковёр, под ним сухой хрустящий песок. И главное — боровики! Крепкие, тёмно-вишнёвые, как с картинки. Сомнения закравшиеся в предыдущем абзаце оказались беспочвенны.

Правда, быстро выяснился нюанс: почти всё, что росло на виду, срезали конкуренты ещё ранним субботним утром. Нам достались трудовые «хвосты». Но концепция подтвердилась на местности: косвенные признаки вывели нас ровно в целевой биотоп. Слой карты – «кто здесь проходил с ведром три часа назад» спутник, увы, отдает не всем желающим.
Чтобы не сличать слои глазами, я формализовал пересечение в алгоритм генерации полигонов-кандидатов:
Экспертная оценка почв: типам почв Фридланда присвоили рейтинг пригодности (). В отбор пошли почвы от
(прежде всего те самые иллювиально-железистые подзолы).
Растеризация: вектор почв перевели в растровую сетку, идентичную сетке CGLS-LC100.
Логическое пересечение: бинарная маска «хвойный лес почва
».
Полигонизация и отсев: преобразовали маску обратно в вектор через rasterio.features.shapes, выкинув мелкий мусор площадью до 0,3 км². Осталось 3265 зон общей площадью 10 240 км².
Зональная статистика подложки: для каждого полигона рассчитали зональное среднее доли песка в подпочве на глубине 60 см по глобальной сетке OpenLandMap / SoilGrids (Hengl et al., 2017) [23] (разрешение 250 м).
Разделение на сосну и ель: если средняя песчаность превышала 60%, полигон получал флаг pine=true (условный сосняк); если ниже — отправлялся в категорию «прочий хвойный» (чаще сырые ельники).
Итог: 1048 «сосновых» зон (4348 км²) и 2217 прочих хвойных.
Флаг pine=true был смелым авансом: он означал не то, что модель распознала сосну, а лишь то, что хвойный лес стоит на относительно лёгкой песчаной почве. Пересечение разномасштабных данных (почвы 1:2,5 млн, песок 250 м, лес 100 м) не делает границы точнее их самого грубого компонента. Звёзды означали приоритет проверки ногами, а не плотность боровиков на квадратный метр.
После Луги стало ясно, что в лес нужен удобный полевой инструмент. Я дал Клоду задание набросать веб-интерфейс, куда заложить сценарии для смартфона:
Тап по участку раскрывает карточку с кнопками перехода в навигаторы – ссылку по протоколу geo: (RFC 5870) [24] для открытия в сторонних офлайн-приложениях Android.
Кнопка геолокации через встроенный в браузер W3C Geolocation API [25]: стоишь среди сосен и видишь, внутри ты расчётного полигона или ещё бредёшь по переходной зоне.
Разделение панели на «простой режим» (только грибные места, радар дождей и болота) и «экспертный» (где можно крутить прозрачность почв и подсвечивать отдельные типы).
Не спервой попытки но электронный мозген справился. Проект переставл быть простым. Автоматичеи подтянулось тестирование и деплой репозитория через гитхаб экшенс, хранение секретов, логирование логинов и еще черта в ступе. Все как мы любим.

Первый прототип крутился на библиотеке Leaflet [26]. Но тут вскрылась фундаментальная проблема геодезических проекций:
Стандартные веб-карты (OSM, Google) используют проекцию EPSG:3857 [27] (WGS 84 / Pseudo-Mercator, или Web Mercator).
Спутниковые тайлы Яндекса исторически опираются на эллипсоидальную проекцию Меркатора — EPSG:3395 [28] (WGS 84 / World Mercator).
Если натянуть векторный оверлей из одной проекции на растр другой, на широте Санкт-Петербурга (60° с. ш.) возникает физический сдвиг геометрии на местности примерно в 18 километров. Библиотека MapLibre GL JS [29] отпала сразу — она жёстко привязана к Web Mercator. Единственным движком, способным динамически трансформировать растровые и векторные слои в произвольные проекции через WebGL (браузерный интерфейс аппаратного ускорения графики) и Canvas прямо на мобильном процессоре, оказался OpenLayers [30]. Проверил прототип на смартфоне: подложка Яндекса встала без перекосов, контуры легли пиксель в пиксель.
Отдавать мобильному браузеру «сырые» файлы GeoJSON лесов и болот весом по 35 МБ через мобильную сеть на лесной опушке — верная смерть. Данные требовалось тайлировать — разрезать на стандартные пространственные квадраты разного масштаба.
Конвейер генерации оформили в воспроизводимый bash-скрипт:
Утилита mapshaper [31] переводила координаты в локально настроенную азимутальную равновеликую проекцию Ламберта LAEA (Lambert Azimuthal Equal Area, сохраняющую площади объектов) с центральной точкой 60° с. ш., 31° в. д. В плоских метрах пороги упрощения и фильтры площади работают геометрически строго, в отличие от искажающихся угловых градусов WGS84.
Команда -clean удаляла топологические наложения и осколки растеризации.
Упрощение геометрии алгоритмами Дугласа–Пекера (1973) [32] / Висвалингама–Уайатта (1993) [33] с флагом keep-shapes удаляло лишние вершины, не допуская распада мелких замкнутых полигонов. Контуры болот, например, «похудели» с 778 до 333 тысяч вершин.
Утилита tippecanoe [34] паковала полигоны в векторные тайлы формата Mapbox Vector Tile (MVT) [35] внутри единого контейнера PMTiles [36].
Формат PMTiles устроен гениально: это единый файл, содержащий пирамиду тайлов со встроенным индексным заголовком. Браузер через OpenLayers шлёт к серверу запросы диапазонов байтов (HTTP range-requests), скачивая только нужные несколько килобайт на текущий экран, а сервер отвечает кодом 206 Partial Content.
Архивы легли в облачное объектное хранилище Cloudflare R2 [37], а перед ними встал Cloudflare Workers [38] — бессерверный обработчик на JavaScript, который проверяет авторизацию и раздаёт байты с минимальной задержкой.
Чтобы не тонуть в прямом смысле слова, через Overpass API [39] (язык запросов к базе OpenStreetMap) мы выкачали все полигоны болот Ленобласти (natural=wetland). Утилита osmtogeojson [40] собрала их в мультиполигоны с внутренними «дырами». Этот слой стал отрисовываться поверх кандидатов ярко-синим и оливковым цветом. Логика [41]: сосновый бор часто тянется узкой песчаной гривой между непроходимыми верховыми топями. Видишь сухое ребро среди синевы — туда и надо идти.
Тогда же в поездке возникла мысль: нужно ли это кому‑то ещё? Я выставил объявление на Авито о продаже доступа к карте на две недели за символическую плату. Случились три реальные продажи. Пришлось быстро дописывать защитный контур: Вход через учётные записи Яндекса и «ВКонтакте» А Выдача приватного слоя точек только при наличии валидной сессионной cookie.
Тем временем, сезон неумолимо катился к финалу. Окрылённые лужским успехом, мы отправились на проверенные места в Выборгский район.
Результат слегка отрезвил: на опушках стояли шеренги машин, по лесу бродили угрюмые конкуренты с пустыми ведрами. Видимо байки про грибников собирающих грибы с фонариками по ночам были не беспочвенны. На следующем намеченном участке сосняк на поверку оказался завален буреломом и затянут подлеском. Карта работала с вероятностью «фифти-фифти»: если точка обещала сосну — сосна там, скорее всего, была; но в половине мест под ногами чавкала жижа, пропущенная грубыми картами почв.

Не теряем надежды, едем дальше. Поезжаем еще буквально 10 километров в то место, где карта предсказывает беломощники и сосновый лес. И оказываемся ровно в таком лесу. Все на месте. беломощники, сосна и боровые грибы. Победа.
Вернувшись домой, я решилглубже копнуть геологию. Откуда вообще берётся песок под сосняками?
Песок и песчаник — принципиально разные геологические тела. Песок — рыхлый, несцементированный обломочный материал. Песчаник — монолитная осадочная горная порода, где зёрна кварца намертво связаны природным минеральным цементом. Классический пример — знаменитые девонские обрывы реки Оредеж у Белогорки и Ям-Тёсова: этим породам свыше 380 миллионов лет, когда здесь плескалось тёплое мелководное море и плавали панцирные рыбы.
Но современный сосновый бор растёт не на девонских плитах. Его среда — это четвертичный чехол, сформированный последними оледенениями:
Морена (): несортированная смесь валунов, суглинков и гравия, которую ледник грёб перед собой. Это субстрат тяжёлый, плотный, на нём чаще поднимается тёмный ельник.
Флювиогляциальные отложения (): пески и гравийники, перемытые и отсортированные бешеными потоками талых ледниковых вод. Именно они слагают зандровые поля, озы и камовые холмы — сухие, прекрасно дренированные возвышенности.
Озёрно-ледниковые отложения (): накапливались в приледниковых подпруженных озёрах. Они состоят как из песков, так и из тончайших ленточных глин. Сам по себе индекс
на карте вовсе не гарантирует сухой грунт под ногами.
Эоловые пески (): древние песчаные дюны, навеянные ветром в суровом перигляциальном климате.

Теперь у меня были довольно точные данные о подходящих почвах
Решили проверить кандидата под Токсово в районе Кавголовского озера. Приезжаем — идеальный, звенящий сосновый бор на крутых песчаных холмах. Но ровно по границе перспективного полигона тянется трёхметровый глухой забор неизвестного генезиса. Плюнули, развернулись и пошли на соседнее болото собирать спелую клюкву.
Карта обогатилась геологией, но оставалась фундаментальная брешь: как заглянуть внутрь лесного массива с шагом не 100, а хотя бы 10–20 метров?
Первым делом мы добавили базовую глобальную маску древесного покрова ESA WorldCover v200 [42] с шагом 10 метров (класс Tree cover). Стало видно просеки, опушки и границы вырубок. Но WorldCover — это бинарная маска: она подсвечивает дерево, но не отличает сосну от берёзы или ольхи.
Возникло ощущение, что решение лежит на поверхности: хвойные деревья вечнозелёные, а лиственные сбрасывают листву на зиму. Считаем нормализованный разностный вегетационный индекс NDVI (Rouse et al., 1974 [43]; Tucker, 1979 [44]):
Логика: сравним летний NDVI и весенний безлистный NDVI спутника Sentinel-2 (Drusch et al., 2012) [45], найдём порог «просадки» зелёности и отделим хвойные от лиственных.
Мы проверили эту гипотезу на пикселях Ленобласти в Google Earth Engine (GEE) [46] (Gorelick et al., 2017 [47]). Полный провал:
Бесснежная весенняя фенология: гистограмма сезонной разности NDVI внутри леса оказалась строго одногорбой. Никакого разделения на два колокола нет — единым порогом отделить хвою от листвы невозможно. К тому же озимые поля и луговины весной выдавали точно такую же «зелёность», как зрелый сосняк.
Зимний «снегометод»: идея искать вечнозелёные кроны над белым снегом разбилась о физику высоких широт. На 60° с. ш. солнце зимой едва поднимается на 6–15° над горизонтом. Кроны отбрасывают гигантские тени: 97% лесных пикселей сколлапсировали в физический минимум индекса.
Казалось, спутники бессильны. Но ресёрч научной литературы (Udali et al., 2021 [48]; Blickensdörfer et al., 2024 [49]) подсказал: проблема не в спутнике Sentinel-2, а в попытке решить многомерную задачу простым ручным порогом. Нужны размеченные обучающие выборки и машинное обучение [50].
Моих познаний в ML было недостаточно чтобы понять как выбрать подходящую модель и как ее дообучать. Пришлось обратиться к научным работам разных авторов раскрывающим тему определения типов растительности по спутниковым снимкам.
В конце концов был найден хорошо расписанный пайплайн для разделения хвойных и лиственных основанный как раз на Random Forest модели: MDPI rs13163237 [51]
Я снова обратился к OSM, но теперь не за готовыми сосняками, а за обучающими полигонами с тегом leaf_type. После отсева мелких скверов и дачных посадок (оставили строго контуры площадью от 3 гектаров) набралось 3 769 полигонов: 1 407 чисто хвойных, 451 лиственный и 1 911 смешанных. Смешанные массивы временно отложили, чтобы обучить бинарный классификатор.
Контуры ужали внутрь на 15 метров буфером отсечения граничных эффектов и насэмплировали обучающие точки с шагом 30 метров (76 760 точек). Для каждой точки в GEE собрали вектор признаков:
Оптика Sentinel-2: летний и весенний NDVI, их разность (фенологический сдвиг), коротковолновые инфракрасные каналы SWIR (Short-Wave Infrared) B11 и B12, чувствительные к влажности хвои и геометрии полога, индекс NDII;
Радар Sentinel-1: обратное рассеяние в поляризациях VV (вертикальная передача и приём) и VH (вертикальная передача, горизонтальный приём) летом и зимой;
Рельеф Copernicus GLO-30: цифровая модель высот DEM с разрешением 30 метров, из которой вычислялись абсолютная высота и уклон поверхности.
Облачные запросы падали по таймауту пяти минут, поэтому выборку выгрузили пакетным CSV-файлом, а обучение запустили локально в Python на базе библиотеки scikit-learn [52]. Модель — Random Forest [53] (ансамбль решающих деревьев).
В геоданных кроется страшная ловушка — пространственная автокорреляция. Соседние пиксели леса почти идентичны. Если перемешать точки случайным образом, соседние пиксели одного и того же дерева окажутся и в обучении, и в тесте, выдав дутые 99% точности.
Мы применили пространственно-блочную кросс-валидацию: всю Ленинградскую область разбили на квадраты сетки 0,25°. Модель училась на одних блоках, а тестировалась на 30% совершенно независимых полигонов, которых никогда не видела в глаза.
Результат на 29 190 проверочных точках:
Overall Accuracy (общая точность): 0,887;
Каппа Коэна (): 0,772 (отличный показатель с поправкой на случайное угадывание);
Полнота по классам: лиственный — 0,895, хвойный — 0,878.
Мы поочерёдно отключали группы признаков, чтобы понять их реальный вклад:
|
Набор признаков |
Число признаков |
Accuracy |
Каппа |
|---|---|---|---|
|
Только оптика Sentinel-2 |
6 |
0,848 |
0,692 |
|
Оптика + Рельеф (высота, уклон) |
8 |
0,884 |
0,765 |
|
Оптика + Рельеф + Радар Sentinel-1 |
14 |
0,888 |
0,774 |
|
Полный набор (+ песок) |
15 |
0,888 |
0,774 |
Выводы оказались поразительными:
Рельеф — ключевой драйвер: добавление высоты и уклона дало колоссальный скачок точности (+3,6 процентных пункта). Хвойные и мелколиственные леса в тайге чётко привязаны к геоморфологии.
Радар оказался лишним: 6 тяжелейших каналов Sentinel-1 дали прирост всего в 0,4 п.п. Для экономии памяти [54] и времени радар был исключён из финального продакшена.
Анализ важности признаков по перестановкам (permutation importance) показал: лидирует летний NDVI (0,1635), за ним — уклон рельефа (0,0282) и канал SWIR B11 (0,0277). А та самая сезонная просадка NDVI, которая с треском провалилась в виде одиночного порога, внутри многомерной модели дала весомый вклад (0,0145).
Попытка рассчитать всю Ленобласть в 10-метровом разрешении в GEE зависла на 15,5 часов и была снята. На сетке 20 метров число пикселей сократилось в 4 раза, и расчёт уложился в 25 минут.
Чтобы исключить ошибки [55] классификации над водоёмами (без маски модель объявила хвойным половину Ладожского озера), растр обрезали строгой маской древесного полога ESA WorldCover.
Итоговый слой получил название «Хвойный 20 м» (пометка , бета-версия). При нарезке растровых тайлов файл весил 466 МиБ, превышая лимит загрузки Cloudflare R2 в 300 МиБ. Мы квантовали альфа-канал прозрачности (задающий вероятность хвойного) с помощью Pillow [56] до 16 фиксированных градаций: вес упал до 221 МиБ без визуальной деградации.
┌────────────────────────────────────────────────────────────────────────┐
│ ИТОГОВАЯ ТОЧНОСТЬ КЛАССИФИКАТОРА │
│ │
│ МАТРИЦА ОШИБОК (ТОЧЕК В ТЕСТЕ: 29 190) │
│ Назвала Лиственным Назвала Хвойным │
│ На деле Лиственный: 14 578 1 706 │
│ На деле Хвойный: 1 580 11 326 │
│ │
│ • Overall Accuracy (Общая точность): 88.7% │
│ • Каппа Коэна (согласие сверх случайного): 0.772 │
│ • Полнота детекции хвои (Recall): 87.8% │
└────────────────────────────────────────────────────────────────────────┘
Изначально я просто хотел меньше крутить баранку и не бродить по пустым лесам. В итоге пет-проект заставил погрузиться в целый стек технологий и дисциплин:
Геология и почвоведение: генезис четвертичных отложений, литология девона, морфология подзолов;
Основы микологии: экология эктомикоризы Boletus pinophilus, молекулярные маркеры ITS/GAPDH;
ГИС и веб-картография: проекции, тонкости OpenLayers, векторные тайлы PMTiles и range-запросы в Cloudflare Workers / R2;
Computer Vision и OCR: конвейеры векторизации архивных геолкарт, дескрининг растров, робастные оценки;
Дистанционное зондирование Земли и ML: мультиспектральная фенология Sentinel-2, радар Sentinel-1, борьба с пространственной автокорреляцией и оптимизация ансамблей Random Forest.
А можно ли выделить саму сосну? Мы проверили это математически [57].
Среди хвойных точек попытались обучить модель предсказывать песчаный субстрат по спектру кроны:
По оптике показатель ROC AUC (Receiver Operating Characteristic — Area Under the Curve, площадь под кривой ошибок) составил ровно 0,500 — эквивалент подбрасывания монетки.
Радар поднял AUC лишь до 0,537.
Спектрально кроны сосны и ели на песчаных и суглинистых почвах в среднем диапазоне Sentinel-2 неотличимы. А обучающих меток конкретных пород в OSM катастрофически мало: сосны набралось около 150 выделов, а ели — всего 28.
Выделить породу сосны в чистом виде из бесплатного космоса и выборки OSM пока не получилось. Надо либо доразмечать датасет в ручную либо взять область шире. Но наш рабочий суррогат – это пересечение ML-слоя хвойного леса 20 м с песчаными контурами ГГК-1000 и сухим рельефом — на практике прекрасно локализует боровые биотопы.
Беломошник – геоботанический тип леса, а не ландшафтный класс. Напочвенный лишайниковый покров со спутников среднего разрешения сквозь сомкнутый полог крон не считывается. Попытки найти повыдельные таксационные карты в открытых источниках (ФГИС ЛК, региональные лесохозяйственные регламенты) упёрлись в то, что по Ленинградской области геометрия лесоустройства в открытом доступе отсутствует. Поэтому пересечение факторов остаётся наиболее честным приближением.
И пара слов о современных инструментах разработки. Без диалога с LLM (в частности, Claude [58]) подобный исследовательский пласт: от парсинга нестандартных протоколов до математической обработки растров заняло бы в одиночку пару месяцев плотного времени. Я же уложился в серию спринтов между поездками.
Две корзины у Свири, радость от найденных боровиков под Лугой и даже забор под Токсово сложились в общую исторю этой осени. Получвшаяся карта не гарантирует, что грибы прыгнут в багажник сами но значительно экономит моторесурс и дарит азарт исследователя.
Проект продолжает развиваться:
Рабочая карта: https://griby-lenobl.mushrooms.workers.dev/ [59]
Репозиторий проекта: https://github.com/Neanderthal/mushrooms [60]
OSM (OpenStreetMap) [12] — краудсорсинговый картографический проект с открытыми геоданными. Источник разметки лесов и контуров болот.
CGLS (Copernicus Global Land Service) [11] — служба глобального мониторинга земной поверхности в рамках европейской космической программы Copernicus.
LC100 (Land Cover 100 m) — растровый продукт земного покрова с шагом пикселя 100 м (в проекте взят слой Forest-Type за 2019 год).
ESA WorldCover [42] — глобальная высокодетальная карта типов поверхности с разрешением 10 м от Европейского космического агентства (ESA). В проекте использован класс Tree cover версии v200.
Copernicus DEM GLO-30 [61] — глобальная цифровая модель высот (DEM — Digital Elevation Model) с шагом около 30 метров, источник данных о высоте и углах наклона склонов.
GDAL (Geospatial Data Abstraction Library) [19] — базовая библиотека для трансляции, трансформации и чтения растровых и векторных геоформатов.
GeoTIFF [62] — стандартизированный формат растровых графических файлов TIFF, содержащий встроенные географические метаданные о координатной привязке.
COG (Cloud-Optimized GeoTIFF) [18] — оптимизированный для облачных сред GeoTIFF с внутренней тайловой структурой, позволяющий скачивать фрагменты растра HTTP-запросами диапазонов байтов без полной загрузки файла.
GeoJSON [16] — открытый формат описания географических объектов (точек, ломаных, полигонов и их свойств), основанный на синтаксисе JSON.
EPSG [63] — реестр геодезических параметров Европейской группы нефтеразведки (European Petroleum Survey Group). Числовые коды обозначают конкретные координатные системы.
EPSG:3857 (Web Mercator / Pseudo-Mercator) [27] — общепринятая в веб-картографии цилиндрическая проекция на сфероиде (OSM, Google Maps).
EPSG:3395 (World Mercator) [28] — эллипсоидальная проекция Меркатора, применяемая в тайловых сервисах Яндекса.
LAEA (Lambert Azimuthal Equal Area) — азимутальная равновеликая проекция Ламберта. Сохраняет истинные площади контуров, устраняя масштабные искажения при расчётах в метрах.
WGS84 (World Geodetic System 1984) — общеземная эллипсоидальная геодезическая система, глобальный стандарт спутниковой навигации GPS.
ГГК-1000/3 [64] — Государственная геологическая карта масштаба 1:1 000 000 третьего поколения (ВСЕГЕИ).
— геологический индекс флювиогляциальных (водно-ледниковых) отложений (пески, гравийники зандров и озов).
— геологический индекс озёрно-ледниковых отложений (пески, супеси, ленточные глины приледниковых озёр).
— геологический индекс эоловых отложений (дюнные перевеянные пески).
— геологический индекс ледниковых моренных отложений (несортированные суглинки, валунники).
NDVI (Normalized Difference Vegetation Index) — нормализованный относительный вегетационный индекс, количественная мера фотосинтетической активности растительности.
SCL (Scene Classification Layer) — аппаратно-программный растровый слой классификации сцены спутника Sentinel-2, позволяющий автоматически отфильтровывать облака, тени крон, снежный покров и битые пиксели.
SWIR (Short-Wave Infrared) — коротковолновый инфракрасный спектральный диапазон, отражение в котором определяется структурой крон и содержанием влаги в хвое/листве.
B11 / B12 — каналы 11 и 12 сенсора MSI спутника Sentinel-2, соответствующие полосам SWIR.
VV / VH — поляризационные моды радара с синтезированной апертурой (SAR) спутника Sentinel-1 (VV — вертикальное излучение и приём, VH — вертикальное излучение и горизонтальный приём).
Random Forest (Случайный лес) [53] — ансамблевый алгоритм классификации на базе комитетного голосования множества независимых решающих деревьев.
ROC AUC (Receiver Operating Characteristic — Area Under the Curve) — метрика площади под кривой ошибок, отражающая интегральную способность бинарного классификатора разделять классы независимо от выбранного порога (0,5 — уровень случайного шума, 1,0 — идеальное разделение).
Каппа Коэна () — статистическая метрика согласованности предсказаний модели с эталонной разметкой за вычетом вероятности случайного совпадения классов.
Overall Accuracy (Общая точность) — отношение числа безошибочно классифицированных тестовых точек к общему размеру проверочной выборки.
CIELAB — перцептивно сбалансированное цветовое пространство CIE , где геометрическое расстояние между координатами соответствует воспринимаемой глазом разнице оттенков.
HSV (Hue, Saturation, Value) — цилиндрическое представление цвета по тону, насыщенности и яркости.
RANSAC [65] / USAC [66] / MAGSAC++ [67] — семейство робастных алгоритмов оценки математических моделей на зашумлённых массивах данных с высокой долей грубых ошибок (выбросов).
API (Application Programming Interface) — программный интерфейс для взаимодействия сетевых сервисов и передачи структурированных данных.
206 Partial Content [68] — статусный код протокола HTTP, возвращающий запрошенный по смещению диапазон байтов файла.
KV (Key–Value) [69] — распределённое бессерверное хранилище типа «ключ — значение» платформы Cloudflare Workers.
R2 [37] — объектное S3-совместимое облачное хранилище Cloudflare с нулевой стоимостью исходящего трафика.
WebGL (Web Graphics Library) [70] — браузерный API для высокопроизводительного рендеринга 2D- и 3D-графики с использованием аппаратных ресурсов GPU.
PMTiles [36] — открытый облачно-ориентированный однофайловый архив для картографических векторных и растровых тайлов.
ITS (Internal Transcribed Spacer) — внутренний транскрибируемый спейсер ДНК, универсальный молекулярный штрихкод в систематике грибов.
B. pinophilus / B. edulis — общепринятое в биологической номенклатуре сокращение названий видов Boletus pinophilus (белый гриб сосновый) и Boletus edulis (белый гриб сетчатый/обыкновенный).
ООПТ — особо охраняемая природная территория.
РСФСР — Российская Советская Федеративная Социалистическая Республика.
Автор: Neanderthal
Источник [71]
Сайт-источник BrainTools: https://www.braintools.ru
Путь до страницы источника: https://www.braintools.ru/article/37478
URLs in this post:
[1] зрения: http://www.braintools.ru/article/6238
[2] Cladonia: https://cepl.rssi.ru/bio/forest/1_pin_syl_clad.htm
[3] интерес: http://www.braintools.ru/article/4220
[4] случайности: http://www.braintools.ru/article/6560
[5] мозг: http://www.braintools.ru/parts-of-the-brain
[6] опыт: http://www.braintools.ru/article/6952
[7] Boletus pinophilus: https://ru.wikipedia.org/wiki/%D0%91%D0%B5%D0%BB%D1%8B%D0%B9_%D0%B3%D1%80%D0%B8%D0%B1_%D1%81%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D1%8B%D0%B9
[8] Beugelsdijk et al. (2008): https://www.ingentaconnect.com/content/nhn/pimj/2008/00000020/00000001/art00001
[9] РНК: http://www.braintools.ru/article/8114
[10] Habitat Suitability Modelling: https://doi.org/10.1016/S0304-3800(00)00354-9
[11] Copernicus Global Land Service (CGLS): https://land.copernicus.eu/global/
[12] OpenStreetMap (OSM): https://www.openstreetmap.org/
[13] soil-db.ru: http://soil-db.ru
[14] Livewire: https://livewire.laravel.com/
[15] Chrome DevTools Protocol (CDP): https://chromedevtools.github.io/devtools-protocol/
[16] GeoJSON (RFC 7946): https://datatracker.ietf.org/doc/html/rfc7946
[17] CGLS-LC100 (Buchhorn et al., 2020): https://doi.org/10.3390/rs12061044
[18] Cloud-Optimized GeoTIFF (COG): https://cogeo.org/
[19] GDAL: https://gdal.org/
[20] /vsicurl: https://gdal.org/user/virtual_file_systems.html#vsicurl-http-https-ftp-files-random-access
[21] rasterio: https://rasterio.readthedocs.io/
[22] leaf_type=needleleaved: https://wiki.openstreetmap.org/wiki/Key:leaf_type
[23] OpenLandMap / SoilGrids (Hengl et al., 2017): https://doi.org/10.1371/journal.pone.0169748
[24] geo: (RFC 5870): https://datatracker.ietf.org/doc/html/rfc5870
[25] W3C Geolocation API: https://www.w3.org/TR/geolocation/
[26] Leaflet: https://leafletjs.com/
[27] EPSG:3857: https://epsg.io/3857
[28] EPSG:3395: https://epsg.io/3395
[29] MapLibre GL JS: https://maplibre.org/
[30] OpenLayers: https://openlayers.org/
[31] mapshaper: https://github.com/mbloch/mapshaper
[32] Дугласа–Пекера (1973): https://doi.org/10.3138/FM57-6770-U275-W85G
[33] Висвалингама–Уайатта (1993): https://doi.org/10.1179/000870493786962263
[34] tippecanoe: https://github.com/felt/tippecanoe
[35] Mapbox Vector Tile (MVT): https://github.com/mapbox/vector-tile-spec
[36] PMTiles: https://protomaps.com/docs/pmtiles
[37] Cloudflare R2: https://www.cloudflare.com/developer-platform/r2/
[38] Cloudflare Workers: https://workers.cloudflare.com/
[39] Overpass API: https://wiki.openstreetmap.org/wiki/Overpass_API
[40] osmtogeojson: https://github.com/tyrasd/osmtogeojson
[41] Логика: http://www.braintools.ru/article/7640
[42] ESA WorldCover v200: https://esa-worldcover.org/
[43] Rouse et al., 1974: https://ntrs.nasa.gov/citations/19740022614
[44] Tucker, 1979: https://doi.org/10.1016/0034-4257(79)90013-0
[45] Sentinel-2 (Drusch et al., 2012): https://doi.org/10.1016/j.rse.2012.01.013
[46] Google Earth Engine (GEE): https://earthengine.google.com/
[47] Gorelick et al., 2017: https://doi.org/10.1016/j.rse.2017.06.031
[48] Udali et al., 2021: https://doi.org/10.3390/rs13163237
[49] Blickensdörfer et al., 2024: https://doi.org/10.1016/j.rse.2024.114111
[50] обучение: http://www.braintools.ru/article/5125
[51] MDPI rs13163237: https://www.mdpi.com/2072-4292/13/16/3237
[52] scikit-learn: https://scikit-learn.org/
[53] Random Forest: https://scikit-learn.org/stable/modules/ensemble.html#forests-of-randomized-trees
[54] памяти: http://www.braintools.ru/article/4140
[55] ошибки: http://www.braintools.ru/article/4192
[56] Pillow: https://python-pillow.org/
[57] математически: http://www.braintools.ru/article/7620
[58] Claude: https://claude.ai/
[59] https://griby-lenobl.mushrooms.workers.dev/: https://griby-lenobl.mushrooms.workers.dev/
[60] https://github.com/Neanderthal/mushrooms: https://github.com/Neanderthal/mushrooms
[61] Copernicus DEM GLO-30: https://spacedata.copernicus.eu/collections/copernicus-digital-elevation-model
[62] GeoTIFF: https://www.ogc.org/standard/geotiff/
[63] EPSG: https://epsg.org/
[64] ГГК-1000/3: https://vsegei.ru/
[65] RANSAC: https://doi.org/10.1145/358669.358692
[66] USAC: https://doi.org/10.1109/TPAMI.2012.257
[67] MAGSAC++: https://doi.org/10.1109/CVPR42600.2020.00138
[68] 206 Partial Content: https://datatracker.ietf.org/doc/html/rfc7233#section-4.1
[69] KV (Key–Value): https://developers.cloudflare.com/kv/
[70] WebGL (Web Graphics Library): https://www.khronos.org/webgl/
[71] Источник: https://habr.com/ru/articles/1098962/?utm_source=habrahabr&utm_medium=rss&utm_campaign=1098962
Нажмите здесь для печати.