Как стать автором
Обновить

Разработка производительного распознавателя автономеров для edge-устройств

Уровень сложностиСредний
Время на прочтение10 мин
Количество просмотров2.4K
Всего голосов 8: ↑8 и ↓0+8
Комментарии19

Комментарии 19

Добрый день. Так в итоге, какое целевое устройство для эксплуатации? Jetson TX1/TX2, Nano 1st gen - это все унылый хлам на который даже ориентироваться не стоит.

NVDEC используете или через OpenCV захватываете фреймы?

Описанный сервис — это Restful-service. В качестве запроса приходит уже декодированное изображение. Основной упор делается на устройства компании Nvidia, нам не сильно важно какой Jetson использовать в качестве сервера, так как вся система STS может запускаться как на Jetson, так и на dGPU устройствах. Также есть возможность запуска на Rockchip с использованием NPU. В статье указывается Jetson TX2, так как в основном сервис запускается на нём из-за хорошего соотношения «цена/производительность» (что сильно важно для клиентов). В основном же сервисе, который отправляет запросы используется NVDEC.

Так не полетит. То есть основной сервис RAW RGB в запросах отправляет или что? Если RAW RGB - вы большие фантазеры. Смысл платформы CUDA - организация данных в RAM GPU, а загрузка на инфер больших массивов через шину - антипаттерн, особенно еще и через REST, лучше уж сокеты.

Именно NVDEC/NVJPEG - те механизмы, которые в инфер позволяют что-то эффективно передавать.

В сервисе, который рассматривается в статье, нет задачи работы в режиме реального времени, так как есть модуль, который отправляет уже сформированные кадры для распознавания. Отправляются они не каждый кадр, а лишь отдельно взятые для одного трека (авто), как описано в пункте «Какие еще сложности удалось преодолеть?». В случае, когда нужно распознавать номера на каждом кадре, конечно, такое решение не подойдёт для Jetson. Restful service позволяет обеспечить удалённое взаимодействие с сервисом, если это потребуется.

А зачем тогда Jetson?

В смысле, почему не CPU?
Как я понял, ребята еще массу других задач решают через свое приложение: подсчет проездов по направлениям , классификация транспорта по типам, подсчет пешеходного трафика и др. Эти задачи вполне логично решать на нейроакселераторе вроде джетсона

В смысле, они пишут, что есть где-то что-то что использует NVDEC и делает декодинг видео, соответственно, у них там и инференс есть. Далее, они вместо того, чтобы делать инференс на этой высокоэффективной железке зачем-то отправляют его на Jetson в форме RAW RGB через REST. Выглядит как бред - или они не умеют нормально объяснять.

В первую очередь, сервис должен был запускаться на Jetson TX2, чтобы основной сервис и сервис распознавания номеров находились на одной «железке». Возможность удалённого взаимодействия с сервисом является для нас ещё одним плюсом системы.

Вы все классно объясняете, непонятно только как картинки попадают на инференс с камеры и при чем тут REST? Объясните flow.

Я вам объясняю, если вы в сервис распознавания номеров отдаете картинки через RAW RGB, вы абьюзите железку и просто бесполезно тратите ее ресурсы.

Нормальный flow: делать пайплайн, который декодирует весь поток, но обрабатывает только часть данных, если есть типа "внешний трекер". Потому что загрузка RAW RGB в TensorRT выглядит накладной, особенно через RESTful API.

Вот как мы это делаем:

  • у нас DeepStream

  • декодинг на NVDEC

  • внутри ряд модулей паровозиком - какие-то модули делают одно, какие-то другое, но все они работают с одной и той же картинкой заранее аллоцированной в GPU RAM после NVDEC

  • даже если вызывается, скажем, Triton, то с ним тоже обмен через указатель на память, а через REST только метаданные;

  • если OpenCV - то OpenCV CUDA, без скачивания в пространство CPU;

  • если надо веторы считать - CuPy или тензоры CUDA PyTorch, без скачивания тензоров в CPU;

Вот это все - архитектура NVIDIA, которая работает хорошо только тогда, когда вы делаете все правильно, а не абьюзите железку.

Мы понимаем, как оптимально использовать Nvidia Jetson. То что вы описываете, мы затрагивали в другой статье: https://habr.com/ru/articles/725916/.

Здесь мы не стремимся использовать 100% возможности платформы Nvidia, а так называемый «абьюз» позволяет нам упростить разработку сервиса, сделав его независимым модулем, который не встраивается в основной пайплайн.

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

Помимо этого, если встроить такой плагин в последовательность основного пайплайна, мы неизбежно придём к тому, что один кадр станет обрабатываться дольше, а значит упадёт количество FPS (даже если этот плагин будет использовать уже декодированное изображение в RAM GPU). Поэтому описанный сервис работает асинхронно и не затрачивает ресурсы основного пайплайна.

Помимо этого, если встроить такой плагин в последовательность основного пайплайна, мы неизбежно придём к тому, что один кадр станет обрабатываться дольше, а значит упадёт количество FPS (даже если этот плагин будет использовать уже декодированное изображение в RAM GPU). Поэтому описанный сервис работает асинхронно и не затрачивает ресурсы основного пайплайна.

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

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

Вы ступаете на скользкий путь. Сомневаюсь, что сможете обосновать чем пул тредов в разных процессах в Linux отличается от нескольких пулов тредов в одном процессе. Плюсы только в отказоустойчивости в силу ограничения области распространения критических ошибок. А так dlopen вполне может и отдельные модули загружать в виде плагинов.

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

нам нужны были только латинские заглавные буквы и арабские цифры.

Это не совсем правда. Если распознаются только номера РФ, то из всех букв нужны лишь ABCEHKMOPTXY - обучение на сжатом алфавите должно заметно поднять качество распознавания в пограничных случаях. Если распознаете номера братского соседа - там есть и латинская I. Если же распознаются и номера свеженедружественных стран, то, скажем, в Германии на номерах есть полный набор гласных с двумя точками наверху - и при этом такая буква из прописной становится строчной.

Просится двухступенчатый классификатор - сначала класс номера, а уже затем подученные распознаватели внутри каждого класса.

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

А что с правительственными номерами (черные, синие) и нестандартными формами (квадратные на китайцах)?

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

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории