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







