Почему VLM плохо справляются с OCR: гайд по препроцессингу и выбору модели 2024 | AiManual
AiManual Logo Ai / Manual.
14 Янв 2026 Гайд

VLM сломались на ваших сканах: почему мультимодалки не читают текст и как это исправить за 2 часа

VLM ошибаются на сканах, рукописях и таблицах. Пошаговый разбор проблем, препроцессинг изображений, выбор модели (Qwen3-VL, LLaVA) и готовый пайплайн для produc

Вы загрузили скан договора в GPT-4V. Получили поэзию вместо текста

Типичная история: берете современную Vision Language Model, суете ей скан паспорта или договора, а она выдает что-то вроде "На изображении виден документ с текстом. Возможно, это официальная бумага". Или хуже - начинает галлюцинировать, придумывая несуществующие номера и даты.

Вы платите за дорогую модель, а получаете уровень детского сада. Почему так происходит? Потому что VLM - это не OCR системы в классическом понимании. Они созданы для понимания сцен, описания картинок, ответов на вопросы о визуальном контенте. Текст для них - просто еще один визуальный паттерн, как форма дерева или цвет машины.

Главное заблуждение: Раз модель мультимодальная, значит она умеет читать. Нет. VLM обучаются на датасетах типа COCO, где текста мало, он идеально четкий и чаще всего на английском. Ваши размытые сканы с печатями, тенями и кривым русским шрифтом - это другой мир.

Три типа документов, которые ломают любую VLM

Тип документа Что ломается Пример ошибки
Сканы с тенями и бликами Контрастность падает, текст сливается с фоном "Иванов" → "Иванob", цифры 8 и 3 путаются
Рукописные формы Нет единого стандарта написания букв Подпись врача превращается в случайный набор символов
Таблицы и бланки Модель не понимает структуру, теряет связи между ячейками Данные из разных колонок смешиваются в один абзац

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

Почему не работает обычный препроцессинг из учебников

Вы наверняка гуглили "улучшение изображения для OCR" и нашли стандартные рецепты: применить adaptive threshold, увеличить контраст, убрать шум. Проблема в том, что эти методы создавались для старых OCR вроде Tesseract, которые работают с бинарными изображениями (черно-белыми).

VLM работают с RGB изображениями, часто в формате 336x336 или 448x448 пикселей. Когда вы берете скан А4 (3508x2480), уменьшаете до 336x336, а потом применяете резкие фильтры - вы уничтожаете информацию. Текст превращается в месиво из пикселей.

💡
VLM видят мир иначе. Им не нужны кристально четкие буквы - им нужны семантические паттерны. Иногда легкая размытость помогает модели лучше понять контекст, чем перешарпленное изображение с артефактами.

Правильный пайплайн: препроцессинг, который действительно работает

1 Ресайз с умом (не ломайте пропорции)

Первая ошибка - слепо ресайзить до стандартного размера модели. Если у вас таблица 10x10 ячеек, после ресайза до 336x336 она превратится в серое пятно.

# КАК НЕ НАДО ДЕЛАТЬ
from PIL import Image

image = Image.open("scan.jpg")
# Убиваем всю структуру документа
image = image.resize((336, 336))
# ПРАВИЛЬНЫЙ ПОДХОД
from PIL import Image
import numpy as np

def smart_resize_for_vlm(image, target_size=336):
    """
    Сохраняем соотношение сторон, добавляем паддинг
    для квадратного изображения
    """
    # Определяем текущий размер
    width, height = image.size
    
    # Находим максимальную сторону
    max_side = max(width, height)
    
    # Масштабируем так, чтобы максимальная сторона была target_size
    scale = target_size / max_side
    new_width = int(width * scale)
    new_height = int(height * scale)
    
    # Ресайзим с сохранением пропорций
    image = image.resize((new_width, new_height), Image.Resampling.LANCZOS)
    
    # Создаем новое квадратное изображение с белым фоном
    new_image = Image.new('RGB', (target_size, target_size), (255, 255, 255))
    
    # Вставляем наше изображение по центру
    offset = ((target_size - new_width) // 2, (target_size - new_height) // 2)
    new_image.paste(image, offset)
    
    return new_image

2 Убираем тени и выравниваем освещение

Сканы с мобильных телефонов - главный враг VLM. Тень от руки, неравномерное освещение, блики от ламинации. Модель видит это как часть изображения и пытается интерпретировать.

import cv2
import numpy as np

def remove_shadows_and_enhance(image_array):
    """
    Убираем тени и выравниваем освещение
    без потери цветовой информации
    """
    # Конвертируем в LAB цветовое пространство
    # L - яркость, A и B - цвет
    lab = cv2.cvtColor(image_array, cv2.COLOR_RGB2LAB)
    
    # Разделяем каналы
    l, a, b = cv2.split(lab)
    
    # Применяем CLAHE только к каналу яркости
    # Это выравнивает освещение без влияния на цвета
    clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
    cl = clahe.apply(l)
    
    # Собираем обратно
    limg = cv2.merge((cl, a, b))
    
    # Конвертируем обратно в RGB
    enhanced = cv2.cvtColor(limg, cv2.COLOR_LAB2RGB)
    
    return enhanced

3 Сегментация документа перед отправкой в VLM

Вместо того чтобы пихать целую страницу А4 в модель, разбейте ее на логические блоки. Заголовок, таблица, подпись, печать - каждый блок обрабатывайте отдельно.

Это критично для таблиц. Если отправить всю таблицу как одно изображение, VLM потеряет структуру. Если отправить каждую ячейку отдельно - получите точные данные, но потеряете контекст. Решение: отправляйте строки или небольшие группы ячеек.

Выбор модели: какая VLM меньше всего ненавидит ваш текст

Не все мультимодальные модели одинаково бесполезны для OCR. Некоторые проектировались с учетом работы с текстом в изображениях.

Модель OCR способности Минимальные требования Когда выбирать
Qwen3-VL Лучшая среди open-source для текста в изображениях 16+ GB VRAM (fp16) Сложные документы со смешанным контентом
LLaVA-NeXT Средние, но быстрые и легкие 8 GB VRAM Простые документы, нужна скорость
CogVLM Хороша для таблиц и структуры 14 GB VRAM Финансовые отчеты, Excel-подобные таблицы
MiniCPM-V Удивительно хороша для своего размера 6 GB VRAM Бюджетные системы, мобильные приложения

Qwen3-VL - текущий чемпион. Но у нее есть особенность: она требует правильного промптинга. Не просто "прочитай текст", а конкретные инструкции.

# ПЛОХОЙ промпт
prompt = "Что написано на этом изображении?"

# ХОРОШИЙ промпт для Qwen3-VL
prompt = """
Ты вижу документ. Извлеки весь текст максимально точно.
Сохрани форматирование: если текст в таблице, сохрани структуру таблицы.
Если есть нумерованные списки, сохрани нумерацию.
Верни чистый текст без дополнительных комментариев.
"""

Гибридный подход: когда VLM сдаются, вызывайте тяжелую артиллерию

Иногда никакой препроцессинг не поможет. Рукописный текст, каллиграфия, старые документы с потускневшими чернилами. Здесь нужен комбинированный подход.

Пайплайн для самых сложных случаев:

  1. Детекция текстовых блоков - используйте CRAFT, DBNet или любой детектор. Нужно понять, где вообще есть текст.
  2. Классификация типа текста - машинный/рукописный, печатный/курсив, основной текст/сноски.
  3. Маршрутизация:
    • Печатный текст → специализированный OCR (Donut, TrOCR)
    • Рукописный текст → VLM с усиленным препроцессингом
    • Таблицы → CogVLM или табличный OCR
  4. Постобработка - исправление очевидных ошибок, слияние результатов.

Этот подход описан в нашей статье про OCR-воркфлоу для паспортов, но работает для любых документов.

Квантование: как впихнуть Qwen3-VL на RTX 3060

Qwen3-VL в fp16 требует 16+ GB VRAM. На RTX 3060 с ее 12 GB это не запустится. Но можно использовать квантование.

Внимание: Квантование ухудшает качество OCR. Модель теряет способность различать похожие символы (O и 0, l и 1). Для документов с важными числовыми данными это критично.

Если все же нужно квантовать:

# Пример квантования с помощью AutoGPTQ
from transformers import AutoTokenizer, AutoModelForCausalLM
from auto_gptq import AutoGPTQForCausalLM

model_name = "Qwen/Qwen3-VL-7B-Instruct"

# Загружаем квантованную версию
model = AutoGPTQForCausalLM.from_quantized(
    model_name,
    model_basename="model",
    use_safetensors=True,
    trust_remote_code=True,
    device="cuda:0",
    use_triton=False,
    quantize_config=None
)

Но лучше рассмотреть альтернативы. MiniCPM-V дает 80% качества Qwen3-VL при 40% размера. Или использовать imatrix для адаптивного квантования, которое меньше бьет по точности OCR.

Чеклист перед запуском в production

  • Тестируйте на реальных данных, а не на идеальных сканах из интернета
  • Создайте набор "ядрёных" документов: с печатями, подписями, таблицами, низким качеством
  • Измеряйте не только accuracy, но и воспроизводимость (дает ли модель одинаковый результат на одном документе)
  • Настройте fallback: когда VLM выдает низкую уверенность, передавайте документ в классический OCR
  • Кэшируйте результаты: один и тот же документ не должен обрабатываться дважды

Будущее: VLM, которые действительно умеют читать

Проблема VLM и OCR решается на уровне датасетов. Новые модели обучаются на Document Understanding Benchmark, где есть сканы реальных документов со всеми их недостатками.

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

P.S. Если после всех оптимизаций модель все равно путает "ИНН" и "ИНЫ", возможно, проблема не в модели. Проверьте, не установили ли вы ее вверх ногами. (Шутка. Но такое бывает чаще, чем кажется).