Это перевод с сокращениями научной статьи Marek Kraft, Mateusz Piechocki, Bartosz Ptak, Krzysztof Walas «Autonomous, Onboard Vision-Based Trash and Litter Detection in Low Altitude Aerial Images Collected by an Unmanned Aerial Vehicle» (Remote Sensing, 2021, 13, 965). Статья и иллюстрации распространяются по лицензии CC BY 4.0. Текст переведён и сокращён, код на Python и расчёты по датасету добавила редакция.
Исследователи Познанского технического университета (Польша) собрали дрон, который сам облетает парк или улицу по заданному маршруту, находит на снимках брошенный мусор и ставит каждую находку на карту. Распознавание идёт прямо на борту, без передачи видео на землю. Для обучения нейросети авторы сняли и разметили собственный набор снимков UAVVaste и выложили его в открытый доступ. Дальше пересказываем, как устроена система, какие нейросети и платы они сравнивали, и показываем код, который можно запустить самому.

Зачем искать мусор с дрона
Мусор привлекает мусор: люди охотнее бросают отходы туда, где уже грязно, а в чистом месте мусорят реже. Убирают его почти всегда вручную, и чтобы прочесать большой парк или берег, нужно много людей и времени. Дрон с камерой видит территорию сверху и быстро её облетает. Если он сам отметит, где лежит мусор, уборщикам останется пройти по точкам.
Сложность в том, что мусор на снимке сверху очень мелкий. Обычные наборы снимков для обучения нейросетей (COCO, TACO) сняты с уровня глаз, и объекты на них крупные. На снимках с дрона банка или пакет занимает несколько десятков пикселей среди травы, камней и плитки.
Датасет UAVVaste
Для обучения авторы собрали свой набор: 772 снимка с дрона и 3 716 размеченных объектов на улицах, в парках и на газонах (в текущей версии на GitHub 3 718 объектов). Для каждого объекта есть рамка и маска в формате COCO. Набор и сама статья выложены по лицензии CC BY 4.0: GitHub, Zenodo.

Насколько мелкие объекты, мы посчитали сами по файлу разметки (annotations.json из репозитория, 2,7 МБ). Для запуска хватит стандартного Python, сами снимки качать не нужно:
import json
from collections import Counter
from statistics import median
with open("annotations.json") as f:
coco = json.load(f)
images = {img["id"]: img for img in coco["images"]}
anns = coco["annotations"]
print(f"снимков: {len(images)}, объектов: {len(anns)}")
sizes = Counter(f'{img["width"]}×{img["height"]}' for img in images.values())
print("разрешения:", ", ".join(f"{k} — {v}" for k, v in sizes.most_common()))
per_image = Counter(a["image_id"] for a in anns)
print(f"объектов на снимок: медиана {median(per_image.values())}, максимум {max(per_image.values())}")
# Доля кадра, которую занимает объект (по площади рамки), в процентах
share = [a["bbox"][2] * a["bbox"][3] / (images[a["image_id"]]["width"] * images[a["image_id"]]["height"]) * 100 for a in anns]
print(f"рамка объекта: медиана {median(share):.3f} % кадра")
# Сколько пикселей останется у объекта, если сжать кадр до 608×608, как в статье
def side_608(a):
img = images[a["image_id"]]
return max(a["bbox"][2] * 608 / img["width"], a["bbox"][3] * 608 / img["height"])
side = [side_608(a) for a in anns]
small = sum(s < 32 for s in side) / len(side) * 100
print(f"на входе 608 px: медиана длинной стороны {median(side):.0f} px, меньше 32 px — {small:.0f} % объектов")
Результат:
снимков: 772, объектов: 3718
разрешения: 3840×2160 — 384, 3668×1628 — 338, 4000×3000 — 38, 4032×3024 — 4, 960×1280 — 4, 1280×960 — 2, 4056×3040 — 2
объектов на снимок: медиана 4.0, максимум 65
рамка объекта: медиана 0.072 % кадра
на входе 608 px: медиана длинной стороны 22 px, меньше 32 px — 74 % объектов
Медианная рамка занимает 0,07 % кадра. Когда снимок 4K сжимают до 608 × 608 точек, у трёх объектов из четырёх длинная сторона становится меньше 32 пикселей. По классификации COCO это «маленькие объекты», самые трудные для нейросети.
Как устроен дрон
Летает дрон на автопилоте Pixhawk 2 с GPS-модулем Here2, в котором есть компас и барометр для измерения высоты. Маршрут патрулирования задаётся точками, это штатная функция автопилота. Камера на подвесе смотрит строго вниз. Снимки обрабатывает отдельный бортовой компьютер (компаньон-компьютер), который можно заменить, не трогая остальное.

Авторы проверили три варианта бортового компьютера:
| Плата | Что это | Цена и энергопотребление |
|---|---|---|
| Nvidia Jetson Xavier NX | модуль с 6-ядерным ARM-процессором и видеоядром на 384 ядра CUDA, 8 ГБ памяти | дороже всех, зато запускает любые модели |
| Raspberry Pi 4 + Google Coral USB | ускоритель Edge TPU на 4 TOPS, работает только с моделями, сконвертированными под него | дёшево и экономно |
| Raspberry Pi 4 + Intel Neural Compute Stick 2 | ускоритель Myriad X, модели через OpenVINO | дёшево, запускает и YOLO, но медленно |
Какие нейросети сравнивали
Модели брали готовые, предобученные на COCO, и дообучали на UAVVaste (перенос обучения). Размеры «якорных» рамок YOLO пересчитали под мелкие объекты методом k-средних. Сравнивали YOLOv3 и YOLOv4 с облегчёнными tiny-версиями, YOLOv4-CSP, EfficientDet-d1 и d3, а также SSD с MobileNetV2.
Главная метрика — mAP@50: доля правильно найденных объектов, если рамка совпадает с разметкой хотя бы наполовину. Для задачи «найти и поставить точку на карте» такой точности хватает.
| Модель | mAP@50 (FP32) | mAP@50 (FP16) | mAP@50 (INT8) |
|---|---|---|---|
| YOLOv4 | 0,785 | 0,784 | 0,166 |
| EfficientDet-d3 | 0,751 | 0,750 | — |
| YOLOv4-CSP | 0,736 | 0,745 | — |
| YOLOv3 | 0,694 | 0,694 | 0,075 |
| EfficientDet-d1 | 0,669 | 0,669 | — |
| YOLOv4-tiny-3l | 0,615 | 0,614 | — |
| YOLOv4-tiny | 0,566 | 0,566 | 0,270 |
| SSD MobileNetV2 | 0,545 | — | 0,000 |
| YOLOv3-tiny | 0,239 | 0,232 | 0,000 |
Прочерк — модель не удалось собрать в этом формате или его не проверяли.
Лучше всех нашла мусор полная YOLOv4. EfficientDet-d3 чуть хуже по главной метрике, но пропускает меньше объектов, зато даёт больше ложных срабатываний. Интересно, что YOLOv4-CSP, которая на COCO обгоняет обычную YOLOv4, здесь оказалась хуже. Авторы делают вывод: рейтинг моделей на COCO не переносится автоматически на другую задачу.
Перевод модели в половинную точность (FP16) точность почти не меняет. А простое квантование в 8-битные целые (INT8) её обрушивает, у некоторых моделей до нуля. Без специальной подготовки модели INT8 не годится.
Скорость на борту
На Jetson Xavier NX (видеоядро, оптимизация TensorRT), кадров в секунду:
| Модель | FP32 | FP16 | INT8 |
|---|---|---|---|
| YOLOv4 | 5,4 | 19,3 | 34,7 |
| YOLOv4-CSP | 6,4 | 23,3 | — |
| YOLOv4-tiny | 44,9 | 132,2 | 176,0 |
| EfficientDet-d1 | 8,7 | 16,4 | — |
| EfficientDet-d3 | 2,8 | 5,5 | — |
На ускорителях для Raspberry Pi 4:
- Google Coral запускает только SSD MobileNetV2: 23,9 кадра в секунду по USB 3.0 и 31,7 в форсированном режиме, которому нужен дополнительный обдув. По USB 2.0 вдвое медленнее.
- Intel NCS2 крутит полную YOLOv4 примерно с 1 кадром в секунду, YOLOv4-tiny — 11,2 кадра.
- Голый процессор Raspberry Pi 4 без ускорителя тянет SSD на 1,2 кадра в секунду, а YOLOv4 на 0,07 кадра, то есть один кадр за 14 секунд.
Вывод авторов: лучший вариант — Xavier NX с YOLOv4 в FP16, он даёт почти реальное время при хорошей точности и оставляет запас на будущее. Если важнее цена и энергопотребление, подойдёт Raspberry Pi с USB-ускорителем, но придётся смириться с потерей точности. С 2021 года вышли новые версии YOLO и платы Jetson Orin, но выводы о мелких объектах и квантовании от этого не устарели.
Как найденный мусор попадает на карту
Нейросеть выдаёт рамку в пикселях, а уборщику нужны координаты. Авторы считают их так. Камеру заранее калибруют по шахматной доске (библиотека Kalibr), чтобы убрать искажения объектива. Затем, зная углы обзора камеры и высоту дрона, вычисляют, сколько метров земли помещается в кадр, переводят смещение рамки от центра кадра в метры, поворачивают его на курс дрона по компасу и прибавляют к координатам GPS.

Вот эти формулы (1)–(3) из статьи в виде функции на Python. Мы добавили поворот на курс и перевод метров в градусы:
import math
EARTH_R = 6_378_137 # радиус Земли, м (WGS 84)
def litter_position(lat, lon, alt, yaw, px, py, w, h, fov_h, fov_v):
"""Координаты мусора по рамке на снимке.
lat, lon — координаты дрона; alt — высота над землёй, м; yaw — курс, градусы от севера по часовой;
px, py — центр рамки, пиксели; w, h — размер кадра; fov_h, fov_v — углы обзора камеры, градусы.
Камера смотрит строго вниз, верх кадра — по курсу дрона.
"""
# Формула (1) статьи: сколько метров земли помещается в кадр
X = 2 * alt * math.tan(math.radians(fov_h / 2))
Y = 2 * alt * math.tan(math.radians(fov_v / 2))
# Формулы (2)–(3): смещение рамки от центра кадра в метрах
right = (px - w / 2) / w * X
forward = (h / 2 - py) / h * Y
# Поворот на курс: из «вперёд/вправо» в «север/восток»
psi = math.radians(yaw)
north = forward * math.cos(psi) - right * math.sin(psi)
east = forward * math.sin(psi) + right * math.cos(psi)
# Метры в градусы
lat2 = lat + math.degrees(north / EARTH_R)
lon2 = lon + math.degrees(east / (EARTH_R * math.cos(math.radians(lat))))
return lat2, lon2, X, Y
# Кадр 8 × 6 м, как в примере авторов: высота 5 м, углы обзора 77,3° и 61,9°
lat, lon, X, Y = litter_position(52.4064, 16.9252, alt=5, yaw=0,
px=3840, py=1080, w=3840, h=2160, fov_h=77.3, fov_v=61.9)
print(f"кадр {X:.1f} × {Y:.1f} м, мусор у правого края: {lat:.6f}, {lon:.6f}")
кадр 8.0 × 6.0 м, мусор у правого края: 52.406400, 16.925259
Мы проверили функцию на трёх случаях. Объект в центре кадра получает координаты дрона. Объект у правого края при курсе на север оказывается в 4 м к востоку. При курсе на восток тот же объект оказывается в 4 м к югу.
Из формулы следует, что ошибка положения растёт пропорционально ошибке высоты. Авторы считают, что для уборки хватит точности в метр и даже хуже: кучу мусора уборщик увидит и так. Если подбирать мусор будет робот, нужен точный высотомер, например лидар.
Сколько успеет облететь дрон
Авторы прикидывают так: если один снимок покрывает участок 8 × 6 м, а дрон летит со скоростью 10 м/с, достаточно обрабатывать около 1,5 кадра в секунду с небольшим перекрытием. За 30 минут дрон просмотрит больше 0,1 км². Проверим:
frame_along, frame_across = 8, 6 # кадр 8 × 6 м, длинная сторона вдоль полёта
speed = 10 # м/с
overlap = 0.2 # 20 % перекрытия соседних кадров
minutes = 30
fps = speed / (frame_along * (1 - overlap))
area = speed * minutes * 60 * frame_across / 1e6
print(f"нужно кадров в секунду: {fps:.2f}")
print(f"за {minutes} мин дрон просмотрит {area:.3f} км² ({area * 100:.1f} га)")
нужно кадров в секунду: 1.56
за 30 мин дрон просмотрит 0.108 км² (10.8 га)
Цифры авторов сходятся. Даже YOLOv4 в полной точности на Xavier NX (5,4 кадра в секунду) успевает с запасом. Запас пригодится: снимок высокого разрешения лучше резать на части и проверять каждую отдельно, тогда мелкие объекты не теряются при сжатии.
Что дальше и о чём предупреждают авторы
Нейросеть уверенно отличает мусор от камней, хотя на глаз они похожи. Ошибки бывают в скоплениях: лишняя рамка или пропущенный предмет в куче портят метрики, но не мешают уборке, ведь кучу всё равно уберут целиком.
Авторы планируют расширить датасет, добавить синтетические снимки (вклеивать мусор в фоны, снятые с дрона) и связать систему с сервисом OpenLitterMap, где люди отмечают мусор на карте.
Отдельно авторы пишут о приватности. Съёмка с такой детализацией, чтобы видеть банку на газоне, может восприниматься как слежка. Их система переводит снимки сразу в точки на карте, но перед запуском всё равно нужны меры безопасности, в том числе аудит программ: главными угрозами для дронов авторы называют перехват канала связи и взлом программ. В России к этому добавляются правила полётов: над населёнными пунктами нужно разрешение на использование воздушного пространства, а во многих регионах полёты сейчас запрещены. Подробнее в статье «Где можно летать на квадрокоптере».
Как повторить
- Скачать UAVVaste с GitHub (разметка) или целиком с Zenodo (архив со снимками около 3 ГБ).
- Дообучить на нём детектор, предобученный на COCO.
- Запустить модель на компаньон-компьютере рядом с полётным контроллером, камеру направить вниз.
- Каждую рамку переводить в координаты функцией выше, используя высоту, курс и координаты из автопилота.
Что такое компьютерное зрение и где ещё его применяют на дронах, рассказано в словаре. Сами снимки для такого проекта можно сделать и с обычного дрона в ручном полёте, а обработать потом на компьютере: так проще начать.
Источники
- Kraft M., Piechocki M., Ptak B., Walas K. Autonomous, Onboard Vision-Based Trash and Litter Detection in Low Altitude Aerial Images Collected by an Unmanned Aerial Vehicle. Remote Sensing, 2021, 13, 965 (англ., CC BY 4.0)
- UAVVaste: датасет на GitHub (англ.)
- UAVVaste: архив со снимками на Zenodo, CC BY 4.0 (англ.)
Частые вопросы
Можно ли повторить такую систему самому?
Да, авторы собрали её из готовых деталей: автопилот Pixhawk, GPS-модуль, камера смотрит вниз, а нейросеть работает на Jetson Xavier NX или Raspberry Pi с USB-ускорителем. Датасет UAVVaste открыт, на нём можно обучить свою модель. Сложнее всего разрешение на полёты над городом.
Почему мусор на снимках с дрона искать труднее, чем на обычных фото?
Он очень мелкий. В UAVVaste рамка вокруг мусора занимает в среднем 0,07 % кадра, а после сжатия снимка до 608 × 608 точек у трёх объектов из четырёх длинная сторона меньше 32 пикселей. Модели, обученные на фото с уровня глаз, такие объекты почти не видят.
Сколько площади дрон проверяет за полёт?
По расчёту авторов, при кадре 8 × 6 м и скорости 10 м/с нужно обрабатывать около 1,5 кадра в секунду, и за 30 минут дрон просматривает больше 0,1 км², это около 11 гектаров.



