Введение
Прежде чем углубляться в суть вопроса, в конкретные тонкие моменты заголовка и вводить в курс domain, неплохо бы рассказать предысторию. Если ты студент в современной AI-реальности, найти практику или стажировку для работы с реальными онлайн-наборами данных не так уж и легко. Следовательно, тебе либо остаётся брать из открытых источников (не Kaggle — там всегда чётко согласованные датасеты), либо самому размечать данные.

Прикладной кейс
Выбирать было не из чего: в рамках программы обучения были всего три компании. И как всегда пошёл из принципа — продуктивность и оптимизация превыше AI slop задач без фундамента. Выбрал АО «Метрогипротранс» — проектный институт, который хранит чертежи метрополитенов. И сразу что бросилось в глаза — их оцифровка.

Задача в терминах ML
Детекция основной надписи чертежей для их дальнейшей каталогизации и извлечения метаданных посредством OCR в BIM-системы. Первичная подготовка scan-to-BIM пайплайна. Классификация основной надписи (далее — штамп) по формам ГОСТ 2.301-68. Именно благодаря ГОСТу мы определяем «решаемость» только что выдуманной задачи. Короче говоря, люди вручную перебирают сканы в поисках нужного чертежа, проекта или сметы, а я предлагаю утилиту, которая делает это автоматически, высвобождая человекочасы.

Данные. Неужели так мало?
Как и богатства для человека, набора данных для ИИ никогда не бывает много. Поэтому я намеренно закрутил гайки для «самой лучшей» модели компьютерного зрения — YOLOv8 (спойлер: не дали доступ к данным, хоть и согласился на NDA). Нашёл в интернете пару десятков чертежей, некоторые пришлось перевести из DWG в JPG. Разметил штамп с помощью LabelStudio и сделал экспорт YOLO-аннотаций. Из ниоткуда получил 50 чертежей. Мало, но терпимо. «Синтетика и аугментация выручат», — думал я. Очень пожалел вскоре (4 версии обучающей выборки, утечки).

Синтетика
Как бы сильно мы ни топили за естественную природу вещей, даже крупные IT-компании начали использовать синтетические данные для обучения моделей. Одна из распространённых практик — вырезать целевой класс (в нашем случае штамп) и вставить его на фон из другой картинки. И так перекрёстно создавать датасет, пока из 50 не получим 500 чертежей. Но ограничиваться только этим было бы наивно, поэтому я ещё создал несколько чертежей с фоновым шумом и нарисованным штампом по ГОСТ используя Pillow. Все размеры чётко обозначены в стандартах.

Обучение и baseline
Главная цель модели — выучить физические геометрические пропорции штампов (~3,36 — соотношение длины и ширины, см. рис. 1–2), чтобы отличать их друг от друга. YOLO будет фейлиться, если не сделать маппинг из пикселей в миллиметры и не заставить модель учить геометрию, а не пиксельное сходство. С чем, кстати, baseline OpenCV очень хорошо справляется. Получаем простой if-else алгоритм через контуры с CLAHE внутри обрезанной области чертежа (справа снизу или снизу в зависимости от ориентации), что уже сокращает ложные срабатывания на 50–75%. Стоит отметить что референс перевода пикселей в миллиметры также описан в полиграфических ISO стандартах в зависимости от размера отксанированного A-листа и PPI pixels per inch каждого чертежа. В моих размеченных чертежах пиксели и соотношения высоты на ширину строго соответствуют ISO 216 (см. рис. 3).

Рисунок 1. Распределение aspect ratio штампа
Рисунок 1. Распределение aspect ratio штампа
Рисунок 2. Распределение физической площади штампа
Рисунок 2. Распределение физической площади штампа
Рисунок 3. Распределение разрешений изображения.
Рисунок 3. Распределение разрешений изображения.

Стопроцентный IoU и F1. Это победа?
На малых данных YOLO был переобучен, не говоря уже об утечке. Кривые скрипты брали фоновые изображения из тестовой выборки — технически штамп был вырезан и закрашен, но текстура и шум фона были те же самые. Модель не учила штамп, она учила фон. Когда я это понял — пересчитал всё заново. IoU упал с 1.0 до реальных цифр. Обидно, но честно.

Закручивать гайки
Сравнение было некорректным: OpenCV не видит ничего лишнего и хорошо обобщает в рамках алгоритма, а YOLO нуждается в 80% данных для обучения. Я решил ограничить поток данных для трейна — стратифицированно выбрал 4 реальных чертежа в качестве доноров, вырезал целевой штамп и вставил поверх других изображений. В итоге из реального датасета (50 чертежей) модель видела только 4–5 из них (~10%) — это выглядело справедливо. Зачем? Чтобы модель запоминала геометрию прямоугольника, а не каждый пиксель изображения.

Выводы
Заставить DL-модель с намеренно ограниченными данными находить целевой класс и обобщать геометрию — компромисс между overfitting и underfitting. В конкретно этом кейсе не стоит использовать телескоп в качестве молотка, когда логика сводится к простому алгоритму. OpenCV выбил IoU=0.640 и F1=0.727, YOLOv8 — IoU=0.579 и F1=0.754. DL увереннее в детекции, но пересечение с ground truth ниже - что в общем-то очевидно (см. рис. 4-5).

Рисунок 4. Сравнение моделей по IoU метрике
Рисунок 4. Сравнение моделей по IoU метрике
Рисунок 5. Сравнение  по F1 score
Рисунок 5. Сравнение по F1 score

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