Comments 22
А двухрядные номера как читает? ))
Просмотрел что ли нагрузку на процессор... Хочется прикинуть сколько камер i7 потянет.
Отличный вопрос. Точное количество сильно зависит от разрешения камер, FPS и количества машин в кадре.
На моем i7-9700KF одна камера ~480p@30fps загружала процессор на ~90%. Использовалось видео с "живого" регистратора.
С учетом оптимизаций (пропуск кадров, детектор движения) можно ожидать, что такой процессор уверенно "потянет" 2-3 камеры с разрешением 720p или 1-2 камеры 1080p. Для большего количества уже настоятельно рекомендуется использовать GPU.
YOLO внутри сразу, скорей всего, "пожмёт" Ваши данные к 640х640 и ничего не поменяется. Причём и снизу(480p) и сверху (1080p). Так что в детекции только небольшие накладные расходы..
Извините что опять встреваю)
Да, вы правы. YOLO работает с 640х640, нагрузка от работы нейросети что для 480, что для 1080 особо не изменится. А вот привидение к этим 640х640 для 1080 будет несколько "дороже" по ресурсам.
А в целом по затратам ресурсов, проект сейчас MVP с достаточно "топорной" реализацией, предполагал оптимизировать уже под конкретные задачи/реализации)
Да, не скорей всего, а 100%. ну так в целом получается, дорого-богато. Нам на 200 камер прийдется раскошелиться с таким решением.
Да, вы абсолютно правы. Для 200 камер потребуется совершенно другой подход к архитектуре и "железу".
Этот проект вырос из небольшого фриланс-задания для автосервиса, поэтому и фокус в статье был на максимальной оптимизации под CPU.
Но если говорить о масштабировании на сотни камер, то архитектура решения кардинально меняется - без GPU уже не обойтись
Кстати для таких задач часто используют не полноценные CPU, а что-то вроде Intel NUC с OpenVINO или Jetson Nano от NVIDIA, они оптимизированы именно под инференс нейросетей и при меньшей общей производительности могут показывать лучшие результаты на конкретной задаче, чем "универсальный" Core i7

У Вас на видео в простейшем случае вылезла ошибка, а Вы забыли это упомянуть.
Потому следующие замечания:
1) 100 эпох на yolo8n для детекции номеров на 25к изображений? У меня не то чтобы много опыта, но тот что есть, говорит - скорей всего переобучение. Для подобной задачи это всё ещё большая модель.
2) Вот на видео очевидная пробелма в простейшей ситуации. И подозреваю, что Вы не знаете, как это фиксить. Проблема "коробочного" решения в 2 клика.. Но может я и ошибаюсь - распознаватель-то у Вас свой )
Было бы приятнее прочитать про Ваш опыт, если бы в статье было поменьше восторженных эпитетов, если результат отнюдь не выдающийся.
Однако какой-то результат получили, что уже неплохо!
Спасибо за критику по существу. Вы абсолютно правы, результат не идеален, и статья действительно выиграет от более честного анализа. Позвольте уточнить пару моментов.
1. Про ошибку на видео и контекст задачи.
Вы совершенно верно подметили ошибку OCR. Я специально выбрал такой сложный кадр из "живого" трафика, чтобы продемонстрировать пределы возможностей MVP.
Изначально система проектировалась для более простых условий — статичных камер в автосервисе, где машины неподвижны. Как вы и сказали, для такой задачи текущего качества (с небольшим дообучением на целевых данных) уже достаточно.
Что касается фикса ошибки на видео, то здесь действительно два пути:
ML-подход: Дообучить OCR-модель с более "агрессивными" аугментациями (перспективные искажения, размытие).
CV-подход: Улучшить алгоритм препроцессинга, добавив, например, более сложную стабилизацию изображения перед распознаванием.
2. Про 100 эпох и переобучение YOLO.
Это очень грамотное замечание. Риск переобучения при таком количестве эпох действительно существует. К счастью, в данном случае его удалось избежать, что подтверждается графиками обучения: кривые ошибок для train и val выборок идут почти в унисон, без значительного расхождения. Современные фреймворки, как ultralytics, имеют хорошие встроенные механизмы регуляризации, которые с этим помогают. Но вы правы в главном: пик метрики mAP@0.5-0.95 был достигнут значительно раньше (примерно на 70-80 эпохе), и для экономии ресурсов можно было смело останавливать обучение тогда. 100 эпох были скорее для "чистоты эксперимента".
Хорошее руководство по созданию MVP для сложной ML-задачи. Не стал изобретать велосипед там, где он не нужен (взял YOLOv8), но и не побоялся испачкать руки, когда готовое решение (Tesseract) не подошло.
Особенно ценно решение отложить квантизацию YOLO, когда стало ясно, что риск сломать окружение выше, чем потенциальная выгода - это признак зрелого инженера, а не просто исследователя
Да, использовал, и довольно активно. Мой принцип — ИИ как "второй пилот", а не как автор.
В коде он писал шаблонные вещи и комментарии, позволяя мне фокусироваться на архитектуре. Для статьи и README — выступал в роли стилиста, улучшая форму(иногда слишком и нужно было упрощать, но как говорится "ломать - не строить"), но не суть.
Работая над проектом в одиночку, ИИ действительно становится незаменимым "спарринг-партнером" для отладки и проверки идей. Это интересный и очень продуктивный опыт.
И для одиночного разработчика, когда тебе не у кого спросить/посоветоваться/обсудить и есть только статьи по теме и тех.документация, ИИ достаточно полезен, главное понимать, что ИИ врут достаточно часто, и относится к его ответам критически, хотя бы в рамках своих знаний.
А почему имена YOLOv8n, а не скажем YOLOv11n или YOLOv12n выбрали?
Выбор YOLOv8n был в первую очередь прагматичным решением для MVP, поскольку я уже имел с ней опыт работы. Цель этого проекта была не в поиске самой лучшей модели для этой задачи, а в том, чтобы проверить жизнеспособность идеи и построить полный каркас MVP
Я на днях интересовал этим LPR, взял cv2::Haar для детекции, для OCR начал с Tesseract, это вообще не подходит для этих задач, прям ноль. Потом пробовал EasyOcr, дало средний, но результат, зависит от препроцессинга кадра, руками писал поворот номеров в горизонталь, и самое главное для нее, это размер входного plate в пикселях, нужно от этого отталкиваться, стало хоть немного адекватно работать.
Но, естественно, пришел к тому же датасету, что у вас и что надо обучать свой детектор и ocr, а тут ваша статья, еще и github-ом, для MVP новичкам типа меня бесценно, спасибо вам =D
Спасибо за добрые слова) Очень приятно слышать, что моя статья и репозиторий оказались для вас полезным "шаблоном" и подтверждением ваших выводов. Именно ради таких моментов и стоит делиться своей работой с сообществом. Уверен, с таким подходом у вас все получится!
Так же поделюсь источником-вдохновением - https://habr.com/ru/articles/432444/
Напишу, для тех, кто захочет использовать ваш проект:
Если у вас произвольные данные на входе в пайплайн, скажем с видео камеры:
во первых, надо знать что из вашего frame надо вырезать roi = frame(640*640), иначе модель сожмет все до 640*640 сама и вы потеряете что-нибудь, и детектор будет хуже работать.
во вторых, если детектор найдет bbox размера отличного от 128*32 (обычно меньше), то модель OCR будет ваш bbox ресайзить, что приведет к искажениям символов и вы очень сильно потеряете или вообще не будет находить правильный текст - тут можно от центра bbox увеличить самому extended_bbox = bbox увеличенный до 128*32 с центром от оригинального bbox, а потом уже из img вырезать extended_bbox и передавать в модель OCR - confidence будет 0.87 (или можно кастомный паддинг сделать в transforms.Compose() вместо Resize, кому как).
вдруг, кому-то сэкономит время =D

Собираем ANPR-систему на Python: от YOLOv8 и кастомного OCR до INT8-квантизации