Перейти к основному содержимому
Версия: 3.14.0

Детекция тел

Human Body Detector

Компонент Human Body Detector используется для обнаружения человеческих тел на изображении.
Результат детекции - координаты прямоугольника, ограничивающего обнаруженное тело человека.

На этой странице вы узнаете как запустить демонстрационный сэмпл body_detector для детекции человеческих тел на изображении и как интегрировать компонент Human Body Detector в проект на C++.

Human Body Detection Sample

Сэмпл body_detector демонстрирует детекцию человеческих тел на изображении.

примечание

Для запуска сэмпла body_detector необходим дистрибутив Face SDK версии 3.14 (или выше) с установленными компонентами для платформ Windows или Linux (в соответствии с используемой вами ОС).

  • Если Face SDK не установлен, следуйте инструкциям Начало работы. Выберите нужную платформу на этапе "Выбор компонентов".

  • Если Face SDK установлен без компонентов платформ Windows или Linux, используйте утилиту maintenancetool и установите нужную платформу выбрав ее на этапе "Выбор компонентов".

Для запуска сэмпла body_detector используются следующие аргументы:

  • Путь до изображения
  • Путь до файла body.enc
примечание

Путь по умолчанию до файла модели Human Body Detector: share/bodydetectors/body.enc в корневой директории Face SDK.

Примеры консольных команд для запуска сэмпла body_detector из директории bin:

  • Linux: ./body_detector group/01.jpg ../share/bodydetectors/body.enc
  • Windows: .\body_detector.exe group\01.jpg ..\share\bodydetectors\body.enc

Результат детекции человеческих тел на изображении отобразиться в новом окне.

Результат детекции человеческих тел

В случае возникновения неполадок, соответствующие сообщения будут выведены в консоль.

Устранение неполадок
  • Ошибка Assertion failed (ERROR: not found libonnxruntime.so), error code: 0x032ad038:

    • Проверьте наличие файла библиотеки lib/libonnxruntime.so в корневой директории Face SDK
    • Добавть путь к библиотеке lib/libonnxruntime.so в переменную окружения LD_LIBRARY_PATH
  • Ошибка Assertion failed (ERROR: not found onnxruntime.dll), error code: 0x032ad038:

    • Проверьте наличие файла библиотеки bin/onnxruntime.dll в корневой директории Face SDK

примечание

Исходный код сэмпла body_detector доступен по ссылке. Так же исходный код и инструкция по сборке (файл README.txt) доступны в директории examples/cpp/body_detector/ дистрибутива Face SDK.

Детекция тел (C++)

В этом разделе вы узнаете как интегрировать компонент Human Body Detector в проект на С++.

Context

Context - это гетерогенный контейнер, состоящий из набора иерархически организованных данных, представленных как пары ключ-значение. Ближайший аналог Context - объект JSON. Каждый объект Context может содержать: скалярный объект (integer, real, boolean, string), указатель на область памяти, массив объектов Context, ассоциативный контейнер пар <string, Context> с неограниченной вложенностью.

Пример использования объекта Context
Context array_elem0;
array_elem0["name"] = "Julius Zeleny";
array_elem0["phone"] = 11111111111l;
array_elem0["social_score"] = 0.999;
array_elem0["verified"] = true;

std::cout << array_elem0["name"].getString() << std::endl; // "Julius Zeleny"
std::cout << array_elem0["phone"].getLong() << std::endl; // 11111111111l
std::cout << array_elem0["social_score"].getDouble() << std::endl;// 0.999
std::cout << array_elem0["verified"].getBool() << std::endl; // 1

Context array_elem1;
array_elem1["name"] = "Owen Cohron";
array_elem1["phone"] = 22222222222;
array_elem1["social_score"] = 0.999;
array_elem1["verified"] = false;

Context array_elem2;
array_elem2["name"] = std::string("Sarah Connor");
array_elem2["phone"] = 333333333l;
array_elem2["social_score"] = 0.5;
array_elem2["verified"] = true;

std::cout << array_elem2["name"].getString() << std::endl; // "Sarah Connor"

Context array;
array.push_back(array_elem0);
array.push_back(array_elem1);
array.push_back(array_elem2);

std::cout << array[0]["phone"].getLong() << std::endl; // 11111111111l
std::cout << array[1]["phone"].getLong() << std::endl; // 22222222222
std::cout << array[2]["phone"].getLong() << std::endl; // 333333333l

size_t array_sz = array.size();
std::cout << array_sz << std::endl; // 3

for(size_t i = 0; i < array_sz; ++i) {
array[i]["phone"];
}

Context full;
full["friends"] = array;

std::cout << full["friends"][1]["social_score"].getDouble() << std::endl; // 0.999

// copy cv::Mat to Context
int width{640}, height{480}, channels{3};
cv::Mat img = cv::imread("photo.jpg");
full["img"]["dtype"] = "uint8";
full["img"]["shape"].push_back(width);
full["img"]["shape"].push_back(height);
full["img"]["shape"].push_back(channels);
full["img"]["ptr"] = img.data;
full["img"]["data"].setDataPtr(img.data, img.total()*img.elemSize());

// create cv::Mat from Context
unsigned char* img_buf = full["img"]["data"].getDataPtr();
cv::Mat imgCopy = cv::Mat(height, width, CV_8UC3, img_buf);

1. Создание Human Body Detector

1.1. Создайте FacerecService.

1.2. Создайте контейнер Context:

auto modelCtx = service->createContext();

1.3. Для создания блока обработчика (Processing block), в созданном контейнере Context определите следующие поля:

// обязательно
modelCtx["unit_type"] = "HUMAN_BODY_DETECTOR";

// обязательно
// путь по умолчанию до файла модели Human Body Detector: _share/bodydetectors/body.enc_ в корневой директории Face SDK.
modelCtx["model_path"] = "../share/bodydetectors/body.enc";

// значение по умолчанию 0.5
modelCtx["confidence_threshold"] = 0.2;

// значение по умолчанию 0.5
modelCtx["iou_threshold"] = 0.4;

// библиотека onnxruntime по умолчанию расположена в директории дистрибутива Face SDK: "lib" для платформы Linux или "bin" для платформы Windows
// вы можете задать ваш собственный путь до библиотеки onnxruntime
// если путь до библиотеки не указан, то будет использоваться стандартный порядок поиска, используемый в данной ОС
modelCtx["ONNXRuntime"]["library_path"] = "../lib"

1.4. Используя контейнер Context, создайте Human Body Detector Processing block:

pbio::ProcessingBlock bodyDetector = service->createProcessingBlock(modelCtx);

2. Детекция тел

Детектор тел принимает контейнер Context, содержащий изображение в бинарном формате:

/*
{
"image" : { "format": "NDARRAY",
"blob": <blob_value>,
"dtype": "uint8_t",
"shape": [] }
}
*/

Ключ "blob" содержит указатель на данные. Указатель устанавливается функцией void Context::setDataPtr(void* ptr, int copy_sz), где copy_sz - это размер памяти в байтах, которая будет скопирована и далее автоматически освобождена. Копирование не выполняется если в качестве аргумента copy_sz передан 0.

Ключ "dtype" может содержать одно из следующих значений: "uint8_t", "int8_t", "uint16_t", "int16_t", "int32_t", "float", "double". Каждому значению соответствует определенный тип OpenCV: CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F.

2.1. Создайте контейнер Context для изображения, используя метод createContext():

auto imgCtx = service->createContext();

2.2. Загрузите RGB-изображение как объект cv::Mat:

cv::Mat image = cv::imread(input_image_path, cv::IMREAD_COLOR);
cv::Mat input_image;
cv::cvtColor(image, input_image, cv::COLOR_BGR2RGB);

2.3. Конвертируйте изображение из cv::Mat в бинарный формат и добавьте его в контейнер Context:

void cvMatToBSM(pbio::Context& bsmCtx, const cv::Mat img, bool copy)
{
bsmCtx["format"] = "NDARRAY";
size_t copy_sz = copy ? img.total()*img.elemSize() : 0;
bsmCtx["blob"].setDataPtr(img.data, copy_sz);
bsmCtx["dtype"] = CvTypeToStr.at(img.depth());
for(int i = 0; i < img.dims; ++i)
bsmCtx["shape"].push_back(img.size[i]);
bsmCtx["shape"].push_back(img.channels());
}

cvMatToBSM(imgCtx, input_image);

2.4. Создайте контейнер Context:

auto ioData = service->createContext();
ioData["image"] = imgCtx;

2.5. Вызовите метод bodyDetector() и передайте контейнер ioData:

bodyDetector(ioData);

Метод bodyDetector() добавит результат обработки сэмплов (изображений) в контейнер ioData.

Формат выходных данных представляет собой список объектов, доступный по ключу "objects".

Каждый объект списка имеет:

  • Ключ "class" со значением "body"
  • Ключ "bbox" (bounding box) содержит массив из четырех чисел типа long {x1, y1, x2, y2} - координаты в пикселях на исходном изображении
  • Ключ "score" содержит число типа float в диапазоне [0,1]
/*
{
"objects": [{ "id": <id_value>,
"class": "body",
"score": <score_value>,
"bbox": [] }]
}
*/

Объекты Context позволяют итерироваться по своим значениям, поэтому вы можете использовать следующий код для получения результата детекции тел и отрисовки результата на исходном изображении:

for(const auto& obj : ioData["objects"])
{
if(obj["class"].getString().compare("body"))
continue;
const auto& rectCtx = obj.at("bbox");
cv::Rect rect(cv::Point{rectCtx[0].getLong(), rectCtx[1].getLong()},
cv::Point{rectCtx[2].getLong(), rectCtx[3].getLong()});
cv::rectangle(img, rect, {0, 255, 0}, 1);
}

cv::imshow("img", img);
cv::waitKey();

3. Ускорение на GPU

Human Body Detector может быть использован с ускорением на GPU (CUDA). Для этого необходимо определить ключ "use_cuda" со значением true для Context-контейнера блока обработчика (см. Создание Human Body Detector).