Время прочтения: 4 мин.

Применение искусственного интеллекта (далее – ИИ) проникает во все сферы деятельности человека, а также связанные с ними услуги и устройства. Назрела необходимость применения алгоритмов ИИ при обслуживании клиентов на устройствах самообслуживания (далее – УС).

Алгоритмы ИИ могут применяться на УС прежде всего для защиты клиентов от финансовых мошенничеств, в том числе с использованием методов социальной инженерии.

Так, известные схемы мошенничеств предполагают звонок по телефону потенциальной жертве, убеждение клиента пройти к УС, и под диктовку мошенника по телефону совершить определенные действия на банкомате (перевести денежные средства на счет мошенника, снять наличные, переподключить услугу мобильный банк на номер телефона мошенника, и т.д.).

Какими алгоритмами ИИ можно воспользоваться для предотвращения подобных мошеннических схем на УС? Это могут быть алгоритмы компьютерного зрения, позволяющие сканировать с камер УС внешность клиента и анализировать его поведение. Если клиент во время обслуживания на УС общается с третьими лицами по телефону, то возможным решением может быть блокировка его транзакций на УС с выводом сообщения на экран монитора о необходимости перезвонить в Контактный центр банка-эмитента.

Впервые банкомат с искусственным интеллектом, который реализует алгоритм автоматического прерывания транзакции, если клиент в момент совершения операции разговаривает по телефону, был разработан японской компанией Hitachi-Omron Terminal Solutions в 2018 году. Информация о банкомате по ссылке: https://tass.ru/obschestvo/5756911.

В нашей статье мы приводим один из возможных кодов для первоначальной идентификации клиентов, с поднятой к уху рукой в момент проведения операций на УС: Для разработки проекта была использована библиотека PoseNet, которая находится в открытом доступе по ссылке: https://github.com/rwightman/posenet-pytorch.

# подключим библиотеки
import torch
import cv2
import numpy as np
import posenet as pn
from typing import Tuple, Optional

def main():
    # загрузим модель
    estimator = pn.load_model(101)
    stride = estimator.output_stride
    # подготовим вебкамеру
    webcam = cv2.VideoCapture(0)
    webcam.set(3, 320)
    webcam.set(4, 240)
    while True:
        # получим кадр
        image, to_show, scale = pn.read_cap(
            webcam, scale_factor=0.7125, output_stride=stride)
        with torch.no_grad():
            image = torch.Tensor(image)
            # запустим распознование скелета
            heatmap, offset, displacement_forward, displacement_backward = estimator(image)
            scores_p, scores_k, coords = pn.decode_multiple_poses(
                heatmap.squeeze(0), offset.squeeze(0),
                displacement_forward.squeeze(0), displacement_backward.squeeze(0),
                output_stride=stride, max_pose_detections=1, min_pose_score=0.15)
        coords *= scale
        # вычислим и отобразим положение головы человека
        head_pos = get_head_position(scores_k[0], coords[0])
        overlay = cv2.circle(to_show,
                             (int(head_pos[0]), int(head_pos[1])),
                             5, color=(255, 0, 0), thickness=-1)
        # рассчитаем минимальное расстояние от головы до руки
        min_distance = 1000
        for left in [True, False]:
            hand_pos = get_hand_pos(scores_k[0], coords[0], left)
            if hand_pos is not None:
                overlay = cv2.circle(to_show,
                                     (int(hand_pos[0]), int(hand_pos[1])),
                                     5, color=(0, 255, 0), thickness=-1)
                dist = distance(head_pos, hand_pos)
                if dist < min_distance:
                    min_distance = dist
        # если расстояние не велико, значит человек разговаривает по телефону
        if min_distance < 120:
            overlay = cv2.putText(overlay, "PHONE DETECTED", (20, 30),
                                  cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 3)
        cv2.imshow('posenet', overlay)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

def get_head_position(scores: np.ndarray, coords: np.ndarray) -> Tuple[float, float]:
    """
    Функция для получения положения головы
    """
    px, py, count = 0.0, 0.0, 0
    for i in range(5):
        if scores[i] > 0.5:
            px += coords[i][1]
            py += coords[i][0]
            count += 1
    return px / count, py / count

def get_hand_pos(scores: np.ndarray, coords: np.ndarray, left: bool) -> Optional[Tuple[float, float]]:
    """
    Функция для получения положения руки
    :param left: Левая рука или правая
    """
    index = 9 if left else 10
    if scores[index] < 0.5:
        return None
    return coords[index][1], coords[index][0]

def distance(pos1: Tuple[float, float], pos2: Tuple[float, float]) -> float:
    """
    Функция для вычисления расстояния между двумя координатами
    """
    (x1, y1), (x2, y2) = pos1, pos2
    dx, dy = x1 - x2, y1 - y2
    return np.sqrt(dx * dx + dy * dy)

if __name__ == "__main__":
    main()

Пример работы приведённого выше кода:

В статье приведен код, который пока определяет клиентов с поднятой к уху рукой, но может использоваться для дальнейшей обучающей модели по распознаванию самого телефона в ладони клиента.