Ultralytics YOLO27: Tham gia danh sách chờ.
Get Started
Nền tảng Thị giác máy tính·Chọn tác vụ·Bài học 5/10
Bài họcngười mới bắt đầu

Ước tính tư thế và OBB

Đọc keypoint và hộp xoay từ YOLO26, xây dựng quy tắc dựa trên từng loại, và nhận biết khi tư thế hoặc góc mới là tín hiệu thực sự.

Một cơ sở chăm sóc cần biết khi có người bị ngã; một cảng cần đếm số tàu nằm sát nhau trong ảnh chụp từ drone. Hộp thông thường không đáp ứng được cả hai: hộp không cho biết một người đang đứng thẳng hay không, còn hộp thẳng bao quanh một con tàu nằm chéo thì chủ yếu là mặt nước. Ước tính tư thế và OBB được thiết kế chính xác để giải quyết hai vấn đề này.

Kết quả

Viết quy tắc tư thế từ keypoint YOLO26 và đo lường mức tiết kiệm mà hộp xoay mang lại trên ảnh chụp từ trên cao.

Lộ trình cấp tốc
Nếu bạn đã nắm rõ cách thực hiện, đây là phiên bản tóm tắt.
  1. Pose: một hộp cộng với 17 keypoint cho mỗi người (thứ tự COCO: 0 mũi, 5–6 vai, 11–12 hông, 15–16 mắt cá chân).

  2. Lọc keypoint theo độ tin cậy trước khi sử dụng; các khớp bị che khuất vẫn có tọa độ.

  3. OBB: tâm, kích thước và góc (xywhr, góc tính bằng radian).

  4. Dùng pose khi tư thế là tín hiệu; dùng OBB khi vật thể nằm nghiêng trong ảnh nhìn từ trên xuống; các trường hợp khác dùng detection.

Thực hành

Pose: khi tư thế là tín hiệu#

Ba vận động viên chạy trên lối đi ven sông, mỗi người được bao quanh bởi hộp người và bộ khung xương 17 keypoint từ tính năng ước tính tư thế YOLO của Ultralytics

Model pose trả về một hộp cho mỗi người, cùng với danh sách keypoint cố định. Các model được huấn luyện trên COCO-Pose dự đoán 17 keypoint cho mỗi người — mũi, mắt, tai, vai, khuỷu tay, cổ tay, hông, đầu gối và mắt cá chân — luôn theo cùng một thứ tự, vì vậy index 0 là mũi, 11 là hông trái và 15 là mắt cá chân trái. Mỗi keypoint cũng có độ tin cậy riêng.

Quy tắc hữu ích đơn giản nhất: cơ thể đứng thẳng cao hơn rộng; cơ thể nằm trên sàn rộng hơn cao. Đây là kết quả áp dụng trên ảnh xe buýt, chỉ sử dụng những keypoint mà model có độ tin cậy cao:

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

Ba người rõ ràng đang đứng thẳng. Hai hàng cuối là người bị cắt mất một phần ở mép trái và một bản phát hiện trùng có độ tin cậy thấp: chỉ với một hoặc hai keypoint nhìn thấy được thì không thể đánh giá, nên quy tắc trả về "không xác định" thay vì đoán. Hệ thống phát hiện té ngã dùng trong thực tế sẽ bổ sung yếu tố thời gian thông qua tracking — chẳng hạn nằm lâu hơn vài giây sau khi ngã nhanh.

Khớp bị che khuất vẫn có tọa độ

Triệu chứng: skeleton có cổ tay lơ lửng giữa không trung và quy tắc tư thế được kích hoạt với người chỉ hiện một phần. Nguyên nhân: keypoints.xy trả về vị trí cho cả 17 keypoint, kể cả những điểm model không thể nhìn thấy. Cách khắc phục: lọc bằng keypoints.conf như trên, đồng thời yêu cầu số lượng keypoint nhìn thấy tối thiểu trước khi đưa ra bất kỳ quyết định nào.

Pose phát huy tác dụng khi câu trả lời phụ thuộc vào hành động của cơ thể: phát hiện té ngã hoặc nâng vật với lưng cong để đảm bảo an toàn, đo góc khớp và đếm số lần tập thể thao như trong giám sát bài tập, hoặc theo dõi tư thế vật nuôi và các điểm mốc cố định trên bộ phận bằng bố cục keypoint tùy chỉnh. Để trả lời câu hỏi "có người ở đây không?", hãy dùng detection thông thường.

OBB: khi góc quan trọng#

Ba du thuyền neo ở các góc khác nhau trong ảnh chụp từ trên cao, mỗi chiếc được bao quanh bởi hộp xoay khít từ Ultralytics YOLO OBB

Các cạnh của hộp thông thường song song với ảnh. Hộp giới hạn có hướng bổ sung góc xoay, được lưu dưới dạng tâm, chiều rộng, chiều cao và góc (xywhr). Trong ảnh nhìn từ trên xuống — ảnh vệ tinh, drone, camera băng chuyền nhìn từ trên cao — vật thể nằm ở nhiều góc độ, còn hộp thẳng bao quanh một vật thể nằm chéo thì chủ yếu là phông nền, như trường hợp các du thuyền phía trên. Hãy đo mức chênh lệch trên ảnh chụp từ drone tại bến du thuyền:

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)

Hộp thẳng bao phủ diện tích lớn gấp khoảng hai lần hộp xoay quanh cùng một chiếc thuyền, phần diện tích dư ra là mặt nước. Điều này gây ra hai vấn đề: NMS thấy các hộp thẳng của những chiếc thuyền gần nhau chồng lấn và có thể loại bỏ các đối tượng thực, đồng thời mọi ước tính kích thước đều bị phóng đại. Các model OBB được huấn luyện trên tập dữ liệu ảnh chụp từ trên cao như DOTA xử lý trực tiếp những cảnh này. Lưu ý góc tính bằng radian: -0.25 rad tương đương khoảng -14°.

Chọn giữa detection, pose và OBB#

Tình huốngTác vụ phù hợp nhấtLý do
Đếm người trên vỉa hèPhát hiệnCâu trả lời là sự hiện diện và vị trí
Phát hiện người bị ngã tại cơ sở chăm sócPoseHướng cơ thể là tín hiệu
Đếm số lần squat trong phòng tậpPoseGóc đầu gối và hông là tín hiệu
Đếm thuyền neo tại bến bằng droneOBBThuyền nằm chéo và đậu sát nhau
Các kiện hàng trên băng chuyền, nhìn từ trên caoOBBHướng vật thể thay đổi và các vật thể sát nhau
Ô tô ở tầm đường phốPhát hiệnÔ tô xuất hiện gần như thẳng đứng trong khung hình
Pose và OBB là detection cộng thêm một thành phần

Pose bổ sung keypoint vào mỗi hộp; OBB bổ sung một góc. Nếu code của bạn không bao giờ đọc keypoint hoặc góc, detector thông thường sẽ nhanh gán nhãn hơn, chạy nhanh hơn và dễ debug hơn.

Dùng thử

Chạy phép so sánh trong phần giải pháp trên ảnh bến du thuyền: model detection được huấn luyện trước trên COCO so với model OBB. Ghi lại cả hai số lượng, rồi viết một câu giải thích mức chênh lệch đến từ hình học hộp là bao nhiêu và từ dữ liệu huấn luyện của từng model là bao nhiêu. Cuối cùng, nêu một vấn đề trong công việc của bạn mà pose hoặc OBB sẽ xử lý tốt hơn detection thông thường, cùng quy tắc mà code của bạn sẽ áp dụng.

Điều kiện hoàn thành
Bạn đã hoàn thành bài học khi tất cả các điều kiện sau đều đúng.
  • Bạn có cả hai số lượng thuyền trong boats.jpg và một câu giải thích mức chênh lệch.

  • Bạn có thể chỉ ra dòng trong quy tắc tư thế lọc các keypoint bị che khuất và giải thích vì sao cần dòng đó.

  • Bạn đã nêu một vấn đề trong công việc phù hợp với pose hoặc OBB, cùng quy tắc mà code của bạn sẽ áp dụng.

Hiển thị lời giải
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

Phần lớn mức chênh lệch đến từ dữ liệu huấn luyện, không phải hình học. yolo26n.pt được huấn luyện trên COCO, nơi thuyền chủ yếu được chụp từ bên cạnh; khi nhìn từ trên cao, model không phát hiện được gì ở ngưỡng mặc định (giảm conf xuống 0.05 thì model nhận nhầm một số thuyền thành chai). Model OBB được huấn luyện trên ảnh chụp từ trên cao. Hình học vẫn quan trọng: ngay cả model detection được huấn luyện trên ảnh thuyền chụp từ trên cao cũng sẽ tạo hộp lớn gấp khoảng hai lần và gặp khó khăn với NMS trong các hàng thuyền đậu sát nhau. Cả tác vụ lẫn dữ liệu huấn luyện đều phải phù hợp với góc nhìn khi triển khai.

Tiếp theo là gì

Bến du thuyền cho thấy dữ liệu huấn luyện cũng quan trọng như tác vụ. Tiếp theo: kiểm tra xem tập dữ liệu có phù hợp với thế giới mà bạn triển khai model hay không.

Đăng nhập để lưu tiến độ