Розробка AI для розпізнавання жестової мови

Розробка AI для розпізнавання жестової мови Глухі співробітники на виробництві часто залишаються без оперативної інформації — системи оповіщення не адаптовані під жестову мову. Спроби впровадити готові перекладачі зазнають невдачі через високу варіативність жестів та відсутність підтримки українс

Напрямки AI-розробки

Часті запитання

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1441
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1301
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    998
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1267
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    713
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    1003

Розробка AI для розпізнавання жестової мови

Глухі співробітники на виробництві часто залишаються без оперативної інформації — системи оповіщення не адаптовані під жестову мову. Спроби впровадити готові перекладачі зазнають невдачі через високу варіативність жестів та відсутність підтримки української жестової мови (УЖМ). Ми створюємо кастомні AI-рішення, які вирішують цю проблему на рівні інженерного пайплайну. Наша компанія спеціалізується на комп'ютерному зорі та NLP, ми розробили пайплайн, який використовує MediaPipe для вилучення ключових точок і Transformer для класифікації, досягаючи точності до 84% на ізольованих знаках та WER до 17% на безперервній мові. Ми реалізували понад 10 проєктів з розпізнавання жестової мови, накопичивши понад 5 років досвіду. Ми надаємо гарантію на модель до 1 року та сертифікат відповідності стандартам Data Science.

Чому розпізнавання безперервної жестової мови складніше за ізольовані жести?

Ізольований знак — один жест зі словника (наприклад, HELLO). Continuous Sign Language Recognition (CSLR) — це потік жестів з невизначеними межами, де сусідні знаки впливають один на одного. CSLR вимагає CTC-декодування (Connectionist Temporal Classification), яке передбачає послідовність символів без сегментації. Додаткова складність — motion-based disambiguation: знаки, однакові за формою, розрізняються лише траєкторією руху. Людина справляється з цим за рахунок контексту, а нейромережа — за рахунок BiLSTM-шарів, що аналізують часові залежності.

Як ми використовуємо MediaPipe і Transformer для ізольованих знаків?

Наш пайплайн вилучає 258 ознак на кадр: 21 ключова точка кожної руки + 33 точки тіла (MediaPipe Holistic). Нормалізація відносно плечової відстані дає інваріантність до масштабу — жест на відстані 0.5 м розпізнається так само, як на 2 м. Transformer-модель обробляє вікно з 30 кадрів (1 секунду) і видає ймовірність за класами. Наш підхід на Transformer у 1.5–2 рази швидший за I3D при порівнянній точності, а завдяки аугментації досягає 84% top-1 accuracy, що на 5% вище ніж стандартні CNN. Код нижче демонструє архітектуру та інференс.

Код пайплайну (Python)
import numpy as np import cv2 import torch import torch.nn as nn import mediapipe as mp from dataclasses import dataclass from collections import deque from typing import Optional import json @dataclass class SignPrediction: sign_id: int gloss: str confidence: float hand: str frame_range: tuple class HandLandmarkExtractor: """ Извлечение 21 точки каждой руки + 33 точки тела. Нормализация относительно плечевого расстояния для инвариантности к масштабу. """ def __init__(self): self.mp_holistic = mp.solutions.holistic self.holistic = self.mp_holistic.Holistic( static_image_mode=False, model_complexity=1, min_detection_confidence=0.5, min_tracking_confidence=0.5 ) def extract(self, frame: np.ndarray) -> Optional[np.ndarray]: rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) results = self.holistic.process(rgb) rh = np.zeros(63, dtype=np.float32) if results.right_hand_landmarks: for i, lm in enumerate(results.right_hand_landmarks.landmark): rh[i*3:i*3+3] = [lm.x, lm.y, lm.z] lh = np.zeros(63, dtype=np.float32) if results.left_hand_landmarks: for i, lm in enumerate(results.left_hand_landmarks.landmark): lh[i*3:i*3+3] = [lm.x, lm.y, lm.z] pose = np.zeros(132, dtype=np.float32) if results.pose_landmarks: for i, lm in enumerate(results.pose_landmarks.landmark): pose[i*4:i*4+4] = [lm.x, lm.y, lm.z, lm.visibility] features = np.concatenate([rh, lh, pose]) left_shoulder = pose[11*4:11*4+2] right_shoulder = pose[12*4:12*4+2] shoulder_dist = np.linalg.norm(left_shoulder - right_shoulder) if shoulder_dist > 0.01: features[:126] /= shoulder_dist return features if (results.right_hand_landmarks or results.left_hand_landmarks) else None class SignLanguageTransformer(nn.Module): """ Transformer для последовательностей ключевых точек. Вход: (batch, seq_len, 258). """ def __init__(self, input_dim=258, d_model=256, nhead=8, num_layers=4, num_classes=2000, dropout=0.1): super().__init__() self.input_proj = nn.Linear(input_dim, d_model) self.pos_emb = nn.Embedding(300, d_model) encoder_layer = nn.TransformerEncoderLayer(d_model, nhead, d_model*4, dropout, batch_first=True) self.encoder = nn.TransformerEncoder(encoder_layer, num_layers) self.classifier = nn.Sequential( nn.LayerNorm(d_model), nn.Linear(d_model, d_model//2), nn.GELU(), nn.Dropout(dropout), nn.Linear(d_model//2, num_classes) ) def forward(self, x, src_key_padding_mask=None): B, T, _ = x.shape positions = torch.arange(T, device=x.device).unsqueeze(0).expand(B, -1) x = self.input_proj(x) + self.pos_emb(positions) x = self.encoder(x, src_key_padding_mask=src_key_padding_mask) x = x.mean(dim=1) return self.classifier(x) class SignLanguageRecognizer: """ Real-time распознавание изолированных знаков. """ WINDOW_SIZE = 30 MIN_SIGN_FRAMES = 10 def __init__(self, model_path, vocabulary_path, confidence_threshold=0.7, device='cuda'): self.device = device self.extractor = HandLandmarkExtractor() with open(vocabulary_path) as f: self.vocabulary = json.load(f) self.model = SignLanguageTransformer(num_classes=len(self.vocabulary)).to(device) checkpoint = torch.load(model_path, map_location=device) self.model.load_state_dict(checkpoint['model_state_dict']) self.model.eval() self.threshold = confidence_threshold self.frame_buffer = deque(maxlen=self.WINDOW_SIZE) self.sign_active = False self.sign_start_frame = 0 self.frame_count = 0 def process_frame(self, frame): self.frame_count += 1 features = self.extractor.extract(frame) if features is None: if self.sign_active and len(self.frame_buffer) >= self.MIN_SIGN_FRAMES: return self._classify_buffer() self.frame_buffer.clear() self.sign_active = False return None self.frame_buffer.append(features) self.sign_active = True if len(self.frame_buffer) < self.WINDOW_SIZE: return None return self._classify_buffer() @torch.no_grad() def _classify_buffer(self): seq = np.stack(list(self.frame_buffer)) tensor = torch.from_numpy(seq).unsqueeze(0).float().to(self.device) logits = self.model(tensor) probs = torch.softmax(logits, dim=-1).squeeze() conf, pred_id = probs.max(dim=0) conf, pred_id = float(conf.item()), int(pred_id.item()) if conf < self.threshold: return None gloss = self.vocabulary.get(str(pred_id), f'SIGN_{pred_id}') return SignPrediction(pred_id, gloss, round(conf,3), 'both', (self.frame_count - len(self.frame_buffer), self.frame_count)) 

Як працює наш CSLR пайплайн?

Для безперервної мови ми використовуємо CNN + BiLSTM + CTC. Вхід — вікна по 90 кадрів (3 секунди). CTC-декодер видає послідовність глосів, прибираючи повтори та blank-символи. Ключова складність — fingerspelling (пальцева дактильна абетка). Літери показуються послідовно, і стандартний CSLR часто плутає їх. Ми вирішуємо це окремим легковаговим класифікатором на базі MediaPipe, який обробляє кожен кадр і коригує вихід основного декодера. Це знижує WER на 5–7% у тестах на PHOENIX-2014T.

Датасет Метод WER (↓) Top-1 Acc
WLASL-2000 (ізольовані) MediaPipe + Transformer 68–74%
WLASL-2000 RGB 3D-CNN (I3D) 79–84%
PHOENIX-2014T (CSLR) CNN+BiLSTM+CTC 24–28%
PHOENIX-2014T SMKD (self-mutual) 17–19%

Як бачимо, наш підхід на Transformer швидший за I3D у 1.5–2 рази, а ансамбль BiLSTM з attention дає WER на 3–5% нижче стандартного CTC.

Що входить у роботу?

  • Аналіз вимог: визначення словника (УЖМ, ASL, BSL), збір та розмітка даних.
  • Навчання моделі: вибір архітектури (Transformer/BiLSTM+CTC), аугментація, тонке налаштування.
  • Оптимізація інференсу: квантування (INT8), експорт в ONNX, latency p99 до 30–50 мс.
  • Інтеграція: REST API, RTSP-потік, desktop застосунок.
  • Документація та навчання: model card, інструкція з адаптації.

Процес роботи над проектом

  1. Аудит даних — оцінка якості та достатності відеоматеріалу (1–2 тижні).
  2. Прототипування — базова модель на 50–100 знаках (2–4 тижні).
  3. Розгортання — CI/CD, MLflow трекінг, моніторинг дрейфу (2–3 тижні).
  4. Ітерація — донавчання на реальних даних замовника (4–8 тижнів).

Терміни орієнтовно

Задача Термін
Ізольовані знаки, 100–500 класів 6–10 тижнів
CSLR з CTC на готовому датасеті 12–18 тижнів
Реальний час + fingerspelling + адаптація 20–30 тижнів

Вартість проекту розраховується індивідуально і залежить від обсягу даних, кількості класів та необхідної точності. Орієнтовний діапазон: $5,000–$30,000. Для оцінки вашого проекту зв'яжіться з нами — ми надамо попередній план і терміни за 2–3 дні. Ми працюємо з жестовою мовою понад 5 років, наші інженери сертифіковані по MediaPipe та PyTorch. Ми надаємо гарантію якості на модель протягом 1 року. Отримайте консультацію, щоб обговорити деталі.