В этом примере показано, как оценить позу тела одного или нескольких людей с помощью алгоритма OpenPose и предварительно обученной сети.
Целью оценки позы тела является определение местоположения людей на изображении и ориентации их частей тела. Когда в сцене присутствует несколько человек, оценка позы может быть более сложной из-за окклюзии, контакта с телом и близости аналогичных частей тела.
Существует две стратегии оценки позы тела. Стратегия сверху вниз сначала идентифицирует отдельных людей, используя обнаружение объектов, а затем оценивает позу каждого человека. Стратегия снизу вверх сначала идентифицирует части тела на изображении, такие как носы и левые локти, а затем собирает людей на основе вероятных пар частей тела. Стратегия снизу вверх более надежна для окклюзии и контакта с телом, но стратегия более трудна для реализации. OpenPose - алгоритм оценки позы человека с участием нескольких человек, использующий стратегию снизу вверх [1].
Для идентификации частей тела в изображении OpenPose использует предварительно обученную нейронную сеть, которая предсказывает тепловые карты и поля сродства частей (PAF) для частей тела во входном изображении [2]. Каждая тепловая карта показывает вероятность того, что конкретный тип корпусной части расположен в каждом пикселе изображения. PAF - это векторные поля, указывающие, связаны ли две части тела. Для каждого определенного типа спаривания частей тела, такого как шейка к левому плечу, существуют два PAF, которые показывают x - и y-компонент векторного поля между экземплярами частей тела.
Чтобы собрать детали тела в отдельных людей, алгоритм OpenPose выполняет ряд операций постобработки. Первая операция идентифицирует и локализует детали корпуса с помощью тепловых карт, возвращаемых сетью. Последующие операции определяют фактические связи между частями тела, что приводит к отдельным позициям. Дополнительные сведения об алгоритме см. в разделе Идентификация позиций из тепловых карт и PAFs.
Импорт предварительно подготовленной сети из файла ONNX.
dataDir = fullfile(tempdir,'OpenPose'); trainedOpenPoseNet_url = 'https://ssd.mathworks.com/supportfiles/vision/data/human-pose-estimation.zip'; downloadTrainedOpenPoseNet(trainedOpenPoseNet_url,dataDir) unzip(fullfile(dataDir,'human-pose-estimation.zip'),dataDir);
Загрузите и установите пакет поддержки Deep Learning Toolbox™ Converter для формата модели ONNX.
Если Deep Learning Toolbox Converter™ for ONNX Model Format не установлен, то функция предоставляет ссылку на необходимый пакет поддержки в обозревателе надстроек. Чтобы установить пакет поддержки, щелкните ссылку и нажмите кнопку Установить. Если пакет поддержки установлен, то importONNXLayers функция возвращает LayerGraph объект.
modelfile = fullfile(dataDir,'human-pose-estimation.onnx'); layers = importONNXLayers(modelfile,"ImportWeights",true);
Удалите неиспользуемые выходные слои.
layers = removeLayers(layers,["Output_node_95" "Output_node_98" "Output_node_147" "Output_node_150"]); net = dlnetwork(layers);
Чтение и отображение тестового изображения.
im = imread("visionteam.jpg");
imshow(im)
Сеть ожидает данные изображения типа данных single в диапазоне [-0,5, 0,5]. Переместите данные в этот диапазон и измените их масштаб.
netInput = im2single(im)-0.5;
Сеть ожидает цветовые каналы в порядке синий, зеленый, красный. Переключите порядок цветовых каналов изображения.
netInput = netInput(:,:,[3 2 1]);
Сохранение данных изображения в виде dlarray.
netInput = dlarray(netInput,"SSC");Спрогнозировать тепловые карты, выводимые из 2-D сверточного слоя с именем «node _ 147».
heatmaps = predict(net,netInput,"Outputs","node_147");
Получение числовых данных тепловой карты, сохраненных в dlarray. Данные имеют 19 каналов. Каждый канал соответствует тепловой карте для уникальной части корпуса с одной дополнительной тепловой картой для фона.
heatmaps = extractdata(heatmaps);
Отображение тепловых карт при монтаже с повторным масштабированием данных в диапазоне [0, 1], ожидаемом для изображений типа данных single. Сцена насчитывает шесть человек, а в каждой тепловой карте по шесть ярких пятен.
montage(rescale(heatmaps),"BackgroundColor","b","BorderSize",3)

Чтобы визуализировать соответствие ярких пятен с телами, выведите первую тепловую карту в фальсеколоре поверх тестового изображения.
idx = 1; hmap = heatmaps(:,:,idx); hmap = imresize(hmap,size(im,[1 2])); imshowpair(hmap,im);

Алгоритм OpenPose не использует фоновую тепловую карту для определения местоположения деталей тела. Удалите фоновую тепловую карту.
heatmaps = heatmaps(:,:,1:end-1);
Спрогнозировать PAF, которые выводятся из 2-D сверточного уровня с именем «node _ 150».
pafs = predict(net,netInput,"Outputs","node_150");
Получение числовых данных PAF, сохраненных в dlarray. Данные имеют 38 каналов. Существует два канала для каждого типа спаривания частей тела, которые представляют x - и y-компонент векторного поля.
pafs = extractdata(pafs);
Отображение PAF в монтаже с повторным масштабированием данных в диапазоне [0, 1], ожидаемом для изображений типа данных single. В двух столбцах показаны компоненты x и y векторного поля соответственно. Пары частей тела находятся в порядке, определяемом params.PAF_INDEX значение.
Пары частей корпуса с преимущественно вертикальным соединением имеют большие величины для пар y-компонент и незначительные значения для пар x-компонент. Одним из примеров является соединение правого бедра с правым коленом, которое появляется во втором ряду. Обратите внимание, что PAF зависят от фактических позиций на изображении. Изображение с телом в другой ориентации, например лежа, не обязательно будет иметь большую величину y-компонента для соединения правого бедра с правым коленом.
Пары частей тела с преимущественно горизонтальным соединением имеют большие величины для пар x-компонент и незначительные значения для пар y-компонент. Одним из примеров является соединение шейки с левым плечом, которое появляется в седьмом ряду.
Пары частей тела под углом имеют значения как для x -, так и для y-составляющих векторного поля. Одним из примеров является шейка левого бедра, которая появляется в первом ряду.
montage(rescale(pafs),"Size",[19 2],"BackgroundColor","b","BorderSize",3)

Чтобы визуализировать соответствие PAFs с телами, отобразите x - и y-компонент первого типа пары частей тела в фальсеколоре поверх тестового изображения.
idx = 1; impair = horzcat(im,im); pafpair = horzcat(pafs(:,:,2*idx-1),pafs(:,:,2*idx)); pafpair = imresize(pafpair,size(impair,[1 2])); imshowpair(pafpair,impair);

Постобработочная часть алгоритма идентифицирует индивидуальные позы людей на изображении с помощью тепловых карт и ПАФ, возвращаемых нейронной сетью.
Получение параметров алгоритма OpenPose с помощью getBodyPoseParameters функция помощника. Функция прикрепляется к примеру как вспомогательный файл. Функция возвращает структуру с такими параметрами, как количество деталей тела и соединения между типами деталей тела. Параметры также включают пороговые значения, которые можно настроить для повышения производительности алгоритма.
params = getBodyPoseParameters;
Идентифицировать отдельных людей и их позы с помощью getBodyPoses функция помощника. Эта функция присоединена к примеру как вспомогательный файл. Вспомогательная функция выполняет все этапы последующей обработки для оценки позы:
Определение точного расположения деталей корпуса по тепловым картам с помощью подавления, не являющегося максимальным.
Для каждого типа спаривания частей тела создайте все возможные пары между обнаруженными частями тела. Например, создайте все возможные пары между шестью шейками и шестью левыми плечами. Результатом является двудольный граф.
Оцените пары путем вычисления интеграла прямой линии, соединяющей две обнаруженные части тела через векторное поле PAF. Большая оценка указывает на сильную связь между обнаруженными частями тела.
Сортируйте возможные пары по их показателям и найдите допустимые пары. Допустимыми парами частей тела являются пары, соединяющие две части тела, принадлежащие одному человеку. Как правило, пары с наибольшим баллом считаются первыми, поскольку наиболее вероятно, что они являются действительной парой. Однако алгоритм компенсирует окклюзию и близость, используя дополнительные ограничения. Например, один и тот же человек не может иметь повторяющихся пар частей тела, а одна часть тела не может принадлежать двум разным людям.
Зная, какие части тела соединены, соберите части тела в отдельные позы для каждого отдельного человека.
Вспомогательная функция возвращает матрицу 3-D. Первое измерение представляет количество идентифицированных людей в изображении. Второй размер представляет количество типов деталей тела. Третье измерение указывает координаты x и y для каждой части тела каждого человека. Если часть тела не обнаружена на изображении, то координаты для этой части равны [NaN NaN].
poses = getBodyPoses(heatmaps,pafs,params);
Отображение позы тела с помощью renderBodyPoses функция помощника. Эта функция присоединена к примеру как вспомогательный файл.
renderBodyPoses(im,poses,size(heatmaps,1),size(heatmaps,2),params);

[1] Цао, Чжэ, Гине Идальго, Томаш Симон, Ших-Эн Вэй и Ясер Шейх. «OpenPose: 2D оценка позы для нескольких человек в реальном времени Используя области близости части». ArXiv:1812.08008 [Cs], 30 мая 2019 года. https://arxiv.org/abs/1812.08008.
[2] Осокин, Даниил. «2D оценка позы для нескольких человек в реальном времени на центральном процессоре: легкий вес OpenPose». ArXiv:1811.12004 [Cs], 29 ноября 2018 года. https://arxiv.org/abs/1811.12004.
dlnetwork (инструментарий для глубокого обучения) | importONNXLayers (инструментарий для глубокого обучения) | predict (инструментарий для глубокого обучения)