Своё распознавание номеров на весовой — без единой лицензии
Раньше номер въезжающей машины на весовой вбивал оператор вручную. Собственный сервис читает номер с камеры в реальном времени, а тракторы без читаемых номеров — по ArUco-меткам.
01 — Почему не купили готовоеДве категории транспорта — и у каждой свои сложности
Задача звучала просто: машина заезжает на весовую, оператор должен как можно быстрее получить её номер, чтобы взвешивание не превращалось в очередь из-за ручного ввода. Готовые коммерческие системы распознавания номеров решают это — но обычно продаются как канал: лицензия на камеру, подписка на облачное распознавание, сервисный контракт. Для одной весовой с двумя камерами это несоразмерно дорого относительно самой задачи.
На весовую заезжают два типа объектов, и коммерческое ALPR-решение «из коробки» хорошо закрывает только один из них:
- Грузовой транспорт с обычными номерами. Стандартная задача распознавания: камера, ракурс въезда, номер по ГОСТу — то, для чего и делают коммерческие ALPR-системы.
- Собственная техника — тракторы. Номер часто заляпан, установлен не по ГОСТу, а то и вовсе отсутствует как класс — техника внутри хозяйства идентифицируется по внутреннему инвентарному номеру. Ни одна коробочная система распознавания номеров эту технику надёжно не читает — она её и не должна читать, это не то, для чего ALPR проектировали.
То есть даже купив коммерческую систему, вторую половину задачи — тракторы — всё равно пришлось бы решать отдельно и вручную. Раз одну половину так или иначе пишем сами, логичнее было спроектировать обе сразу как единый сервис.
Сервис должен непрерывно смотреть на поток с камеры и в любой момент — по запросу из 1С — мгновенно отдавать последний распознанный номер. Не «сфотографировать и подождать 5 секунд», а уже иметь готовый ответ к моменту, когда оператор нажал кнопку.
02 — Как устроено решениеОдин сервис, два канала распознавания
В основе — небольшой Python-сервис, который в фоновом потоке постоянно читает кадры с камеры по RTSP и разбирает их одним из двух способов в зависимости от того, что на кадре: обычный номер или трактор.
Машины. Для обычных номеров используется связка из двух моделей: одна находит на кадре прямоугольник номерного знака (детектор), вторая читает символы внутри этого прямоугольника (OCR). Обе модели работают локально, без обращения к внешним сервисам — открытая библиотека fast-alpr, работающая поверх OpenCV. Дальше — простая, но обязательная часть: распознанный текст приводится к валидному виду. Модель иногда путает похожие символы — латинскую O и цифру 0, кириллическую В и цифру 8 — и в коде есть отдельная функция, которая раскладывает строку по позициям российского номера и точечно подставляет наиболее вероятный символ на каждую позицию. Результат сверяется с регулярным выражением формата номера — если не совпало, ответу присваивается более низкая уверенность, а не отбрасывается сразу.
Тракторы. Решили не бороться с OCR на грязном металле, а обойти задачу: на кабину каждого трактора наклеен небольшой ArUco-маркер — чёрно-белый квадрат по принципу QR-кода, спроектированный так, чтобы надёжно читаться под углом, в движении и при плохом освещении. Камера видит маркер тем же кадром, что и обычные номера — просто по нему не гоняется OCR, а сразу декодируется числовой ID. Дополнительно заложена проверка по минимальной площади маркера в кадре — это отсекает случайные ложные срабатывания на бликах рифлёного металла весовой площадки.
Скользящее окно — защита от «залипшего» номера. Первая версия логики копила голоса за номер всё время, пока машина стоит в кадре. Трактор, простоявший на взвешивании пять минут, успевал накопить сотни голосов — и когда следующая машина подъезжала практически без паузы, её пара кадров не могла перебить эту накопленную массу. Решение — голосование в скользящем окне фиксированного размера: система помнит не всю историю, а только последние несколько кадров. Как только новый номер занимает большинство слотов в этом окне, он немедленно становится текущим — независимо от того, сколько «веса» набрал предыдущий.
Мост в 1С. Распознавание идёт непрерывно в фоне, а не по запросу — это ключевое архитектурное решение. К моменту, когда оператор нажимает кнопку в 1С, ответ уже готов: 1С делает обычный HTTP-запрос к локальному сервису и мгновенно получает последний зафиксированный номер, без задержки на съёмку и распознавание в моменте.
Параметр consume=1 нужен, чтобы один и тот же номер не был случайно взят в обработку
дважды, если оператор нажал кнопку повторно.
03 — НадёжностьRTSP рвётся — сервис не должен падать
Отдельное внимание ушло не на распознавание, а на устойчивость самого видеопотока. IP-камеры периодически теряют соединение, а библиотеки для чтения RTSP иногда «зависают» внутри системного вызова так, что поток не возвращает управление и не бросает исключение. Если в этот момент попытаться закрыть и переоткрыть соединение из другого потока — есть риск уронить процесс целиком без единой строки в трейсбеке.
Поэтому чтение кадра выполняется с явным таймаутом в отдельном потоке-наблюдателе: если чтение не укладывается в отведённое время, зависший объект соединения просто помечается как потерянный и больше не трогается — сервис открывает новое соединение, а старое безопасно освобождается сборщиком мусора. Это на порядок скучнее, чем логика распознавания, но именно от таких деталей зависит, будет ли сервис работать месяцами без перезапуска вручную.
04 — Во что это обошлосьЕдинственная статья расходов — сами камеры
Всё программное обеспечение в решении — открытые библиотеки без коммерческих лицензий: OpenCV для работы с видео, открытые модели детекции и распознавания номеров, библиотека ArUco для маркеров. Сервис работает локально, на обычном сервере — облачное распознавание не используется, а значит нет и оплаты по числу запросов или подписки на канал камеры, как это устроено у большинства коммерческих ALPR-провайдеров.
| Статья | Коммерческое ALPR-решение | Своё решение |
|---|---|---|
| Лицензия на канал распознавания | обычно да, помесячно или за канал | нет |
| Идентификация тракторов без читаемых номеров | не решает — отдельная задача | закрыта тем же сервисом (ArUco) |
| Оборудование | камеры + иногда специальный контроллер | только камеры |
| Зависимость от облака | часто требуется | нет, всё локально |
Это не значит, что самописное решение — всегда правильный выбор. Там, где нужны десятки камер на разных объектах, круглосуточная поддержка вендора или юридически значимая фиксация нарушений, коммерческая система со своей инфраструктурой и SLA может окупиться быстрее, чем содержание своей разработки. Но для одной весовой с понятным, стабильным ракурсом и известным составом техники — задача оказалась по силам одному разработчику за счёт открытых компонентов, без покупки готового продукта под неё.
05 — ИтогКогда такой подход имеет смысл
Подход себя оправдывает там, где условия съёмки предсказуемы (фиксированная камера, известный ракурс, ограниченный и понятный состав объектов), а интеграция с учётной системой — простая по протоколу, но критичная по задержке. В таких рамках написать собственный сервис на открытых компонентах часто дешевле и гибче, чем встраивать в процесс внешний коммерческий продукт целиком.
Похожая задача на вашем производстве?
Если данные уже собираются, но не связаны между собой в реальном времени — разберём, что можно сделать без покупки отдельного продукта под задачу.