← Назад к руководствам
Приватный тестFace RecognitionОценкаMOUПриватность

Как провести приватный тест модели распознавания InsightFace

Пошаговое руководство по оценке open-source и приватных моделей InsightFace на собственных данных: требования MOU, подготовка изображений, Python-клиент и правила приватности.

8 мин чтения

Что вы настроите

InsightFace предоставляет open-source и приватные модели распознавания через хостируемый API извлечения признаков, чтобы клиент мог самостоятельно оценить точность на своих валидационных данных до подписания коммерческого соглашения.

Это руководство описывает весь процесс: получение endpoint, подготовка изображений, минимальный Python-клиент, правила приватности и обработки данных, а также договорные рамки бесплатного окна оценки.

Перед началом

  • Подписанный MOU, фиксирующий намерение о сотрудничестве, период оценки и объём конфиденциальности относительно идентификаторов моделей, которые мы предоставляем. URL endpoint выдаётся только после подписания.
  • Python 3.9 или выше с numpy, requests и OpenCV (opencv-python).
  • Репрезентативный валидационный набор с результатами детекции (bounding boxes из RetinaFace, SCRFD или вашего детектора).
  • Чётко определённый оценочный датасет с эталонными метками и научно обоснованная методология оценки.

1. Подписать MOU и запросить доступ

Любой приватный тест начинается с подписанного MOU между вашей организацией и InsightFace. В нём фиксируются намерение о сотрудничестве, период оценки и объём конфиденциальности относительно идентификаторов моделей, которые мы вам передаём.

URL endpoint, список доступных моделей (open-source или приватные модели, разрешённые в вашем MOU) и лимиты по аккаунту высылаются по e-mail на технического контакта из MOU. Endpoint не публикуется и не должен распространяться вне круга авторизованных контактов.

  • Окно оценки — максимум две недели с момента выдачи endpoint. Для более длительной работы нужен коммерческий контракт.
  • Каждый MOU активирует только перечисленные имена моделей; иные имена отклоняются сервером.
  • Если URL нужно сменить (например, по окончании окна), новая ссылка отправляется тому же списку контактов.

2. Подготовить репрезентативный валидационный набор

Приватные модели — это backbone-ы распознавания, без детектора. Каждый запрос принимает один плотно обрезанный портрет одного человека и возвращает один embedding. Сначала запустите свой детектор, затем посылайте по одному кропу за раз.

При этом сервер всё равно выполняет вторичную детекцию и выравнивание поверх присланного портрета перед извлечением embedding, поэтому небольшие неточности кадрирования допустимы.

  • Одно лицо на изображение. При нескольких людях — сохраняйте каждый кроп в отдельный файл.
  • Документируйте согласие и правовое основание для каждого изображения согласно положению о данных в MOU.

3. Кадрирование и кодирование лица

Перед отправкой добавьте небольшое поле вокруг bounding box. Expansion factor около 0,2 (по 10 % с каждой стороны) сохраняет полезный для распознавания контекст волос, подбородка и ушей. По желанию ограничьте длинную сторону (например, 256 пикселей), чтобы уменьшить размер.

Отправляйте только без потерь, например PNG. JPEG и WebP низкого качества дают артефакты вокруг глаз и рта, которые измеримо снижают качество embedding. Хелпер ниже — стартовая точка; адаптируйте его к формату bounding box вашего детектора.

  • Добавляйте поле (expansion factor); кадр строго по box ухудшает точность.
  • Сохраняйте кропы в PNG. Повторное JPEG-кодирование перед вызовом API — самая частая причина неожиданно низких очков.
Кадрирование одиночного портрета с полем (Python)
import cv2


def crop_face_with_expansion(image, bbox, expansion_factor=0.2, max_side=256):
    """
    Crop a single-person headshot with a small margin around the detected
    face box, and optionally downscale so the longest side is <= max_side.

    image:             input image as a numpy array (BGR or RGB).
    bbox:              face bounding box [x, y, width, height] from your
                       detector of choice (RetinaFace, SCRFD, etc.).
    expansion_factor:  total margin ratio (0.2 means +10% on each side).
    max_side:          if set, the longest side of the result is bounded.
    """
    img_h, img_w = image.shape[:2]
    x, y, w, h = bbox

    # 1. Margin distributed evenly to both sides.
    dw = int(w * expansion_factor / 2)
    dh = int(h * expansion_factor / 2)

    # 2. Expanded box, clamped to image bounds.
    x1 = max(0, x - dw)
    y1 = max(0, y - dh)
    x2 = min(img_w, x + w + dw)
    y2 = min(img_h, y + h + dh)

    face_img = image[y1:y2, x1:x2]

    # 3. Optional bounded downscale with a high-quality filter.
    if max_side is not None:
        curr_h, curr_w = face_img.shape[:2]
        longest = max(curr_h, curr_w)
        if longest > max_side:
            scale = max_side / longest
            new_w = int(curr_w * scale)
            new_h = int(curr_h * scale)
            face_img = cv2.resize(
                face_img, (new_w, new_h), interpolation=cv2.INTER_AREA,
            )

    return face_img


# Save the crop with a lossless format (PNG) before sending it to the API.
# Lossy formats (JPEG, WebP at low quality) introduce compression artifacts
# that can measurably reduce face recognition accuracy.
# cv2.imwrite("probe.png", crop)

4. Вызов API извлечения признаков

API ожидает multipart/form-data POST: один файл в поле image и строку model_name. Ответ — JSON с model_name и feature (L2-нормализованный embedding). Сохраняйте каждый embedding как .npy, чтобы офлайн считать cosine similarity.

Пример клиента ниже точно воспроизводит продакшн-протокол. Запускайте напрямую или импортируйте extract_feature в свой pipeline. Передавайте URL, полученный по e-mail, через --server-url; не зашивайте его в скрипты, которые попадают в общий репозиторий.

  • model_name должен быть из значений MOU; иные имена сервер отклоняет.
  • Пустой feature означает, что в кропе не найдено лицо — проверьте box и поле.
  • Сравнивайте embedding-и через cosine similarity на L2-нормализованных векторах; на клиенте не нормализуйте повторно.
Минимальный Python-клиент к приватному endpoint
"""Example client for the private InsightFace feature extraction service.

Uploads a single-person face image to the test endpoint, reads the returned
embedding, and saves it locally with np.save for offline evaluation.
"""

import argparse
import os.path as osp

import numpy as np
import requests


def extract_feature(image_path, output_path, url, model_name, timeout=120.0):
    filename = osp.basename(image_path)
    data = {"model_name": model_name}

    with open(image_path, "rb") as infile:
        files = {
            "image": (filename, infile, "application/octet-stream"),
        }
        try:
            resp = requests.post(
                url=url, files=files, data=data, timeout=timeout,
            )
            resp.raise_for_status()
        except requests.RequestException as ex:
            raise SystemExit(
                "request failed: %s: %s" % (type(ex).__name__, str(ex))
            )

    payload = resp.json()
    feature = payload.get("feature")
    if not isinstance(feature, list):
        raise SystemExit("server response feature must be a list")
    if len(feature) == 0:
        raise SystemExit(
            "server returned no features; verify the image contains a "
            "detectable face"
        )

    feat = np.asarray(feature, dtype=np.float32)
    np.save(output_path, feat)
    print("saved feature:", output_path, feat.shape, payload.get("model_name"))
    return feat


def main():
    parser = argparse.ArgumentParser(
        description=(
            "Upload a face image to the private InsightFace test server and "
            "save the embedding with np.save."
        ),
    )
    # The --server-url value is delivered to evaluators by email.
    parser.add_argument(
        "--server-url", required=True,
        help="Feature extraction API URL (sent privately by InsightFace)",
    )
    # The set of choices below is illustrative; the models actually unlocked
    # for your account are listed in your MOU and may evolve over time.
    parser.add_argument(
        "--model-name", required=True,
        choices=["buffalo", "dingo", "eagle"],
        help="Recognition model to evaluate (must match an entry in your MOU)",
    )
    parser.add_argument("--image", required=True, help="Input face image path (PNG recommended)")
    parser.add_argument("--output", required=True, help="Output .npy file path")
    parser.add_argument("--timeout", type=float, default=120.0, help="HTTP timeout in seconds")
    args = parser.parse_args()

    extract_feature(
        args.image, args.output, args.server_url, args.model_name,
        timeout=args.timeout,
    )


if __name__ == "__main__":
    main()

5. Приватность и обработка данных

Загруженные изображения используются только для расчёта и возврата embedding в рамках запроса. После ответа исходные изображения не сохраняются, а трафик оценки не применяется ни для обучения, ни для дообучения.

  • Не передавайте URL, имена моделей или результаты вне списка контактов MOU.
  • О подозрении на утечку URL или учётных данных уведомляйте контакт InsightFace в течение 24 часов.

6. Объём оценки и следующие шаги

Бесплатное окно — до двух недель с момента выдачи URL. В пределах окна можно делать сколько угодно сравнений в рамках rate limit; рекомендуем зафиксировать тестовый набор, препроцессинг и метрики до запроса endpoint, чтобы окно ушло на цифры, а не на подготовку.

По окончании теста, пожалуйста, как можно скорее оцените результаты и сообщите вывод о коммерческом сотрудничестве.

Нужна помощь с production-развертыванием?

Свяжитесь с InsightFace по вопросам лицензирования моделей, оптимизации runtime и поддержки целевого hardware.

Связаться