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







