Business Card and Badge Text Recognition

We design and deploy artificial intelligence systems: from prototype to production-ready solutions. Our team combines expertise in machine learning, data engineering and MLOps to make AI work not in the lab, but in real business.
Showing 1 of 1 servicesAll 1566 services
Business Card and Badge Text Recognition
Simple
~2-3 business days
FAQ
AI Development Areas
AI Solution Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1212
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    852
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_logo-advance_0.png
    B2B Advance company logo design
    561
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    822

Реализация распознавания текста с визиток и бейджей

Распознавание визиток — частный случай 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%
Email 97–99% 90–95%
Имя 85–92% 75–85%
Должность 75–85% 65–78%
Компания 82–90% 72–83%
Задача Срок
Мобильное приложение сканирования визиток 2–3 недели
Система регистрации по бейджам 3–5 недель
Integration с CRM, экспорт контактов 4–6 недель