Типичная ситуация: клиент присылает 500 страниц отсканированных отчётов — таблицы, графики, хаотичный текст. Обычный OCR возвращает простыню символов: столбцы смешаны, строки разорваны, структура потеряна. Задача Table Recognition — найти таблицы и восстановить их сетку. Мы решаем эту задачу с помощью пайплайна на Table Transformer, camelot и постобработки. Результат — чистые DataFrame, готовые для загрузки в базу или Excel.
Мы — команда с 5+ летним опытом в Computer Vision и NLP. На счету — 30+ проектов по извлечению данных из документов для банков, логистики и ритейла. Гарантируем точность >95% на стандартных документах и полную поддержку после внедрения.
Как Table Transformer решает задачу распознавания таблиц?
State-of-the-art: Table Transformer от Microsoft, основан на DETR, обучен на PubTables-1M (947k таблиц из научных публикаций). Детектор находит таблицы, структурный распознаватель восстанавливает строки и столбцы. Для каждого бокса мы запускаем OCR (Tesseract или EasyOCR) для извлечения текста ячеек. Сравнение: Table Transformer лучше camelot для сканов в 2–3 раза по точности (93% vs 70%), но требует GPU.
from transformers import TableTransformerForObjectDetection, DetrImageProcessor from PIL import Image import torch class TableExtractor: def __init__(self): # Детектор таблиц self.det_processor = DetrImageProcessor.from_pretrained( 'microsoft/table-transformer-detection' ) self.det_model = TableTransformerForObjectDetection.from_pretrained( 'microsoft/table-transformer-detection' ) # Структурный распознаватель self.str_processor = DetrImageProcessor.from_pretrained( 'microsoft/table-transformer-structure-recognition' ) self.str_model = TableTransformerForObjectDetection.from_pretrained( 'microsoft/table-transformer-structure-recognition' ) def extract_tables(self, image_path: str) -> list[dict]: image = Image.open(image_path).convert('RGB') # 1. Детектируем таблицы table_boxes = self._detect_tables(image) tables = [] for box in table_boxes: # 2. Кропаем каждую таблицу table_crop = image.crop(box) # 3. Распознаём структуру (строки/столбцы) structure = self._recognize_structure(table_crop) # 4. Извлекаем текст из ячеек через OCR cells = self._extract_cell_texts(table_crop, structure) tables.append({ 'bbox': box, 'structure': structure, 'cells': cells, 'dataframe': self._cells_to_dataframe(cells) }) return tables def _detect_tables(self, image: Image.Image) -> list[tuple]: inputs = self.det_processor(images=image, return_tensors='pt') with torch.no_grad(): outputs = self.det_model(**inputs) target_sizes = torch.tensor([image.size[::-1]]) results = self.det_processor.post_process_object_detection( outputs, threshold=0.7, target_sizes=target_sizes )[0] boxes = [] for label, box in zip(results['labels'], results['boxes']): if label == 0: # table class x1, y1, x2, y2 = box.tolist() boxes.append((int(x1), int(y1), int(x2), int(y2))) return boxes camelot или pdfplumber: что выбрать для вашей задачи?
Для цифровых PDF (не сканов) camelot — лучший выбор. Lattice-режим работает с таблицами, имеющими линии, stream — с выровненным текстом. pdfplumber даёт гибкость смешанных документов, но требует ручной настройки. Мы выбираем инструмент под тип документа: для отчётов с линиями — camelot lattice, для сложных макетов — pdfplumber с кастомными настройками.
import camelot def extract_tables_from_pdf(pdf_path: str, pages: str = 'all') -> list: # Lattice: для таблиц с явными линиями tables_lattice = camelot.read_pdf( pdf_path, pages=pages, flavor='lattice' ) # Stream: для таблиц без линий (выровненный текст) tables_stream = camelot.read_pdf( pdf_path, pages=pages, flavor='stream', edge_tol=50 ) results = [] for table in tables_lattice: if table.accuracy > 80: results.append({ 'page': table.page, 'accuracy': table.accuracy, 'dataframe': table.df, 'csv': table.df.to_csv(index=False) }) return results pdfplumber для смешанных документов
import pdfplumber import pandas as pd def extract_tables_pdfplumber(pdf_path: str) -> list[pd.DataFrame]: tables = [] with pdfplumber.open(pdf_path) as pdf: for page in pdf.pages: page_tables = page.extract_tables( table_settings={ 'vertical_strategy': 'lines', 'horizontal_strategy': 'lines', 'snap_tolerance': 3 } ) for raw_table in page_tables: # Первая строка как заголовок df = pd.DataFrame(raw_table[1:], columns=raw_table[0]) tables.append(df) return tables Постобработка: очистка данных таблицы
После извлечения часто нужна очистка:
def clean_table(df: pd.DataFrame) -> pd.DataFrame: # Удаление пустых строк и столбцов df = df.dropna(how='all').dropna(axis=1, how='all') # Объединение многострочных заголовков df.columns = [' '.join(str(c).split()) for c in df.columns] # Числовые столбцы for col in df.columns: try: df[col] = pd.to_numeric( df[col].str.replace(',', '.').str.replace(' ', ''), errors='ignore' ) except AttributeError: pass return df | Подход | Применение | Качество |
|---|---|---|
| Table Transformer | Сканы, изображения | Хорошее |
| camelot (lattice) | PDF с линиями | Отличное |
| camelot (stream) | PDF без линий | Среднее |
| pdfplumber | Smешанные PDF | Хорошее |
| AWS Textract | Облако, масштаб | Хорошее |
Процесс работы над проектом
- Анализ документации: изучаем структуру исходных документов, типы таблиц, метаданные.
- Выбор инструмента: подбираем оптимальную комбинацию (Table Transformer, camelot, pdfplumber) под ваш кейс.
- Разработка пайплайна: пишем скрипты детекции, распознавания, постобработки.
- Тестирование: прогоняем на 100+ страницах, сверяем accuracy, дообучаем модель при необходимости.
- Интеграция: настраиваем экспорт в CSV, Excel, базу данных или REST API.
- Документация и обучение: передаём код, описание, обучаем вашу команду.
Что входит в работу (deliverables)
- Аудит исходных данных: анализ типов таблиц, оценка сложности.
- Разработка пайплайна: инференс модели + постобработка.
- Интеграция: API / загрузка в БД / интеграция с 1С или Битрикс24.
- Тестирование и верификация: отчёт по accuracy на вашей выборке.
- Документация: описание архитектуры и инструкция по эксплуатации.
- Обучение: 2-3 часа онлайн-сессии для ваших инженеров.
- Поддержка: 1 месяц после сдачи проекта.
Сроки и стоимость
| Задача | Срок |
|---|---|
| Извлечение из PDF (camelot/pdfplumber) | 1 неделя |
| Сканы + Table Transformer | 2–3 недели |
| Сложные таблицы, post-processing | 3–5 недель |
Стоимость рассчитывается индивидуально — зависит от объёма документов, сложности и необходимости дообучения. Оценим проект бесплатно в течение 1 рабочего дня. Для старта достаточно нескольких образцов документов.
OCR для ячеек таблиц: Tesseract vs EasyOCR vs облачные API
После того как структура таблицы распознана, нужно извлечь текст из каждой ячейки. Выбор движка OCR критично влияет на итоговую точность.
Tesseract — зрелый open-source движок. Хорошо работает с печатным текстом на белом фоне. Требует предобработки: удаление шума, бинаризация Otsu. Поддерживает более 100 языков через языковые пакеты. Скорость: ~0.1 секунды на ячейку на CPU.
EasyOCR — современная нейросетевая альтернатива. Лучше справляется со сложными шрифтами и артефактами сканирования. На GPU в 3–4 раза быстрее Tesseract при сопоставимом качестве. Поддерживает русский язык без дополнительной настройки.
AWS Textract / Google Vision API — облачные решения. Лучшая точность на сложных документах (85–97%), автоматическое распознавание структуры таблиц. Подходят для пакетной обработки без GPU. Стоимость зависит от объёма страниц.
Наш подход: для сканов с хорошим разрешением (300+ DPI) используем EasyOCR, для сложных многоязычных документов — AWS Textract, для on-premise без интернета — Tesseract с препроцессингом.
Готовы взяться за вашу задачу — обсудим детали и сроки. Получите консультацию по выбору оптимального решения.







