Привет, Хабр! Сегодня расскажу о решении важной для многих из нас и ставшей уже классической задачи - детектировании позы человека на изображении. Решать её я предлагаю с использованием библиотеки OpenPose. Всё самое интересное ― под катом. Сразу скажу, что статья небольшая, но наглядная ― я постаралась без лишних слов показать возможности библиотеки. В первую очередь она предназначена для начинающих специалистов, но, возможно, и профи найдут что-то полезное для себя.
Определить позу человека на изображении? А в чём проблема?
Но каждый, кто писал программы распознавания объектов, используя opencv, знает, что выделение опорных точек и построение выпуклой оболочки ― наименьшего выпуклого множества, содержащего опорные точки, дело часто тяжёлое и неблагодарное.
Для примера давайте решим нашу классическую задачу и определим опорные точки на изображении.
image = cv.imread(“C:/Users/User/anaconda3/libs/openpose/examples/media/COCO_val2014_000000000192.jpg”)
im = image.copy() / 255.
im = im / 255
im = rgb2gray(im)
contours, hierarchy = cv2.findContours(img_as_ubyte(im), cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
ma = 0
cnt = 0
for cont in contours:
ar = cv2.contourArea(cont)
if ma < ar:
ma = ar
cnt = cont
hull = cv2.convexHull(cnt, returnPoints = False)
defects = cv2.convexityDefects(cnt,hull)
m = cv2.moments(cnt)
cx = int(m[“m10”]/m[“m00”])
cy = int(m[“m01”]/m[“m00”])
fng = []
for point in defects:
point = point[0]
s, e, f = cnt[point[0]][0], cnt[point[1]][0], cnt[point[2]][0]
d = point[3] / 256.0
fng.append([tuple(s), tuple(e), tuple(f), d])
for point in fng:
cv.circle(image, point[0], 5, [255,0,0], -1)
cv.circle(image, point[1], 5, [255,0,0], -1)
cv. circle(image, point[2], 5, [255,1,0],-1)
Для того чтобы оптимально решить задачу, сначала лучше преобразовать изображение. А именно ― нормализовать и перевести в серый, после чего определить контуры, построить выпуклую оболочку и вывести на изображение опорные точки. Казалось бы, всё просто ― чтобы узнать позу человека, нужно связать только крайние точки тела, к тому же с ближайшими соседями. Но это только кажется, что всё просто. Даже с обычным изображением не всё гладко, а ведь может быть и множество нюансов. Ну например, если на изображении видно не всё тело?
Работы здесь просто вагон и маленькая тележка, может, и не одна. К счастью, для облегчения задач в этом направлении есть несколько крутых решений, которые упрощают нам жизнь. Одно из них ― как раз OpenPose.
Что это такое и как работает?
Одна из первых, если не первая, систем для обнаружения человеческого тела в многомерном пространстве в реальном времени ― всего используется 135 ключевых точек. Они обычно соответствуют «сочленениям», если так можно выразиться, с определённой степенью свободы на человеческом теле. Пример ― шея, плечо, локоть, запястье и т. д.
Впервые модель была предложена исследователями из Университета Carnegie Mellon. На сегодняшний день OpenPose используют в работе тысячи специалистов из крупных и мелких компаний. Например, с ней работает Disney для точной передачи позы человека персонажами, а создатели алгоритма из Carnegie Mellon University научили робота копировать движения человека. Есть и другие проекты на базе OpenPose ― так, команда учёных из Университета Женевы применяет систему для диагностики аутизма у детей.
Теперь давайте посмотрим, как всё это работает. Ниже ― изображение для наглядности.
Вход модели представляет собой цветную картинку размера h*w. Далее ― 10 слоёв VGGNet (Very Deep Convolutional Network), они используются для создания карты признаков (feature maps) входного изображения.
Затем карта признаков обрабатывается в многоэтапном конвейере CNN (Convolutional neural network) для создания карт достоверности (Confidence Maps) и поля сходства деталей (Part Affinity Fields).
Карта достоверности ― набор матриц или «тепловая карта» для каждой ключевой точки. Каждая матрица отражает достоверность появления определённой ключевой точки в пикселе. Чем выше значение на карте, тем выше вероятность появления опорной точки в этой части изображения.
Поле сходства деталей ― набор матриц, который отражает степень близости для найденных ранее опорных точек и отвечает за кодирование 2D-вектора положения, а также направления конечностей в области изображения.
После получения карт достоверности (Confidence Maps) и поля сходства деталей (Part Affinity Fields) применяется Венгерский алгоритм (Двудольное соответствие в теории графов ― максимальное количество совпадений рёбер среди всех совпадений графа), чтобы найти связь частей и соединить суставы одного и того же человека. Из-за векторной природы самого PAF сгенерированные совпадения объединяют общий скелет человека.
Примеры? Они есть у меня
Всё это красивая теория, но давайте посмотрим, что у нас с практическим применением системы. Скачиваем последнюю версию библиотеки с github.
1. OpenPose можно запустить из командной строки, указав путь к изображениям или видео:
bin\OpenPoseDemo.exe --image_dir examples\media\
Программа сама откроет окно с результатами:
Можно работать с OpenPose так же, как с обычной библиотекой Указываем путь до директории с библиотекой и импортируем её.
sys.path.append(dir_path + ‘/../../python/openpose/Release’);
os.environ[‘PATH’] = os.environ[‘PATH’] + ‘;’ + dir_path + ‘/../../x64/Release;’ + dir_path + ‘/../../bin;’
import pyopenpose as op
Запускаем модель, передав ей необходимые параметры.
# Starting OpenPose
opWrapper = op.WrapperPython()
opWrapper.configure(params)
opWrapper.start()
На этом этапе приступаем к обработке изображения.
# Process Image
Datum = op.Datum()
imageToProcess = cv2.imread(args[0].image_path)
datum.cvInputData = imageToProcess
opWrapper.emplaceAndPop(op.VectorDatum([datum]))
Выводим изображение с добавлением полученных опорных точек.
#Display Image
print(“Body keypoints: \n” + str(datum.poseKeypoints))
cv2.imshow(“OpenPose 1.7.0 – Tutorial Python API”, datum.cvOutputData)
cv.waitKey(0)
Возможностей просто море!
OpenPose способна детектировать позы сразу нескольких людей на изображении плюс покадрово обрабатывать видео, распознавать точки на лице или пальцах рук. При этом модель, как было показано выше, является невероятно простой в использовании, избавляя от необходимости самому разбираться с opencv и отбором необходимых точек. Это просто глоток свежего воздуха в атмосфере множества рутинных задач по обработке изображений.