Детекция тел
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]).
- Системные требования:
- Nvidia GPU Driver >= 410.48
- CUDA Toolkit 10.1
- cuDNN 7
- (Для Windows) Microsoft Visual C++ Redistributable for Visual Studio 2019
- Требования к оборудованию:
- графический процессор (GPU) с поддержкой CUDA (NVIDIA GTX 1050 Ti и выше)