Типичная ситуация: клиент присылает 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 с препроцессингом.
Готовы взяться за вашу задачу — обсудим детали и сроки. Получите консультацию по выбору оптимального решения.







