Ни для кого не секрет, что в последние несколько лет в военном деле произошла т.н. революция дронов, заключающаяся (внезапно) в использовании дронов для поражения военной техники и живой силы противника. И в отличие от предыдущих революций, опиравшихся в основном на высокие технологии и не менее высокую цену изготавливаемой продукции, FPV-дроны делают ход козлом и берут не столько технологичностью, сколько копеечной стоимостью, благодаря которой такой агрегат не только может выносить технику, превосходящую его по стоимости в тысячи раз - даже снаряд ПВО порой стоит значительно дороже.

И если военная техника кое-как пытается противостоять новой угрозе, обрастая "мангалами" и "усами", обвешиваясь активной защитой и антидроновыми турелями, то вот с переносными средствами защиты, способными спасти пехотинца, все не так радужно.

Безумный Макс отдыхает
Безумный Макс отдыхает

Да, есть всякие средства предупреждения о приближении дрона (не помогут, если тебя найдут), антитепловизионные накидки (может и защитят от тепловизора, но опять таки, если тебя найдут - все), сетки и "мангалы" (может хватит на пару попаданий, дальше - опять таки все), но это все пассивные средства защиты, а что там с активными?

Есть антидроновые ружья и РЭБ, которые если и способны были защитить от дрона несколько лет назад, то в данный момент их эффективность сильно упала за счет возможности смены частот, оптоволокна и автономного захвата цели на последнем участке. Так, что еще?

Есть всякие специальные патроны, начиненные дробью, сетками и пр.

Выглядит это все классно конечно, но остается один вопрос - как доставить всю эти пакеты снаряды принимающей стороне? Да, попадать дробью значительно легче, чем обычной пулей, но что если цель не хочет, чтобы по ней попали?

Вот видос по теме, чемпион мира по стрельбе из дробовика пытается поразить дроны в различных сценариях. И таки побеждает, со счетом 2:1.

То есть шанс выжить в противостоянии с дроном есть, но также есть и нюансы:

  • не каждый солдат является чемпионом мира по стрельбе

  • не у каждого солдата есть соответствующее снаряжение

  • состояние бойца скорее всего будет несколько более нервным в виду перспективы скорой смерти или увечья

  • в реальное противостоянии чемпион мира по стрельбе тоже не выжил бы - для выживания нужно победить со счетом 3:0 (и скорее всего неоднократно), победа по очкам не проканает

Умные прицелы

Сама идея умных прицелов не нова, об этом я впервые прочитал еще в 90-х в романе Вернона Винджа "Война с "Миром"", в котором была сцена, когда один из героев романа, который до этого и днём не мог попасть в мишень с первого выстрела, в ночном лесу выпускает очередь по преследующему отряду из десяти бандитов и в итоге попадает по каждому. А все благодаря умному прицелу, который высчитывал оптимальный момент для выстрела. Там правда были еще и умные пули, которые сами потом находили цель, но нас интересует первое. Есть ли что-то подобное сейчас?

Оказывается есть, самая известная разработка это умный прицел SMASH 3000 от израильской компании SMARTSHOOTER. Вот видео с его работой.

Кому лень смотреть, вкратце опишу, как это работает.

  • находишь в небе неподвижный или медленно летящий дрон (это очень важно, почему, объясню в следующем пункте)

  • аккуратно наводишься на этот дрон и отмечаешь его в прицеле при помощи специальной кнопки на цевье, чтобы прицел понял, по кому надо стрелять

  • жмешь на спусковой крючок; прицел сам определит оптимальный момент выстрела с учетом расстояния до дрона, угла наклона ствола, скорости полета пули, ветра, влажности воздуха, фазы Юпитера или что он там еще вычисляет

Выглядит это все круто и хайтехово, но вот первый пункт с малоподвижным дроном меня несколько смутил. И судя по комментариям к видео, не только меня.

Собственно в чем они не правы?
Собственно в чем они не правы?

Ну а других умных прицелов у меня для вас нет, есть новости о разработке чего-то подобного концерном "Калашников", и на этом как бы все. Китайские братушки тоже скорее всего делают что-то подобное, но они ребята скрытные и о своих разработках не распространяются.

Так что, как обычно, придется все делать самому. В этой статье я конечно не буду разрабатывать прям полноценный умный прицел как конечный продукт, для этого потребуется целая команда разработчиков и причины того, почему я так думаю, будут приведены в конце статьи. Но некоторый Proof-of-Concept, доказывающий, что подобное изделие на мой взгляд в принципе возможно, я все же сделаю.

Реализация

Постановка задачи ML

Тут очевидно задача детекции объектов с нюансами - нужно не только задетектить объект, но и определить его центр, посчитать расстояние от него до центра экрана и определить, находится ли центр объекта достаточно близко к центру экрана - в условной области поражения.

Функциональные требования

  • функцию грубого наведения и удержания на цели выполняет оператор, задача прицела - определить момент, когда прицел точно наведен на цель и дать разрешающую команду на открытие огня

  • нужно найти объект, идентифицировать его как дрон, определить, что он находится в зоне поражения, и при этом не перепутать его с птицами, самолетами, деревьями, зайчиками, белочками и т.д., ведь попасть крайне желательно с первого выстрела, второго может и не быть, а значит такую роскошь как стрельба очередями по уткам вперемешку с дронами, мы позволить себе не можем (хотя вряд ли оператор будет наводиться на утку, но всякое бывает)

  • для простоты не будем учитывать дальность до цели и фазы Юпитера - будем считать, что взаимодействие с дроном происходит на коротких дистанциях (до 30 метров), на которых возможно попадание прямой наводкой и можно не учитывать баллистический характер движения пули; то есть считаем, что если цель оказалась в перекрестии прицела, значит мы можем по ней попасть

  • нас интересует только одна цель - если в поле зрения несколько целей, выбираем ту, которая находится ближе всего к центру, остальные игнорируем

Нефункциональные требования

  • высочайшая скорость детекции, чем выше, тем лучше - как уже было сказано выше, дрон не хочет, чтобы по нему попали, поэтому будет двигаться быстро, а двигаться быстро он умеет; поэтому для подобного прицела критически важно обнаружить и поразить цель в кратчайшие сроки, пока она не добралась до оператора

  • узкий угол обзора - основные функции по наведению оружия на цель будет выполнять оператор, так что нам не нужно мониторить все поле зрения, мы заранее можем предоположить, что цель будет находиться где-то рядом с центром и благодаря этому можем сузить поле зрения

  • желательно, чтобы время, затрачиваемое на обработку одного кадра (то есть время между экспозицией камеры и командой наведения), всегда было одинаковым - тогда будет легче вычислить, куда мог улететь дрон за время, пока работала система детекции

  • должно быть что-то компактное, малопотребляющее - от подобного устройства потребуется работа на протяжении нескольких суток, так что жить оно должно долго и при этом не требовать для своей работы автомобильный аккумулятор, да и само должно быть достаточно небольшим, чтобы его можно было легко установить на оружие и носить с собой

  • а еще недорогое, чтобы можно было производить массово

Иными словами, наша основная задача - сделать очень компактный и малогабаритный аппарат, который должен очень быстро (желательно за миллисекунды или десятки миллисекунд) принимать картинку с видеокамеры, идентифицировать на ней дрон и выдавать его местоположение и размеры (т.н. bounding box). Дальше мы проводим постобработку, определяем, настоящая ли это детекция или ложное срабатывание и в конце даем вердикт - находится ли дрон условно в перекрестии прицела или нет (в нашем случае это будет центр поля зрения видеокамеры). Если находится - даем команду на выстрел, если нет - ждем, пока он не окажется хотя бы частично в центре.

Для оператора прицела это будет выглядеть так: находим цель, наводимся на нее и нажимаем на спусковой крючок. Выстрел произойдет в тот момент, когда прицел будет уверен в том, что попадание гарантировано.

Метрики

Если вы не ML инженер, можно в принципе эту главу промотать, тут немного душнилова о способах померить качество модели.

Будем использовать mAP или mean Average Precision или среднюю Cреднюю Точность (кстати в инглише есть еще и термин Accuracy, который тоже, как и Precision, переводится как точность и тоже используется в ML, но тут мы его использовать не будем).

В чем суть: у нас есть картинка, с объектом и размеченной вокруг него рамкой, мы обучаем модель предсказывать рамку вокруг дрона, и степень своей уверенности в том, что данный объект это дрон (от 0 до 1). Дальше мы просим ее нарисовать свой вариант рамки вокруг каждого дрона на каждом из валидационных изображений. Она рисует, мы смотрим, насколько рамки соответствуют одна другой. Сделать это можно через IoU - Intersection over Union, то есть берем площадь пересечения рамок и делим ее на суммарную площадь объединенных рамок.

Пересечение рамок
Пересечение рамок
Объединенная рамка
Объединенная рамка

Как считается Average Precision 50 или AP50 для одного класса:

  1. Все предсказанные моделью рамки сортируются по уверенности, от большей к меньшей.

  2. Каждая рамка считается TP (true positive, верное срабатывание), если её IoU с ещё не занятой размеченной рамкой ≥ 50% (поэтому и AP50). Иначе это FP (false positive, ложное срабатывание). Разметка, которой не нашлось пары, - это FN (false negative, пропуск).

  3. Порог уверенности опускается сверху вниз (все, что выше порога считается верными срабатываниями, все что ниже - нет), и на каждом шаге считаются precision = TP/(TP+FP) (то есть какой процент от объектов, которые мы назвали дронами, действительно являются дронами) и recall = TP/(TP+FN) (какой процент от общего числа дронов мы нашли). Дальше строим график зависимости precision от recall: чем ниже порог, тем выше recall и обычно ниже precision.

  4. Дальше мы мерим площадь под этой кривой и получаем AP50.

  5. mAP50 получается из AP50 путем усреднения значений этой метрики для всех классов, но поскольку в данный момент класс у нас один, то AP50 = mAP50.

Пример графика Precision-Recall
Пример графика Precision-Recall

Также будем использовать mAP50:95. Это когда мерим сначала mAP50, потом mAP55, mAP60 и т.д. вплоть до mAP95, затем берем среднее и получаем mAP50:95.

Еще одна метрика, которую будем использовать, это Ошибка центра рамки - расстояние между центрами предсказанной и истинной рамок в случае, если они хотя бы частично совпали. На самом деле эта метрика будет для нас наиболее важной, так как она ближе всего к исходной задаче.

Данные

Данные для обучения брал с Kaggle и Roboflow Universe. В итоге насобирал девять датасетов и получил в сумме 36 903 изображения, 29 609 в обучении и 7 294 для валидации.

Главная идея, которая потом окупилась много раз: размечать каждое изображение режимом дистанции по площади самой крупной рамки. То есть считаем, какую долю от площади изображения занимает площадь самой крупной рамки дрона и в зависимости от этого значения относим ее к одному из 4-х режимов дистанции.

Режим

Доля кадра

Кол-во изображений

close

>= 10%

8878

mid

1-10%

9831

long

< 1%

13059

empty

0%

5135

И все метрики - mAP, ошибка центра, ложные срабатывания - надо считать отдельно по режимам. Средний mAP по всему датасету для этой задачи почти бессмысленен: дальние мелкие дроны занимают самую большую долю изображений, напрямую они малополезны в задаче, но при этом будут нехило так искажать статистику.

Чистка данных

Любой, кто хоть немного работал с данными, понимает, что идеально чистыми они быть не могут (даже если источник уверяет в обратном). Вот с чем пришлось столкнуться в процессе.

  1. Куча дубликатов или, что еще более неприятно, почти дубликатов. Если один попадет в тренировочную выборку, а второй в валидационную, будет не прикольно. Поэтому пришлось кластеризовать изображения по перцептивному хешу (pHash - по сути отпечаток изображения, построенный так, чтобы похожие на вид картинки давали похожие хеши). Дальше клал в тренировочную и валидационную выборку изображения целыми кластерами, дабы не было утечек. Также старался, чтобы доля всех источников и всех режимов и там и там была одинаковой.

  2. Экспорт Roboflow часто содержит до 6 повёрнутых/искажённых копий каждого снимка, пришлось где-то при помощи скриптов, а где-то вручную это все выкидывать.

  3. Большинство кадров - маленький объект на ровном небе, и получается, что у совершенно разных снимков хеши почти совпадают. Поэтому поиск дубликатов двухэтапный: pHash для полноты, затем проверка двумя корреляциями (по яркости и градиенту) на уменьшенных копиях.

  4. Пришлось удалить кадры, где все рамки по размерам меньше 12 пикселей: это ниже порога обнаружения модели (о которой поговорим ниже). Кадры, где есть и мелкая, и нормальная рамка, оставили.

  5. В одной из ранних версий оказалось, что в категории empty полно неразмеченных дронов. Пришлось проверять глазами и удалять подобные изображения.

Железо

Очевидно, что в качестве модели будем использовать нейронку, поэтому под нее нужно подобрать соответствующее железо.

Какие тут варианты:

  • GPU/TPU - нейронка работает из коробки, однако не подходит ни по требованию компактности, ни по требованию энергопотребления

  • всякие NPU типа Hailo, Coral Edge и т.д. - в целом подходят по потреблению и габаритам, но проблема в том, что NPU это сопроцессор, и кадр к нему приносит хост-процессор через драйвер под управлением Linux, а значит там есть планировщик ОС и прочие источники неопределенности, которые сделают нашу систему наведения недетерминированной, а задержку между экспозицией и командой наведения - плавающей, чего нам бы хотелось избежать

  • есть и что-то среднее между GPU и NPU, типа Nvidia Jetson, но там та же проблема с недетерминированостью + потребление и габариты больше, чем у NPU

  • FPGA - микросхема с программируемой архитектурой, имеет относительно низкое потребление и габариты + заливай туда что хочешь, и это всегда будет работать с одной и той же задержкой; из минусов - количество ресурсов очень ограничено, так что заливай что хочешь, но понемножку, да и цена порой кусается

Так что для данного Proof-of-Concept будем использовать FPGA, потом в случае чего его архитектуру можно будет воплотить в ASIC, которая будет быстрее, компактнее и дешевле (правда и дообучить ее в случае чего не выйдет).

Модель

Стандарт де-факто в задаче детекции объектов это модели семейства YOLO, ее и будем использовать, осталось только выбрать, какую именно. Для этого пришлось покопаться в работах по этой тематике, а их оказалось довольно много. В итоге выбрал две:

  • взяли YOLOv3-Tiny, затем нехило ее покромсали и запихали в Xilinx Zynq-7020 (довольно простой аппарат), получили 208 FPS при 2,55 Вт, при этом 1,9 Вт из 2.55 ушло на постобработку при помощи ARM процессора и DDR, ссылка тут

  • взяли YOLOv8n, запихали в Xilinx ZCU102 (этот аппарат сильно более продвинутый), получили 195 FPS, ссылка тут

Ну казалось бы, красота, ~200 FPS это всего лишь 5 мс на кадр, очень быстро! Но вот только авторы статей не акцентируют внимание на то, что это только время работы непосредственно модели на FPGA, а ведь есть еще и предобработка кадра, постобработка детекций и прочее. Так вот, если все это учесть, то цифры получаются уже не такими радужными:

  • в первом случае по разным оценкам получается от 14 до 30 FPS

  • во втором случае - около 24 FPS

В общем на деле цифры не такие красивые как хотелось, а учитывая, что для надежного подтверждения цели требуется несколько кадров, время реакции переваливает за 100 мс. Но у меня была обоснованная надежда на то, что пред/постобработку можно будет сильно оптимизировать, ведь в указанных выше работах этим никто не занимался (а в первой работе постобработку вообще на ноутбуке делали).

Мне удалось ненадолго раздобыть такой же ZCU102, как во второй работе, поэтому было решено не мучаться и взять за основу готовую модель из этой же работы, выкинуть из нее лишние детали, дообучить на датасете дронов, залить в железяку и посмотреть, что получится.

Xilinx ZCU102. Солидный девайс
Xilinx ZCU102. Солидный девайс

Была конечно идея использовать и более поздние (а следовательно и более продвинутые) модели семейства YOLO, но к сожалению они содержат в себе компоненты, которые довольно трудно реализовать в железе, поэтому эту идею пришлось оставить.

Применение

Выглядеть это все будет так:

  • высокоскоростная камера, подключается к плате через USB 3.0, 1280х720, 200 FPS, Global Shutter (то есть глобальный затвор, важно при высокоскоростной съемке)

  • дальше идет сама плата, на ней есть контроллер USB и память DDR, куда кадр отправляется первым делом

  • из DDR кадр забирает ARM процессор, осуществляет его препроцессинг, затем возвращает его в DDR; также он осуществляет управление FPGA

  • далее кадр из DDR забирает FPGA, прогоняет через нейросеть и записывает детекции обратно в DDR

  • затем детекции забирает ARM процессор, делает постобработку, и в случае положительного результата детекции зажигает светодиод

У этой схемы есть свои недостатки:

  • более уместнее была бы камера с интерфейсом MIPI CSI, способным передавать поток напрямую в микросхему без задержек и буферов за фиксированное время, но под рукой была только такая

  • данный вариант ничем не лучше того же NPU, так как плата тоже работает на Linux, есть всякие задержки на взаимодействие с DDR, детерминизм отсутствует, но если сразу пихать всю пред- и постобработку в FPGA, отладка усложнится в разы, поэтому пока придерживаемся такой схемы, тем более это Proof-of-Concept

Тренировка и подготовка модели

Самое веселье начинается, когда мы начинаем готовить модель к работе на плате, схему подготовки привожу ниже.

  1. Обучение. Тут все довольно просто: как уже говорилось выше, разбиваем на тренировочную и валидационную выборку, на первой обучаемся, на второй проверяем, насколько хорошо обучилось. Во время обучения всячески портим картинку аугментациями (случайные изменения картинки, например масштабирование, сдвиг, отражение по горизонтали и т.д.), чтобы обучалось на более богатой выборке. Но некоторые изменения пришлось внести в модель уже на этом этапе, например сократить размер входного изображения с 416x416 до 320x320 (модель с бОльшим входным разрешением просто не влезала в FPGA) и заменить активации с SiLU на ReLU6 (шестерка в названии означает, что максимальное значение функции активации не может быть больше 6). 100 эпох.

  2. QAT . Уменьшаем размер активаций и весов модели до 4-8 бит (это называется квантизация) при помощи фреймворка Brevitas. Дообучаем на 30 эпохах.

  3. Экспорт в QONNX. Вход фиксируется на 192×320 (сеть свёрточная, ей всё равно, какой формы вход. 192×320 - это кадр 16:9 камеры, ужатый до 320 по длинной стороне).

  4. FINN: фронтенд. FINN превращает квантованную нейросеть в конвейер аппаратных слоев для работы в FPGA.

  5. FINN: фолдинг и FIFO. Для каждого слоя задаём степень параллелизма так, чтобы ни один из слоев не тормозил конвейер, и подбираем глубины FIFO между слоями.

  6. Генерация и сборка. генерируем IP-ядра, затем Vivado сшивает их вместе (около 13 часов), синтезирует и разводит. Результат - файл битстрима для заливки на плату. Удалось достичь частоты работы FPGA 187,5 МГц.

  7. Плата. Заливаем на SD-карту PetaLinux, PYNQ всякие драйверы и файлы Python, осуществляющие управление FPGA, а также пред- и постобработку. Вставляем эту карточку в плату, запускаем.

Вот какие результаты для разных режимов, до и после квантизации. W4A4 означает, что и веса и выходные данные слоев (активации) нашей модели преобразованы в 4-х битный формат.

модель

close mAP50

close mAP50:95

mid mAP50

long mAP50

long mAP50:95

ошибка центра, close

исходная

0.9855

0.7128

0.9893

0.8691

0.4848

1.39%

W4A4, только PTQ

0.9880

0.6737

-

0,7663

0.3540

-

W4A4 после QAT

0.9835

0.7099

0.9879

0.8514

0.4733

1.39%

К счастью, квантизация не слишком сильно испортила нашу модель.

Дальше пара слов про то, как мы будем обрабатывать данные перед и после модели.

Предобработка

Камера работает в режиме 1280×720 при 200 кадрах в секунду, в формате YUYV. Это несжатый поток, поэтому его не нужно декодировать, в отличие от MJPEG. Сам режим 1280×720 достигается путем обрезки (кропа) исходного Full HD изображения с сенсора, так что угловое разрешение остаётся родным. Кадры принимает отдельный поток, и хранит он только самый свежий.

Дальше одна функция прямо в буфере драйвера вырезает центральное окно 320×192 и переводит его из YUYV в RGB. Обрабатываются только нужные пиксели, весь кадр в RGB не переводится.

Затем остаётся положить окно в DMA-буфер и запустить его передачу на FPGA.

Постобработка

YOLOv8n отдаёт тензор размера 24×40×65, то есть 960 ячеек сетки, в каждой 64 канала на рамку и один на класс «дрон». Всё остальное делают ARM-ядра, в два шага.

Декодирование. Функция читает только канал класса во всех 960 ячейках и сравнивает его с заранее заданным порогом. Если уверенность модели в классе данной ячейки больше этого порога, ячейка проходит на следующую ступень. Обычно проходит не более 10. Для выживших ячеек восстанавливается рамка.

Трекер. Трекер одноцелевой. Он берёт рамку, ближайшую к центру кадра, объединяет с ней пересекающиеся рамки взвешенным усреднением (WBF, Weighted Box Fusion) и прогоняет результат через альфа-бета-фильтр. Фильтр сглаживает положение с учетом детекций с трех предыдущих кадров и оценивает скорость цели. Измерение, которое не согласуется с прогнозом, отбрасывает. На выходе получаем смещение цели от оси прицеливания с упреждением на задержку системы и флаг наведения. Если флаг встает в 1 - загорается светодиод.

Результаты

Работает это примерно так - можно видеть, как горящий на плате светодиод (у правого края изображения) гаснет, если закрыть изображение дрона рукой.

Извините за заваленный горизонт, по-другому все в кадр не влезало
Извините за заваленный горизонт, по-другому все в кадр не влезало

Сама по себе нейронка выдает 168 FPS при частоте работы FPGA 187.5 МГц. Но это те же бумажные цифры, что и с предыдущих работ, практического смысла они не имеют.

Все цепь предобработка -> FPGA -> постобработка выдает примерно 113 FPS, это уже ближе к реальности, но больше нас интересуют не кадры в секунду, а задержка, ведь чем она ниже, тем быстрее система сможет среагировать на цель и тем меньше времени будет у цели, чтобы уйти из зоны поражения.

Изначально задержка нашей системы была в районе 75 мс, но путем перекомпиляции модели и переноса части кода с Python на C удалось сократить ее более чем вдвое - до 37 мс.

Расчетное потребление (по оценке САПР Vivado) получилось 6.54 Вт, из них 2,74 Вт приходится на ARM.

Теперь давайте посмотрим, сколько времени занимает каждый из этапов

№

этап

где

медиана, мс

p95, мс

1

передача кадра по USB + пробуждение потока захвата

USB, ARM

5.5

6.4

2

кроп 320×192 + YUYV → RGB

ARM

1.75

2.5

3

ожидание свободного слота для отправки в FPGA

ARM

2.8

5.9

4

отправка кадра в FPGA

ARM -> FPGA

0.5

0.8

5

нейросеть

FPGA

23.1

25.1

6

декодирование детекций

ARM

2.1

2.5

7

трекер

ARM

1.8

2.7

8

итого, от получения кадра до команды наведения

37.3

40.8

Из всех этих этапов неустранимой является только задержка работы нейросети, от всех остальных этапов можно либо избавиться (например путем замены интерфейса камеры с USB на MIPI CSI) либо радикально уменьшить (путем переноса всех этапов пред- и постобработки на FPGA). Да и в принципе саму работу нейросети можно ускорить, например увеличив частоту FPGA до 250-300 МГц. Но поскольку такие манипуляции требуют перекомпиляции модели под более высокую частоту (сейчас ее максимальная частота чуть больше 200 МГц), на данном этапе было решено остановиться. На мой взгляд, вполне реалистично довести медианную задержку до ~20 мс. Плюс также должно сократиться потребление, поскольку ARM процессор больше не будет задействован.

Напоследок сравнение моей модели и моделей из предыдущих работ

Danilowicz & Kryjak (ARC 2025)

Calì et al. (Electronics 2025)

наша модель

сеть

YOLOv8n, 3 головы

YOLOv3-Tiny (с прунингом)

YOLOv8n, 1 голова P3

квантование

W4A4

W4A4

W4A4, первый слой и голова W8

вход

320×192

416×416

320×192

плата

Xilinx ZCU102

Xilinx Zynq-7020

Xilinx ZCU102

частота FPGA

300 МГц

200 МГц

187.5 МГц

LUT

105k (38.2%)

41 605 (78.2%)

82 907 (30.3%)

BRAM36

293 (32.1%)

138 из 140 (98.6%)

720 (79.0%)

DSP

482 (19.1%)

204 (92.7%)

334 (13.3%)

FPS ускорителя

195,3

208.7 (batch 100), 164.8 (batch 1)

168

задержка ускорителя, 1 кадр

-

6.1 мс

22.6 мс

FPS всей системы

~24

30

~113

задержка всей системы

-

~70 мс

~37.3

мощность

-

2.55 Вт (измерено)

6.54 Вт (оценка Vivado)

точность

mAP 0.21, COCO

mAP50 0.177, VisDrone

mAP50 0.98–0.99 (режим close, изображения с дронами вблизи)

Примечание: точность моделей напрямую сравнивать нельзя: у всех трёх работ разные датасеты и задачи. COCO это 80 классов, у VisDrone - мелкие объекты с дрона, у нас один класс и крупная цель.

Что еще осталось

Теперь давайте честно поговорим о том, что еще предстоит сделать, чтобы превратить наш прототип в жизнеспособный продукт.

  1. Сеть ни разу не видела настоящего дрона через настоящий объектив. Все цифры точности получены на разнородных фотографиях из интернета. Трекер проверен только на синтетических треках и на картинках с дронами перед камерой + все пороги в алгоритме постобработки - заглушки. То есть нужно выбирать камеру, которую будем использовать в дальнейшем, а затем идти и снимать на эту камеру разные дроны в разных погодных условиях и при разном освещении (в том числе и ночью). А дальше размечать и использовать этот датасет для повторного обучения модели.

  2. Объектив не выбран. От него зависит, каким по размеру будет дрон в кадре, а значит, и вся настройка сети и трекера. Также опять таки нужно как-то решать вопрос с условиями плохой видимости (добавлять инфракрасную подсветку, ночной режим, тепловизор и т.д.)

  3. Нужна камера с MIPI CSI вместо USB. Она сократит задержку и добавит детерминированности системе.

  4. Птицы и самолёты для сети - тоже дроны. Уже после обучения модели проверял на похожих на дрон летающих объектах типа птиц и самолетов - находит и объявляет дронами, твердо и четко. Так что нужно будет переобучать модель детектить несколько классов (дроны, самолеты, вертолеты, птицы) чтобы не было ложных срабатываний на похожие объекты.

  5. Нет информации об экспозиции камеры. А ведь она тоже вносит свой вклад в задержку, нужно будет измерять. Также пригодился бы аппаратный триггер камеры, благодаря которому экспозиция начинается в момент, когда на него приходит импульс. Если импульс выдаёт FPGA и сама же записывает время, мы точно знаем момент съёмки каждого кадра, что очень сильно поможет в измерении полной задержки. Сейчас мы его не знаем.

  6. Энергопотребление платы под нагрузкой не измерено. К сожалению под рукой не было соответствующего оборудования, позволяющего измерить потребление устройства. Есть только оценка Vivado - 6,5 Вт, из которых 2,7 Вт приходится на ARM процессор.

  7. Всю логику нужно переносить на FPGA. Опять таки, сократит задержку и добавит детерминированности, но сложнее в отладке, так что делать это имеет смысл только на финальном этапе.

  8. ASIC вместо FPGA. По-хорошему на базе архитектуры FPGA нужно делать ASIC, который и работать будет быстрее, и кушать меньше. Но тут возникает еще одна проблема - дообучить нейросеть на таком чипе уже не получится, она будет вшита туда намертво. Впрочем, ничто не мешает добавить на выходе такого чипа маленькую FPGA (например одну из тех, что делает фирма Lattice), хранить на ней последние выходные слои модели и дообучать в случае чего только их.

  9. Интегрировать все это в оружейную платформу. Отдельная и сама по себе нетривиальная задача, которая ставит перед нами множество не только технических, но и бюрократических препятствий.

Вывод

На мой взгляд сделать умный прицел можно, но явно не силами одного энтузиаста - тут нужна целая команда, причем со всякими там допусками типа работы с оружием или дронами. Но задача вполне себе посильная.

Репозиторий со всеми наработками лежит здесь

На этом все, спасибо, что дочитали! Если заметили ошибку, неточность или знаете, как сделать лучше, пишите в комментариях. До новых встреч!

P.S.

Добавлю пожалуй еще рассуждения по поводу этической составляющей данного прицела. А именно - можно ли его адаптировать для применения против людей?

На мой взгляд нет, и вот почему:

  • прицел расчитан для противодействия маленьким и быстрым целям, человек наоборот - большой и медленный

  • прицел расчитан на короткие дистанции, когда цель подлетает к тебе практически в упор, люди же предпочитают по возможности близко не подходить

  • дрон заметить относительно легко, особенно на фоне неба, люди же всячески маскируются, прячутся за укрытиями и т.д.

Иными словами, на дальней дистанциии против людей эта штука бесполезна, потому что ничего не увидит, а на ближней можно обойтись и без нее. Хотя я не сомневаюсь, что что-то подобное рано или поздно сделают и против людей (если уже не сделали, просто показывать стесняются).