Ultralytics YOLO27: Встать в лист ожидания.
Get Started
Основы компьютерного зрения·Выбери задачу·Урок 5/10
Урокначинающий

Оценка позы и OBB

Извлеки ключевые точки и повёрнутые рамки из YOLO26, задай правило на их основе и определи, когда главным сигналом служат поза или угол.

В доме престарелых нужно знать, если кто-то упал; в порту — считать корабли, стоящие вплотную друг к другу на снимке с дрона. Обычные рамки не подходят ни для одной из задач: по рамке не понять, стоит ли человек прямо, а вертикальная рамка вокруг диагонально расположенного корабля захватывает в основном воду. Оценка позы и OBB созданы именно для этих двух задач.

Результат

Составь правило для оценки позы по ключевым точкам YOLO26 и измерь, насколько повёрнутые рамки экономят площадь на аэрофотоснимках.

Ускоренное прохождение
Если ты уже освоился, вот краткая версия.
  1. Поза: рамка и 17 ключевых точек на человека (порядок COCO: 0 — нос, 5–6 — плечи, 11–12 — бёдра, 15–16 — лодыжки).

  2. Перед использованием фильтруй ключевые точки по уверенности модели; даже для скрытых суставов всё равно задаются координаты.

  3. OBB: центр, размер и угол (xywhr, угол в радианах).

  4. Используй оценку позы, когда важна поза; OBB — когда объекты под углом на снимках сверху; во всех остальных случаях — детекцию.

Практические занятия

Оценка позы: когда важна поза#

Три бегуна на набережной: вокруг каждого человека рамка, а на теле — скелет из 17 ключевых точек, полученный с помощью оценки позы Ultralytics YOLO

Модель оценки позы возвращает рамку для каждого человека и фиксированный список ключевых точек. Модели, обученные на COCO-Pose, предсказывают 17 точек на человека — нос, глаза, уши, плечи, локти, запястья, бёдра, колени и лодыжки — всегда в одном порядке: индекс 0 соответствует носу, 11 — левому бедру, а 15 — левой лодыжке. Для каждой ключевой точки также указывается уверенность модели.

Самое простое полезное правило: стоящее тело выше, чем шире; тело, лежащее на полу, шире, чем выше. Вот как оно работает на изображении автобуса, если учитывать только ключевые точки, в которых модель уверена:

from ultralytics import YOLO

model = YOLO("yolo26n-pose.pt")
result = model("https://ultralytics.com/images/bus.jpg", verbose=False)[0]

for xy, conf in zip(result.keypoints.xy, result.keypoints.conf):
    visible = xy[conf > 0.5]  # drop keypoints the model couldn't see
    width = float(visible[:, 0].max() - visible[:, 0].min())
    height = float(visible[:, 1].max() - visible[:, 1].min())
    posture = "unknown" if len(visible) < 5 else "lying" if width > height else "upright"
    print(f"{len(visible):2d}/17 keypoints visible, body {width:3.0f} px wide x {height:3.0f} px tall -> {posture}")
16/17 keypoints visible, body 117 px wide x 427 px tall -> upright
 6/17 keypoints visible, body  80 px wide x 359 px tall -> upright
16/17 keypoints visible, body  91 px wide x 384 px tall -> upright
 1/17 keypoints visible, body   0 px wide x   0 px tall -> unknown
 2/17 keypoints visible, body   3 px wide x   6 px tall -> unknown

Три человека явно стоят. В последних двух строках показаны человек, обрезанный левым краем кадра, и дубликат с низкой уверенностью модели: по одной-двум видимым ключевым точкам ничего не определить, поэтому правило выдаёт «неизвестно», а не пытается угадать. В работающий детектор падений добавляют время: отслеживание определяет, что человек лежит дольше нескольких секунд после резкого падения.

У скрытых суставов тоже есть координаты

Симптом: скелеты с запястьями в воздухе и правила позы, срабатывающие для людей, видимых лишь частично. Причина: keypoints.xy возвращает координаты всех 17 ключевых точек, даже тех, которые модель не видела. Решение: фильтруй точки с помощью keypoints.conf, как описано выше, и требуй минимального количества видимых ключевых точек, прежде чем принимать решение.

Оценка позы полезна, когда ответ зависит от того, что делает тело: например, при обнаружении падений или подъёма тяжестей с согнутой спиной для обеспечения безопасности, измерении углов суставов и подсчёте повторений в спорте, как в мониторинге тренировок, а также при оценке позы скота и поиске неподвижных ориентиров на деталях с пользовательской схемой ключевых точек. Чтобы ответить на вопрос «есть ли здесь человек?», используй обычную детекцию.

OBB: когда важен угол#

Три яхты стоят под углом на аэрофотоснимке; вокруг каждой — плотно прилегающая повёрнутая рамка Ultralytics YOLO OBB

У обычной рамки стороны параллельны краям изображения. Ориентированная ограничивающая рамка дополнительно учитывает поворот; её параметры — центр, ширина, высота и угол (xywhr). На снимках сверху — со спутника, с дрона или с камер над конвейером — объекты располагаются под разными углами, поэтому вертикальная рамка вокруг диагонального объекта захватывает в основном фон, как в случае с яхтами выше. Измерь разницу на снимке марины с дрона:

from ultralytics import YOLO

model = YOLO("yolo26n-obb.pt")
result = model("https://ultralytics.com/images/boats.jpg", verbose=False)[0]

obb = result.obb
rotated_area = obb.xywhr[:, 2] * obb.xywhr[:, 3]  # width x height of each rotated box
x1, y1, x2, y2 = obb.xyxy.T  # the axis-aligned box that would enclose the same object
upright_area = (x2 - x1) * (y2 - y1)

print(f"{len(obb)} objects, classes: {sorted({result.names[int(c)] for c in obb.cls})}")
cx, cy, w, h, angle = obb.xywhr[0].tolist()
print(f"first box: center=({cx:.0f}, {cy:.0f}) size={w:.0f}x{h:.0f} angle={angle:.2f} rad")
ratio = float((upright_area / rotated_area).median())
print(f"an axis-aligned box would be {ratio:.1f}x larger (median)")
173 objects, classes: ['harbor', 'ship']
first box: center=(619, 850) size=33x108 angle=-0.25 rad
an axis-aligned box would be 2.1x larger (median)

Вертикальная рамка занимает примерно вдвое большую площадь, чем повёрнутая рамка вокруг той же лодки, а лишняя площадь приходится на воду. Это вредит дважды: NMS видит пересечение вертикальных рамок соседних лодок и может удалить реальные объекты, а оценка размера оказывается завышенной. Модели OBB, обученные на аэрофотоснимках, например на DOTA, напрямую справляются с такими сценами. Учти, что угол задаётся в радианах: -0.25 рад — это примерно -14°.

Как выбрать между детекцией, оценкой позы и OBB#

СценарийПодходящая задачаПочему
Подсчёт людей на тротуареДетекцияНужно определить наличие и местоположение
Обнаружение падения в доме престарелыхОценка позыВажный сигнал — ориентация тела
Подсчёт приседаний в спортзалеОценка позыВажный сигнал — углы коленей и бёдер
Подсчёт пришвартованных лодок по снимку с дронаOBBЛодки расположены по диагонали и стоят вплотную друг к другу
Посылки на конвейере, вид сверхуOBBОбъекты повёрнуты по-разному и соприкасаются
Автомобили на уровне улицыДетекцияАвтомобили расположены в кадре примерно вертикально
Pose и OBB — это детекция плюс что-то ещё

Pose добавляет ключевые точки к каждой рамке, а OBB — угол. Если код никогда не использует ключевые точки или угол, обычный детектор быстрее размечать и запускать, а также проще отлаживать.

Попробовать

Запусти сравнение из решения на изображении марины: сопоставь детектор, предобученный на COCO, с моделью OBB. Запиши оба результата, а затем одним предложением объясни, какая часть разницы связана с геометрией рамок, а какая — с данными, на которых обучалась каждая модель. Наконец, назови одну задачу из своей работы, где оценка позы или OBB лучше обычной детекции, и укажи правило, которое будет применять твой код.

Критерии готовности
Урок считается завершённым, если выполнены все условия ниже.
  • У тебя есть оба результата подсчёта лодок на boats.jpg и одно предложение с объяснением разницы.

  • Ты можешь указать строку в правиле оценки позы, которая отфильтровывает скрытые ключевые точки, и объяснить, зачем это нужно.

  • Ты назвал задачу из своей работы, для которой подойдёт оценка позы или OBB, и указал правило, которое будет применять твой код.

Показать решение
from ultralytics import YOLO

image = "https://ultralytics.com/images/boats.jpg"
upright = YOLO("yolo26n.pt")(image, verbose=False)[0]
rotated = YOLO("yolo26n-obb.pt")(image, verbose=False)[0]
print(f"axis-aligned detector: {len(upright.boxes)} boxes")
print(f"OBB model: {len(rotated.obb)} rotated boxes")
axis-aligned detector: 0 boxes
OBB model: 173 rotated boxes

Большая часть разницы связана с данными для обучения, а не с геометрией. yolo26n.pt обучалась на COCO, где лодки в основном сняты сбоку; на снимке сверху модель не находит ни одной лодки при пороговом значении по умолчанию (снизь conf до 0.05 — и модель примет некоторые лодки за бутылки). Модель OBB обучалась на аэрофотоснимках. Геометрия тоже важна: даже детектор, обученный на снимках лодок с воздуха, построил бы рамки примерно вдвое большего размера и испытывал бы трудности с NMS на плотно расположенных рядах. И задача, и обучающие данные должны соответствовать условиям эксплуатации модели.

Что дальше

На примере марины мы увидели, что обучающие данные не менее важны, чем сама задача. Далее: проверим, соответствует ли набор данных условиям, в которых будет работать модель.

Войди, чтобы сохранять прогресс