Реализация распознавания текста с визиток и бейджей
Распознавание визиток — частный случай Document OCR с дополнительным этапом: структурирование извлечённых данных по полям (имя, должность, компания, телефон, email, сайт). Бейджи на мероприятиях — похожая задача, но с требованием реального времени (поток с камеры при регистрации).
Пайплайн распознавания визитки
import re
from paddleocr import PaddleOCR
from transformers import pipeline
class BusinessCardRecognizer:
def __init__(self):
self.ocr = PaddleOCR(use_angle_cls=True, lang='ru', use_gpu=True)
# NER для структурирования полей
self.ner = pipeline('ner',
model='DeepPavlov/rubert-base-cased-conversational',
aggregation_strategy='simple')
def recognize(self, image_path: str) -> dict:
# 1. OCR
result = self.ocr.ocr(image_path, cls=True)
text_lines = [line[1][0] for line in result[0]]
full_text = '\n'.join(text_lines)
# 2. Структурирование через правила + NER
structured = self._extract_fields(full_text, text_lines)
return structured
def _extract_fields(self, full_text: str,
lines: list[str]) -> dict:
result = {
'name': None,
'company': None,
'title': None,
'phones': [],
'emails': [],
'websites': [],
'addresses': []
}
# Регулярные выражения для структурированных полей
phone_pattern = r'[\+7|8][\s\-]?\(?\d{3}\)?[\s\-]?\d{3}[\s\-]?\d{2}[\s\-]?\d{2}'
email_pattern = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'
url_pattern = r'(?:https?://)?(?:www\.)?[\w-]+\.[\w.-]+(?:/[\w./?=&-]*)?'
result['phones'] = re.findall(phone_pattern, full_text)
result['emails'] = re.findall(email_pattern, full_text)
result['websites'] = [u for u in re.findall(url_pattern, full_text)
if '.' in u and '@' not in u]
# NER для имени и должности
ner_result = self.ner(full_text)
for entity in ner_result:
if entity['entity_group'] == 'PER':
result['name'] = entity['word']
elif entity['entity_group'] == 'ORG':
result['company'] = entity['word']
# Эвристика: строка между именем и телефонами — должность
result['title'] = self._infer_title(lines, result)
return result
Бейджи на мероприятиях: real-time режим
Для систем регистрации на конференциях: камера сканирует бейдж или визитку, система мгновенно извлекает данные и отмечает посещаемость.
import cv2
from threading import Thread
from queue import Queue
class BadgeScanner:
def __init__(self, recognizer: BusinessCardRecognizer,
camera_id: int = 0):
self.recognizer = recognizer
self.cap = cv2.VideoCapture(camera_id)
self.frame_queue = Queue(maxsize=2)
self.result_queue = Queue()
self.last_scan_time = 0
self.scan_cooldown = 2.0 # секунды между сканированиями
def scan_frame(self, frame: np.ndarray) -> dict | None:
import time
now = time.time()
if now - self.last_scan_time < self.scan_cooldown:
return None
# Быстрая проверка: есть ли прямоугольный объект (карточка)
if not self._detect_card_shape(frame):
return None
result = self.recognizer.recognize_from_array(frame)
if result.get('name') or result.get('emails'):
self.last_scan_time = now
return result
return None
Экспорт в контактную книгу
После распознавания — экспорт в vCard формат:
import vobject
def to_vcard(card_data: dict) -> str:
vcard = vobject.vCard()
vcard.add('n').value = vobject.vcard.Name(family='', given=card_data.get('name', ''))
vcard.add('fn').value = card_data.get('name', '')
if card_data.get('company'):
vcard.add('org').value = [card_data['company']]
if card_data.get('title'):
vcard.add('title').value = card_data['title']
for phone in card_data.get('phones', []):
tel = vcard.add('tel')
tel.value = phone
tel.type_param = 'WORK'
for email in card_data.get('emails', []):
vcard.add('email').value = email
return vcard.serialize()
Точность на реальных визитках
| Поле | Accuracy (хорошее фото) | Accuracy (телефон) |
|---|---|---|
| Телефон | 96–98% | 88–93% |
| 97–99% | 90–95% | |
| Имя | 85–92% | 75–85% |
| Должность | 75–85% | 65–78% |
| Компания | 82–90% | 72–83% |
| Задача | Срок |
|---|---|
| Мобильное приложение сканирования визиток | 2–3 недели |
| Система регистрации по бейджам | 3–5 недель |
| Integration с CRM, экспорт контактов | 4–6 недель |







