«Кульман» — ход работ и замеры

Прототип в песочнице. Цифры на этой странице пересчитываются из файлов замеров при каждом открытии. ← к холсту проверки

1. Что загружено в прототип

2. Конвейер

Станция съёмки
локально: Canon R6 II, контроль кадра
→ Геометрия листа
рамка, формат, шаблон формы
→ Два движка
Tesseract 5 LSTM + PP-OCRv5
→ Нормализация
справочники, правила ЕСКД/ЕСТД
→ Риск и маршрут
автоприём / проверка / слепой ввод
→ Холст проверки
оператор
→ Выпуск
PDF/SVG/DXF, PDF/A, XLSX, JSON
→ Дообучение
на исправлениях

Внешние нейросети подключаются только через шлюз обезличивания и получают вырезки граф, а не лист; каждое обращение пишется в журнал (кнопка «Журнал шлюза»). В этой демонстрации внешние нейросети не вызываются.

3. Реальные листы: основная надпись чертежей

46 листов, 244 непустых граф из 357. Эталон черновой: прочитан нейросетью по обезличенным вырезкам, спорные графы сверены по увеличенным вырезкам. Ошибка в символах (CER) считается без пробелов.

ВариантТочность граф (непустые)CER, ppm (непустые)Точность граф (все)
Tesseract 5 (один)35,7 %415 37152,9 %
PP-OCRv5 / RapidOCR (один)71,7 %195 79178,1 %
Конвейер, как сохранён69,3 %188 93074,5 %
Конвейер, веса выучены на других листах74,6 %173 37678,1 %
ГрафаnTesseractPP-OCRv5Конвейер
Обозначение2814,3 %57,1 %57,1 %
Наименование4544,4 %66,7 %71,1 %
Материал3813,2 %39,5 %44,7 %
Масса3066,7 %83,3 %86,7 %
Масштаб4528,9 %97,8 %95,6 %
Листов3941,0 %89,7 %89,7 %
Лист850,0 %50,0 %75,0 %
Литера1145,5 %54,5 %63,6 %
Разрешение листа, dpinPP-OCRv5КонвейерCER конвейера, ppm
80–11013679,4 %83,1 %68 376
<806555,4 %53,8 %320 346
>1104372,1 %79,1 %238 390

Оба движка дали одно значение в 33,6 % граф; в этих случаях верно 91,5 %. Низкое разрешение (меньше 80 dpi) — главный источник ошибок: в архиве это сканы из интернета. Canon R6 II (24 Мп, 6000×4000) при кадре по формату листа даёт около 340 dpi на A3 и около 180 dpi на A1 — крупные форматы нужно снимать частями.

4. Реальные листы: маршрутные карты ГОСТ 3.1118

4 карты с верно найденной структурой, 236 граф, 3 525 символов. Эталон черновой (нейросеть по вырезкам граф таблицы, без шапки и подписей) + сверка спорных граф по увеличенным вырезкам.

ВариантТочность графCER, ppm
Tesseract 5 (один)66,1 %51 348
PP-OCRv5 / RapidOCR (один)95,8 %1 135
Конвейер, как сохранён97,0 %0
Конвейер, пересчёт текущим кодом96,2 %567
Конвейер, веса выучены на других листах97,0 %0
Тип графыnTesseractPP-OCRv5КонвейерCER конвейера, ppm
Тексты переходов4740,4 %93,6 %93,6 %0
Оснастка, инструмент3672,2 %88,9 %88,9 %0
Цех, участок, РМ27100,0 %100,0 %100,0 %0
КР, КОИД, ОП2615,4 %100,0 %100,0 %0
Нормы (Тпз, Тшт)23100,0 %95,7 %100,0 %0
Номер операции9100,0 %100,0 %100,0 %0
Код и наименование операции933,3 %100,0 %100,0 %0
Документы (ИОТ)977,8 %100,0 %100,0 %0
Оборудование988,9 %77,8 %100,0 %0
Код профессии9100,0 %100,0 %100,0 %0
СМ8100,0 %100,0 %100,0 %0
Разряд8100,0 %100,0 %100,0 %0
УТ862,5 %100,0 %100,0 %0
ЕН80,0 %100,0 %100,0 %0

Оба движка согласны в 65,7 % граф; при согласии верно 98,7 %, CER 0 ppm. Не вошли в посимвольную оценку (структура не совпала с шаблоном):

5. Синтетика: проверка методики (выборки A–D)

A — обучение (дообучение Tesseract, выученные правила); B — подгонка риска; C — калибровка порогов (LTT/Клоппер–Пирсон, α на класс); D — тест. Допуск на ошибку автоприёма α = 250 ppm на класс граф.

КонфигурацияСырой CER, ppmТочность графАвтоприём, графАвтоприём, символовОшибок автоприёмаВерхняя граница 95 %, ppmИтог (проекция), ppm: оператор 0,05 % / 0,2 %
1. Базовые движки, эвристический риск21 32092,4 %32,1 %19,7 %3194312 / 970
2. Базовые движки, модель риска21 32092,4 %58,8 %34,5 %075254 / 993
3. + выученные правила (из исправлений A)13 43895,3 %61,7 %42,5 %075234 / 918
4. + дообученный Tesseract (на вырезках A) + правила для PP-OCR13 36395,2 %61,8 %36,4 %075250 / 976

Итоговый ppm документа = ошибки автоприёма + ошибки, оставшиеся после ручной проверки. Поэтому цель 600 ppm определяется не только распознаванием, но и качеством проверки: при ошибке оператора 0,2 % проекция выше цели, при 0,05 % (двойной слепой ввод критичных граф) — ниже. Дообучение Tesseract: 3705 строк выборки A, ошибка на обучении 1,8 %; на контрольной выборке D сырой CER почти не изменился, доля автоприёма по символам снизилась — в текущем виде дообучение не дало выигрыша и в конвейер по умолчанию не включено.

6. Геометрия листа и размеры (ISO 129 / ГОСТ 2.307)

Ответ на вопрос «почему не распознаются линии, обозначения и размеры»: конвейер до недавнего времени читал только текстовые зоны. Теперь лист разбирается целиком: векторизация (сегменты, осевые, штриховка, окружности) + модуль размеров — детекция стрелок (эрозия → шаблон → кольцо фона), пары стрелок → размерные линии с поддержкой сегментами, лидеры, значения (в том числе повёрнутые на 90° вертикальные размеры), предохранители цепочек. Всё это — редактируемым текстом в выпуске (vector.pdf/svg/dxf) и отдельным слоем на холсте (кнопка «вектор», клавиша V).

ЛистовСтрелок (медиана/лист)Пар стрелок → размерыЛидеровРазмеров со значениемВремя размеры / векторизация, с/лист
466064 (107)72924521100 из 3181 (35%)14.9 / 5.5

Замер честный: 46 реальных чертежей RUS (штампы), без синтетики. Качество ЗНАЧЕНИЙ размеров в эту цифру не входит — часть значений OCR читает с ошибками (Ø20→620, 12h7→1247), они попадают на холст для правки оператором; структура (линии, стрелки, привязка значений) детектируется стабильно. Оверлеи для визуальной сверки — data/eval/dims_overlays/doc_N.png (серым — геометрия, зелёным — размерные пары, красным — значения). Следующие шаги: знаки шероховатости и допусков формы, точность значений, редактирование размеров оператором на холсте.

7. Векторная выдача: контурный слой вместо «каши»

Проверка выдачи глазами (чистый вектор без подложки, 4 листа) показала: скелетная трассировка принципиально не даёт читаемого чертежа — контуры рвутся на углах и Т-примыканиях, толстые линии дают двойной след, почти половина нарисованного приходится в пустоту. Поэтому визуальный слой переведён на промышленный метод (как potrace/autotrace в чертёжных сервисах): обводка границ чернильных областей → замкнутые полигоны. Семантический слой (отрезки, оси, дуги, окружности — для размеров и CAD) сохранён рядом.

Метрика (46 реальных листов RUS)Скелет (было)Контуры (стало)
Полнота чернил (recall)0,9950,999
Точность (доля вектора в чернилах)0,4860,996
IoU с допуском ±1 px—0,833
Время на лист (медиана)1,8–7,1 с0,08 с
Элементов на лист (медиана)≈1100 сегментов669 полигонов
Экспертная оценка чистого вектора (A/B на одном листе)15 %98 % PDF / 85 % DXF-контуры

Сквозной замер «PDF против чернил листа» (PDF отрендерен в разрешении самого скана, 7 листов): полнота 99,1 %, точность 100,0 % (в векторе нет ничего, чего нет в чернилах), площадь чернил 0,95 от исходной — то есть линии больше не «жирнее» оригинала.

Вторая правка — толщина линий. Сначала контур рисовался с компенсирующей обводкой 0,9 px, и замер показал перебор: площадь чернил +25 % (штрихи выходили толще скана, близкие линии слипались). Замена на сдвиг контура наружу на 0,52 px без обводки (граница чернил лежит ровно на полпикселя от центра краевого пикселя) дала строгий IoU 0,7041 → 0,8554 и площадь 0,722 → 1,052. Заодно 1-px штрихи (выносные, размерные) перестали пропадать: у них появилась площадь.

Приёмка на проде (пакетный перевыпуск, 31.10.2026). Все 79 документов перевыпущены заново (46 чертежей + 33 маршрутные карты), ошибок 0. По каждому чертежу проверено машинно: PDF открывается и его страница равна листу, текстовый слой не пуст (0 пустых), контурный DXF не выходит за поле (0 нарушений), у параметрического проверены обе оси и семьдесят шесть дуг-артефактов у кромки листа отброшены, параметрический DXF содержит все шесть слоёв ГОСТ с правильными весами и типами линий — 46 из 46 файлов без замечаний. В параметрических файлах: 121 170 линий, 2 608 дуг, 143 окружности, 4 953 текста. Маршрутные карты: 33 из 33 с PDF, SVG и XLSX (у них DXF не формируется — это таблицы, а не графика).

Что в выпуске: vector.pdf — контуры (заливка even-odd, дырки режутся) + невидимый текстовый слой (PDF text render mode 3): значения остаются выделяемыми и искомыми, но не двоятся поверх глифов — проверено: сотни извлекаемых символов при 0 изменённых пикселях. vector.svg — те же полигоны, текст с fill-opacity=0. vector.dxf — HATCH (solid, с дырками) + замкнутые LWPOLYLINE в слое KONTUR; осевые и центровые — на отключённом слое SEMANTIKA, OCR-слой — TEXT_OCR. vector_param.dxf — параметрический каркас: LINE/ARC/CIRCLE/TEXT/DIMENSION с толщинами и типами линий по ГОСТ 2.303 (основная 0,60, слой 01_OSNOVNAYA; тонкая 02_TONKAYA, осевая 03_OSEVAYA, штриховая 04_SHTRIHOVAYA, штриховка 05_SHTRIHOVKA 0,18, текст 06_TEKST); размеры — сущности 07_RAZMERY, спорные — 08_SPOR, сырой OCR — на отключённом 09_OCR_RAW. Это черновой редактируемый слой: после субпиксельного уточнения ось ложится на центр штриха с ошибкой 0,1–0,25 px (было 0,5–1,0), но семантика листа распознана не полностью — поэтому файл идёт отдельно от контурного, а не вместо него.

Честные ограничения: (1) контурный слой — точная «печатная копия» листа, геометрия в нём не параметрическая; (2) растровая нормировка толщин (скелет + карта ширин + перерисовка 2/4 px) по-прежнему выключена — она портит точность (0,999 → 0,92), и её заменила нормировка в векторном пространстве (слои 01_OSNOVNAYA / 02_TONKAYA по ГОСТ 2.303, см. раздел 8); (3) ручная правка значений размеров работает через семантику (meta["dim_values"] и DIMENSION в параметрическом DXF), а не через перерисовку пикселей.

7а. Чистая отрисовка линий: гибрид «штрихи + остаток» (31.10.2026)

Задача от пользователя: «чистые копии сканов с раздельными контурами, осями, размерами, штриховкой и текстом». Контурный слой раздела 7 точен (recall 0,999), но это «печатная копия»: заливка полигонов повторяет все неровности скана, толщины гуляют, линии не редактируются как линии. Новая выдача (KULMAN_CLEAN_LINES=1 — по умолчанию с 31.10.2026) собирает видимый слой из трёх честных компонент: (1) параметрические штрихи с ИЗМЕРЕННОЙ шириной (p60 профиля поперечного сечения с браковкой засорённых замеров) — прямые рисуются векторами, а не следами пикселей; (2) контуры «остатка» — чернила, не покрытые штрихами (стрелки, узлы, сопряжения, глифы) считаются от ТОЧНОГО экспортного набора; (3) глифы скана вместо шрифтового текста: шрифт ГОСТ не совпадает со сканом по форме и жирности — на листе 10 это стоило 8 п.п. полноты и 4 п.п. точности. Видимые чернила — контуры глифов (копия 1:1), а редактируемость обеспечивает невидимый текстовый слой (render mode 3): текст извлекается и ищется, но не рисуется поверх скана. Набранный вид шрифтом — опция KULMAN_TEXT_FONT=1.

Корневой баг, найденный сквозным замером. Первые версии гибрида держали recall ≈0,90 при «идеальном» внутреннем союзе 1,00. Причина: скелетные сегменты букв покрывали глифы в рендере — остаток считал текст уже нарисованным и не включал его; на выпуске filter_text_skeleton эти сегменты убирал (в параметрике буквы штрихами не рисуются) — и текст оставался вообще без краски (~10 % чернил листа). Симуляция «кэш-союза» лгала, рисуя неотфильтрованный кэш. Лечение: recompute_residual — остаток пересчитывается от точного экспортного набора штрихов после появления OCR-рамок (api._with_dims).

Метрика (сквозной замер: PDF рендерится в DPI скана, сравнение с чернилами)Контурный (лист 10)Шрифтовой гибрид (было, лист 10)Гибрид v15 (лист 10)
Полнота чернил (recall)0,9800,9040,955
Точность (precision)0,9420,8590,904
Площадь чернил0,8391,1231,205
Медиана по 46 листам (v15)——recall 0,946 / precision 0,922 / площадь 1,126
Провалов на 46 листах——0 (средняя пересборка 51,6 с)
A/B-экспертиза (3 панели: скан / было / v15)—задвоение цифр, чужой шрифт, дырыдефектов не выявлено

AA-защита тонкого. Заливка тоньше ~1 мм при растеризации расползается в серую кайму и исчезает («2» в «26,4» пропадала целиком) — тонким полигонам добавлена обводка 0,35 мм; метрика тонкости — 2·S/периметр (площадь/bbox врала в 2–3 раза на криволинейных глифах). Тонкие линии таблиц (1–2 px) вернул в остаток расчёт от сырой adaptive-маски вместо эродированной open 2×2; субвизуальный сор (< 5 px вне текстовых зон) отбрасывается.

Флаги отката: KULMAN_CLEAN_LINES=0 — контурный режим (раздел 7), KULMAN_TEXT_FONT=1 — набранный шрифтовой текст, KULMAN_AA_PAD — добавка к ширинам (по умолчанию 0: прогон показал падение точности без выигрыша полноты). Честное ограничение: площади чернил 1,13–1,21 — штрихи измеряются по сырой маске и несут ореол скана; выборка «профиль ядра» жирнее срезает кайму, но рвёт recall — оставлено на A/B будущих прогонов. Данные: data/eval/clean46_v15.json, tools/real/clean46_v15.py; сравнения data/eval/ab10_3pan_*.png.

7б. Профиль ядра: срезка ореола штрихов (01.11.2026)

Ограничение 7а (площади 1,13–1,21 — штрихи несут ореол скана) снято замером ширины по профилю ядра: сечение штриха поперёк оси по серому (не по бинарной маске), порог на уровне level·контраста («бумага − level·(бумага − чернила)»), ширина — между пересечениями порога с линейной интерполяцией. Ореол скана (blur + adaptive) симметричен и середину профиля не сдвигает, а в бинарную маску кайма запечена — поэтому маска-перемер систематически жирнее. Агрегация по штриху: p60 годных сечений с отбраковкой проб (блоб пересечения — слипшийся сосед). Защита recall: срез относительно маски-перемера ограничен 1,6 px (KULMAN_CORE_MAXCUT — срез шире ~1 px на сторону выходит из допуска ±1 px сквозного замера), минимум 1 px, капы по ГОСТ 2.303 сохранены. Для дуг/окружностей — радиальные сечения. Кайма вокруг штрихов в остаток не попадает (фильтр остатка режет компоненты внутри ±2 px от рендера штриха), вылеты за допуск замера компенсируются — «двойных кромок» нет.

Метрика (46 листов, медианы)v15 (ширины по маске)Профиль ядра (L040 + maxcut 1,6 px)Δ
recall0,9460,940-0,0062
precision0,9220,926+0,4 п.п.
площадь чернил (рендер / маска скана)1,1261,051−0,075 (лишние чернила срезаны на 7%)
Провалов00—
Средняя пересборка листа51.6 с66.8 с+15 с (замер сечений)
Худший лист (31, 94 dpi)recall 0,897recall 0,888−0,9 п.п. — плата за срезку каймы

Конфигурация выпущена как дефолт (vectorize.py): KULMAN_CORE_PROF=1, KULMAN_CORE_LEVEL=0.40, KULMAN_CORE_MAXCUT=1.6; GEOM_CACHE_V=16. Уровень сечения и maxcut выбраны свипом на листах 10/31/14 (5+4 конфигурации, сквозной замер pdf_vs_raster-методикой): L060 срезает площадь до 1,085, но теряет −2,8 п.п. recall на листе 10; L040 без maxcut теряет −1,2 п.п.; L040+MC1,6 — медианная просадка −0,6 п.п. при −7% лишних чернил. Листов с просадкой recall хуже −0,02: 1 из 46.

Откат: KULMAN_CORE_PROF=0 — ширины по маске (v15). Ловушка кэша: GEOM_CACHE_V не различает параметры CORE — при смене LEVEL/MAXCUT поднимать версию кэша вручную (01.11 листы 10/31/14 пересчитались со старым конфигом mc24 из-за этого). Данные: data/eval/clean46_core.json, tools/real/clean46_core.py, калибровка tools/real/core_sweep.py; сравнения data/eval/ab10_core_*.png.

8. Три нерешённые проблемы: как закрыты 31.10.2026

Каждая из трёх проблем разобрана по АРИЗ-85В как техническое противоречие: улучшение одной стороны ухудшало другую, поэтому «подкрутить параметр» не помогало. Ниже — противоречие, приём разрешения и замер.

ПроблемаТехническое противоречиеПриём разрешения (АРИЗ)Замер
Параметрический DXF гуляет на 1–2 pxТочность ↔ топология: скелет живёт в целых пикселях (точнее 1 px не бывает), но только он даёт связность и порядокРазделение функций во времени: скелет отвечает только за то, какие пиксели принадлежат штриху; положение оси считается по всем пикселям этого штриха — поперечный профиль → центр масс → МНК по 5–30 сечениям → привязка концов к пересечениямсмещение оси 0,16 px (было 0,50–0,98), p90 1,27 px; покрытие чернил ±1 px 83,4 % по чистой геометрии; строгий IoU 0,299 — сравнивать со старым 0,37 нельзя: тот прогон рисовал скелет букв поверх печатного текста, теперь буквы в графике не рисуются, а ширины взяты по ГОСТ (осознанная потеря precision при верном центре)
Нормировка толщин ломала точностьРовные толщины ↔ точность: перерисовка растра в 2/4 px даёт идеальный ряд ГОСТ, но сдвигает кромки (0,999 → 0,92)Перенос свойства в другую подсистему: нормировка уходит из растра в вектор. Толщина становится атрибутом слоя, геометрия не трогается вообще; номинальная пара определяется по отношению кластеров ширин (инвариант к растеканию краски), а не по абсолютуотношение кластеров 1,8–2,5 → пара 0,25/0,60 мм; δ скана 0,25–0,42 мм; точность контуров не изменилась
Значения размеров — графикаРедактируемость ↔ верное число: в CAD правится либо геометрия, либо текст, но не оба; OCR даёт неверные числа (Ø20 → 620)Разделение противоречивых требований по объектам: число делает геометрия (DIMENSION с текстом «<>»), OCR работает только арбитром. Три исхода: подтвердил → ассоциативный размер; расхождение 8–12 % (размерная линия обрывается под числом) → концы линии доводятся до числа; несоизмеримо → число отбрасываетсяна 46 листах: 5964 размеров, в DXF как DIMENSION — 1002 (ассоц. 860, выровнено 16, спорных 126); отброшено OCR-чисел 130; правка значения с холста проверена сквозняком (холст → DXF DIMENSION → текстовый слой PDF)

Что ещё дало уточнение. Дубли линий снимаются жёстко уже после уточнения (смещение < 1,6 px, угол < 2°): удалено 584 дублей на 46 листах. Коллинеарные обрывки склеиваются в целые линии при разрыве ≤ 2,5 px — 3241 склеек (в CAD линия должна быть одной, а не из кусков). Концы притягиваются к пересечениям с допуском ≤ 2,5 px — 30053 привязок; более широкий допуск (10 px) рвал покрытие чернил, поэтому оставлен физический недолёт. Ширина штриха теперь берётся из длины чернильного участка в профиле, а не из карты расстояний: прежняя оценка 2·dt при смещённой оси давала «толщину» 5,3 px у штриха 1,2 px.

«Каша» вокруг надписей — откуда бралась. Скелет каждой цифры — это 5–15 коротких штрихов внутри контура знака, и они попадали в параметрический слой поверх того же числа, напечатанного как текст: место рисовалось дважды. Замер на листе 10: 199 рамок распознанных строк, в них 390 отрезков из 1960 (20 % всего слоя). Теперь скелет знаков в параметрику не идёт, но удаляются только короткие фрагменты (≤ 2,5 высоты строки): длинная размерная или контурная линия, проходящая под числом, остаётся. Результат на листе 10: слой 1570 отрезков вместо 1960, доля тёмного внутри текстовых рамок в превью упала с 31 % (как в растре) до 4,7 %, контурный слой не изменился вообще (652 полигона), то есть PDF-копия листа осталась точной.

Мусор OCR больше не становится числом размера. Раньше в DIMENSION уходило всё, что прочитал OCR: на листе 10 из 39 значений «с числом» оказались «S|», «|», «~» — то есть в CAD печаталась не цифра. Добавлено правило правдоподобия: в значении обязан быть хотя бы один десятичный знак, а символы — только из набора ISO 129 (цифры, разделители, Ø/⌀, R, M, x, °, ±, допуски в скобках). На листе 10 отбраковано 7 значений из 39; такой размер остаётся в DXF как измеряемый («<>» — число берётся из геометрии), а не с чужим текстом.

Правка размера на холсте — теперь замкнутый контур, проверено сквозняком. Цепочка: щелчок по числу на холсте → POST /api/documents/ID/dim_value → meta["dim_values"] → перевыпуск. Проверка на листе 10: правка «Ø99,9» появилась (1) в ответе холста с пометкой «правлено» и сохранённым машинным значением, (2) в DXF как текст сущности DIMENSION, (3) в PDF в извлекаемом текстовом слое; снятие правки возвращает машинное. При этом найдена и закрыта ловушка: /vector отдавал закэшированный meta["dims"] и холст показывал СТАРОЕ число после правки — теперь правки накладываются на отдаваемый слой всегда.

Проверка невидимого текстового слоя (было «не подтверждено»). Прошлый тест сравнивал два разных рендера и потому ничего не доказывал. Прямая проверка: из content-stream удалены все операторы BT…ET (111 блоков), оба PDF отрендерены при 150 dpi и сравнены попиксельно — 0 отличий на 4 355 910 пикселях, при этом из исходного файла извлекается 110 текстовых span. Слой невидим и при этом остаётся копируемым и искомым.

Перетолщение контурного слоя — найдена круговая настройка. Прежний сдвиг контура 0,52 px подбирался свипом против СОБСТВЕННОЙ адаптивной маски (площадь 1,052, IoU 0,855) — сравнение получилось круговым: где маска сама жирнее полутона скана (штрих 2,8 px против 2,0 по полутону на листах 7 и 10), полигоны повторяли эту жирность, и PDF был толще скана на 24–40 % (медиана штриха в надписях 0,508 мм против 0,382 в скане; разница держалась на всех порогах бинаризации рендера). Теперь сдвиг подбирается по странице автоматически: измеряем ширину штриха в маске и в полутоне (gray<128), разницу компенсируем минусом к сдвигу (лист 10 → сдвиг 0,12 px). Результат на листе 10: штрих PDF 0,372 мм против 0,382 в скане (−3 %), строгий IoU против полутоновых чернил 0,57 → 0,65; где маска совпадает с полутоном (листы 14–47), сдвиг остаётся 0,52 — поведение не меняется. Тонкие серые линии, которые ловит адаптивная маска и теряет жёсткий порог, по-прежнему покрыты (±1 px: 0,997). Заодно убрана двойная отрисовка в SVG — контур там рисовался заливкой ПЛЮС обводкой 0,12 мм, хотя PDF давно рисуется чистой заливкой.

Текст — шрифтом, а не контурами (решение по требованию заказчика). Буквы теперь печатаются шрифтом ГОСТ 2.304: в PDF — видимым извлекаемым текстом (pdftotext возвращает значения), в vector.dxf — примитивами TEXT на включённом слое TEXT (было: выключенный TEXT_OCR), в SVG — видимыми <text>. Контуры отсканированных букв под текстовыми рамками убираются — но только целиком лежащие в рамке (лист 10: 652 → 558 HATCH, 107 TEXT): цифра, слитая с линией, остаётся контуром, чтобы не рвать линию. Где OCR не нашёл текст — глифы остаются контуром, ничего не теряется. Цена решения: ошибки OCR теперь ВИДНЫ — это и есть редактируемый текст, правится на холсте. Замер после перехода (7 листов): recall 0,992 / precision 1,000 / IoU 0,757, площадь чернил 1,10 — шрифтовые глифы чуть отличаются от сканированных. Откат: KULMAN_TEXT_FONT=0.

Ограничения, которые остаются честно: (1) контурный DXF остаётся главным CAD-файлом — параметрический слой теперь точный по положению, но неполный по семантике (распознаётся примерно четверть размерных линий листа); (2) ручная правка значений размеров сохраняется в meta["dim_values"] и применяется при каждом выпуске, но в самом PDF размер по-прежнему нарисован контуром — правится семантика, а не пиксели; (3) при масштабе листа, отличном от 1:1, ассоциативный размер опирается на распознанное число, а не на истинный масштаб чертежа.

9. Где мы относительно цели 600 ppm

10. Следующие шаги

  1. Правила разбора маршрутных карт: префикс «ИОТ», «код + модель станка», 3/З в моделях, римские цифры в «ШЦ-II», пробелы между словом и номером, пословный выбор между движками по словарю.
  2. Проверка структуры карты (если сетка не совпала с шаблоном — ручная разметка столбцов вместо чтения).
  3. Справочники подтверждённых значений (оснастка, оборудование, документы, типовые переходы) — пополняются из исправлений.
  4. Опыт по разрешению 100/150/200/300 dpi и калибровка порогов автоприёма на реальном эталоне.
  5. Полнота размерной семантики: сейчас распознаётся около четверти размерных линий листа — расширять детектор (радиальные и диаметральные размеры, размеры с полками, шероховатость и допуски формы).
  6. Параметризация контуров: привязка полигонов к семантическим примитивам (линия/дуга/окружность) — контурный DXF уже точен, следующий шаг — заменить полигоны примитивами там, где это возможно без потери формы.