فاز 4 · درس 21

تخمین ژست و تشخیص نقاط کلیدی (Pose Estimation)

نوع
ساختنی
زمان
حدود 45 دقیقه
زبان‌ها
Python
یک فیگور انتزاعی از اسکلت انسان متشکل از مفاصل درخشان که روی یک شبکه مختصات دوبعدی و هیت‌مپ حرارتی رنگی قرار گرفته است.
فهرست مطالب
  1. اهداف یادگیری
  2. صورت مسئله
  3. مفاهیم پایه
  4. رویکرد بالا به پایین در برابر پایین به بالا
  5. رگرسیون نقشه حرارتی
  6. مکان‌یابی با دقت زیرپیکسل
  7. میدان‌های پیوستگی اندام‌ها (PAFs)
  8. مجموعه داده نقاط کلیدی COCO
  9. مقایسه ژست 2 بعدی و 3 بعدی
  10. پیاده‌سازی
  11. گام 1: هدف نقشه حرارتی گاوسی
  12. گام 2: هد کوچک نقاط کلیدی
  13. گام 3: استنتاج — استخراج مختصات نقاط کلیدی
  14. گام 4: مجموعه داده ساختگی نقاط کلیدی
  15. گام 5: آموزش
  16. کاربرد در عمل
  17. انتشار در محیط عملیاتی
  18. تمرین‌ها
  19. اصطلاحات کلیدی
  20. مطالعه‌ی بیشتر

ردیابی حرکات بدن، چهره یا دست پایه‌ی اصلی اپلیکیشن‌های تناسب اندام، پویانمایی، واقعیت افزوده و تحلیل‌های حرکتی است. در نگاه اول، پیش‌بینی مختصات مفاصل شبیه یک رگرسیون ساده‌ی عددی به نظر می‌رسد؛ اما شبکه‌های عصبی بدون درک ساختار فضایی تصویر، در پیش‌بینی مستقیم اعداد به مشکل می‌خورند. این درس سازوکار دقیق و استاندارد صنعت را بررسی می‌کند: تبدیل مسئله به رگرسیون نقشه‌های حرارتی (Heatmaps) و سپس استخراج مختصات نقاط کلیدی.

در این بخش با تفاوت‌های بنیادین روش‌های بالا به پایین (Top-down) و پایین به بالا (Bottom-up) مانند OpenPose آشنا می‌شوید، میدان‌های پیوستگی اندام‌ها (PAFs) را بررسی می‌کنید و یاد می‌گیرید چگونه با معماری‌های شبیه U-Net یک آشکارساز سبک بسازید. برای آزمایش و اجرای کدهای این درس به GPU ابری گران‌قیمت نیازی ندارید و پایپ‌لاین آزمایشی روی CPU معمولی یا سیستم شخصی شما به‌راحتی اجرا می‌شود.

ژست بدنی (pose) مجموعه‌ای مرتب از نقاط کلیدی است. آشکارساز نقاط کلیدی هم یک مدل رگرسیون نقشه حرارتی است. باقی ماجرا فقط کارهای دفتری و حساب‌وکتاب است.

اهداف یادگیری

  • تشخیص تفاوت تخمین ژست بالا به پایین (top-down) و پایین به بالا (bottom-up) و تعیین زمان استفاده از هرکدام
  • رگرسیون نقشه‌های حرارتی (heatmaps) برای K نقطه کلیدی با هدف گاوسی به‌ازای هر نقطه و استخراج مختصات نقاط در زمان استنتاج
  • توضیح میدان‌های پیوستگی اندام‌ها یا PAFs (مخفف Part Affinity Fields) و نحوه‌ی اتصال نقاط کلیدی به نمونه‌های مجزا در پایپ‌لاین‌های پایین به بالا
  • استفاده از MediaPipe Pose یا MMPose برای تخمین نقاط کلیدی در محیط عملیاتی و درک ساختار خروجی آن‌ها

صورت مسئله

مسائل مربوط به نقاط کلیدی با نام‌های گوناگونی شناخته می‌شوند: ژست انسان (17 مفصل بدن)، لندمارک‌های چهره (68 یا 478 نقطه)، دست (21 نقطه)، ژست حیوانات، ژست اجسام در رباتیک و نقاط شاخص آناتومی در پزشکی. ساختار همه‌ی آن‌ها یکسان است: K نقطه‌ی متمایز را روی یک شیء شناسایی کن و مختصات (x, y) آن‌ها را تحویل بده.

تخمین ژست پایه‌ی موشن کپچر، اپلیکیشن‌های تناسب اندام، تحلیل‌های ورزشی، کنترل با ژست‌های حرکتی، پویانمایی، پرو مجازی در واقعیت افزوده (AR) و گرفتن اجسام در رباتیک است. حالت 2 بعدی به بلوغ کامل رسیده است؛ اما ژست 3 بعدی (تخمین موقعیت مفاصل در مختصات دنیای واقعی با یک دوربین تکی) مرز پژوهش‌های کنونی به شمار می‌رود.

مسئله‌ی اصلی مهندسی در اینجا مقیاس‌پذیری است. تخمین ژست یک فرد در یک تک‌تصویر، مسئله‌ای 20 میلی‌ثانیه‌ای است؛ ولی تخمین ژست چندین نفر در میان جمعیت با نرخ 30 فریم بر ثانیه، مسئله‌ای کاملاً متفاوت با معماری‌های جداگانه است.

مفاهیم پایه

رویکرد بالا به پایین در برابر پایین به بالا

پایپ‌لاین پایین به بالاپایپ‌لاین بالا به پایینتشخیص کادرهای افرادبرش هر کادرمدل نقاط کلیدی برای هر کادر(HRNet, ViTPose)یک بار عبور از تصویرنقشه‌های حرارتی تمام نقاط کلیدی+ میدان ارتباطگروه‌بندی نقاط کلیدی بهنمونه‌ها (تطبیق حریصانه)
  • بالا به پایین (Top-down) — ابتدا افراد را شناسایی می‌کند، سپس مدل نقاط کلیدی را روی برش (crop) تصویر هر فرد اجرا می‌کند. بیشترین دقت را دارد؛ ولی زمان اجرای آن با تعداد افراد رابطه‌ی خطی دارد.
  • پایین به بالا (Bottom-up) — با یک گذر رو به جلو (forward pass)، همه‌ی نقاط کلیدی را به همراه یک میدان پیوستگی پیش‌بینی و سپس آن‌ها را گروه‌بندی می‌کند. زمان اجرای آن صرف‌نظر از تراکم جمعیت، ثابت است.

مدل‌های بالا به پایین (نظیر HRNet و ViTPose) بالاترین دقت را دارند؛ درحالی‌که مدل‌های پایین به بالا (مانند OpenPose و HigherHRNet) بالاترین گذردهی (throughput) را در صحنه‌های شلوغ ارائه می‌دهند.

رگرسیون نقشه حرارتی

به جای رگرسیون مستقیم (x, y)، برای هر نقطه کلیدی یک نقشه حرارتی در ابعاد H x W با یک حباب گاوسی متمرکز بر موقعیت واقعی پیش‌بینی کنید.

target[k,y,x]=exp⁡(−(x−cxk)2+(y−cyk)22σ2)\text{target}[k, y, x] = \exp\left(-\frac{(x - \mathit{cx}_k)^2 + (y - \mathit{cy}_k)^2}{2 \sigma^2}\right)

در زمان استنتاج، نقطه بیشینه (argmax) هر نقشه حرارتی، همان موقعیت پیش‌بینی‌شده‌ی نقطه کلیدی است.

چرا نقشه‌های حرارتی بهتر از رگرسیون مستقیم عمل می‌کنند؟ ساختار فضایی شبکه (نقشه ویژگی‌های کانولوشنی) به‌طور طبیعی با خروجی فضایی هم‌راستاست. علاوه‌بر این، اهداف گاوسی نوعی منظم‌سازی ایجاد می‌کنند؛ خطای مکانی کوچک باعث تولید تابعی از زیان ناچیز می‌شود، نه صفر.

مکان‌یابی با دقت زیرپیکسل

دستور argmax مختصات صحیح و بدون اعشار می‌دهد. برای رسیدن به دقت (precision) در سطح زیرپیکسل (sub-pixel)، موقعیت را با برازش یک سهمی روی نقطه بیشینه و همسایگانش بهبود دهید؛ یا مانند کد این درس، نقطه بیشینه را با رابطه‌ی dx = 0.25 * (heatmap[y, x+1] - heatmap[y, x-1]) و فرمولی مشابه برای dy، به سمت همسایه‌ی با مقدار بیشتر بلغزانید.

میدان‌های پیوستگی اندام‌ها (PAFs)

شگرد OpenPose برای اتصال پایین به بالا همین است. برای هر جفت نقطه کلیدی متصل‌به‌هم (مثلاً از شانه‌ی چپ به آرنج چپ)، یک میدان 2 کاناله پیش‌بینی می‌شود که بردار واحد جهت‌گیری بین آن‌ها را مشخص می‌کند. برای اتصال شانه به آرنج متناظرش، انتگرال خطی PAF در امتداد خط واصل جفت‌های نامزد محاسبه می‌شود؛ جفتی که بیشترین مقدار انتگرال را داشته باشد، با هم متناظر می‌شوند.

For each connection (limb):
  PAF channels: 2 (unit vector x, y)
  Line integral: sum over sample points of (PAF . line_direction)
  Higher integral = stronger match

روشی ظریف که بدون نیاز به برش تصویر افراد، برای هر تعداد جمعیت مقیاس‌پذیر است.

مجموعه داده نقاط کلیدی COCO

مجموعه داده استاندارد ژست بدن انسان: 17 نقطه کلیدی به‌ازای هر فرد، همراه با معیارهای ارزیابی PCK (درصد نقاط کلیدی درست) و OKS (شباهت نقاط کلیدی شیء). معیار OKS معادل IoU برای نقاط کلیدی است و خروجی گزارش‌شده در COCO mAP@OKS به حساب می‌آید.

مقایسه ژست 2 بعدی و 3 بعدی

  • ژست 2 بعدی — مختصات تصویر؛ با کیفیت آماده برای محیط عملیاتی حل شده است (MediaPipe، HRNet، ViTPose).
  • ژست 3 بعدی — مختصات دنیای واقعی یا دوربین؛ هنوز حوزه‌ای با پژوهش‌های فعال است. رویکردهای رایج:
    • ارتقای پیش‌بینی‌های 2 بعدی به 3 بعدی با یک پرسپترون چندلایه (MLP) کوچک (VideoPose3D).
    • رگرسیون مستقیم 3 بعدی از روی تصویر (PyMAF، MHFormer).
    • چیدمان‌های چنددوربینه (CMU Panoptic) برای ثبت داده‌های مرجع واقعیت زمینی (ground truth).
تخمین ژست · رگرسیون نقشه حرارتییافتن قله‌ها، اتصال استخوان‌ها
POSE · HEATMAP REGRESSIONA pose model does not regress coordinates directly. It outputs one heatmap per keypoint, trained so a Gaussian bump sits over the true joint; the argmax pixel is the coordinate. Once all K peaks resolve, the joints are linked into a skeleton by a fixed body graph (top-down) or by association fields (bottom-up).per-keypoint heatmap (argmax = joint)اسکلت ساخته‌شدهیکی از K نقشه حرارتیرگرسیون یک گوسی برای هر مفصل، سپس انتخاب پیکسل argmax
مدل تخمین ژست مختصات را مستقیماً پیش‌بینی نمی‌کند، بلکه به ازای هر نقطه کلیدی یک نقشه حرارتی تولید می‌کند؛ به طوری که یک برآمدگی گوسی روی مفصل واقعی قرار گیرد. پیکسل بیشینه (argmax) همان مختصات است. پس از مشخص شدن تمام K قله، مفاصل از طریق یک گراف بدنی ثابت (از بالا به پایین) یا میدان‌های پیوستگی (از پایین به بالا) به یک اسکلت متصل می‌شوند.

پیاده‌سازی

گام 1: هدف نقشه حرارتی گاوسی

import numpy as np
import torch

def gaussian_heatmap(size, cx, cy, sigma=2.0):
    yy, xx = np.meshgrid(np.arange(size), np.arange(size), indexing="ij")
    return np.exp(-((xx - cx) ** 2 + (yy - cy) ** 2) / (2 * sigma ** 2)).astype(np.float32)

hm = gaussian_heatmap(64, 32, 32, sigma=2.0)
print(f"peak: {hm.max():.3f} at ({hm.argmax() % 64}, {hm.argmax() // 64})")

پشته‌سازی نقشه‌های حرارتی هر نقطه کلیدی در امتداد محور کانال، تنسور هدف نهایی را می‌سازد.

گام 2: هد کوچک نقاط کلیدی

مدلی به سبک U-Net که K کانال نقشه حرارتی در خروجی تولید می‌کند.

import torch.nn as nn
import torch.nn.functional as F

class TinyKeypointNet(nn.Module):
    def __init__(self, num_keypoints=4, base=16):
        super().__init__()
        self.down1 = nn.Sequential(nn.Conv2d(3, base, 3, 2, 1), nn.ReLU(inplace=True))
        self.down2 = nn.Sequential(nn.Conv2d(base, base * 2, 3, 2, 1), nn.ReLU(inplace=True))
        self.mid = nn.Sequential(nn.Conv2d(base * 2, base * 2, 3, 1, 1), nn.ReLU(inplace=True))
        self.up1 = nn.ConvTranspose2d(base * 2, base, 2, 2)
        self.up2 = nn.ConvTranspose2d(base, num_keypoints, 2, 2)

    def forward(self, x):
        h1 = self.down1(x)
        h2 = self.down2(h1)
        h3 = self.mid(h2)
        u1 = self.up1(h3)
        return self.up2(u1)

ورودی (N, 3, H, W) و خروجی (N, K, H, W) است. تابع زیان (loss) نیز MSE پیکسل‌به‌پیکسل در مقایسه با اهداف گاوسی است.

گام 3: استنتاج — استخراج مختصات نقاط کلیدی

def heatmap_to_coords(heatmaps):
    """
    heatmaps: (N, K, H, W)
    returns:  (N, K, 2) float coordinates in image pixels
    """
    N, K, H, W = heatmaps.shape
    hm = heatmaps.reshape(N, K, -1)
    idx = hm.argmax(dim=-1)
    ys = (idx // W).float()
    xs = (idx % W).float()
    return torch.stack([xs, ys], dim=-1)

coords = heatmap_to_coords(torch.randn(2, 4, 32, 32))
print(f"coords: {coords.shape}")  # (2, 4, 2)

در زمان استنتاج، کار در یک خط انجام می‌شود. برای دقت زیرپیکسل، کافی است اطراف argmax درونیابی کنید.

گام 4: مجموعه داده ساختگی نقاط کلیدی

ساده است: چهار نقطه روی یک بوم سفید رسم کنید و یاد بگیرید آن‌ها را پیش‌بینی کنید.

def make_synthetic_sample(size=64):
    img = np.ones((3, size, size), dtype=np.float32)
    rng = np.random.default_rng()
    kps = rng.integers(8, size - 8, size=(4, 2))
    for cx, cy in kps:
        img[:, cy - 2:cy + 2, cx - 2:cx + 2] = 0.0
    hms = np.stack([gaussian_heatmap(size, cx, cy) for cx, cy in kps])
    return img, hms, kps

آن‌قدر ساده است که یک مدل بسیار کوچک می‌تواند در یک دقیقه آن را یاد بگیرد.

گام 5: آموزش

model = TinyKeypointNet(num_keypoints=4)
opt = torch.optim.Adam(model.parameters(), lr=3e-3)

for step in range(200):
    batch = [make_synthetic_sample() for _ in range(16)]
    imgs = torch.from_numpy(np.stack([b[0] for b in batch]))
    hms = torch.from_numpy(np.stack([b[1] for b in batch]))
    pred = model(imgs)
    # بزرگ‌نمایی pred به رزولوشن کامل
    pred = F.interpolate(pred, size=hms.shape[-2:], mode="bilinear", align_corners=False)
    loss = F.mse_loss(pred, hms)
    opt.zero_grad(); loss.backward(); opt.step()

کاربرد در عمل

  • MediaPipe Pose — مدل تخمین ژست عملیاتی گوگل؛ ارائه‌شده با محیط‌های اجرای (runtimes) تحت وب (WebGL) و موبایل با تأخیر کمتر از 10 میلی‌ثانیه.
  • MMPose (از OpenMMLab) — پایگاه کد جامع پژوهشی؛ شامل همه‌ی معماری‌های پیشرفته با وزن‌های از‌پیش‌آموزش‌دیده.
  • YOLOv8-pose — سریع‌ترین گزینه برای تخمین ژست چند نفر به‌صورت بلادرنگ تنها با یک گذر رو به جلو.
  • transformers HumanDPT / PoseAnything — رویکردهای نوین بینایی-زبانی برای ژست‌هایی با دایره واژگان باز (هر نوع شیء با هر مجموعه‌ای از نقاط کلیدی).

انتشار در محیط عملیاتی

از این درس خروجی‌های زیر به دست می‌آید:

  • فایل outputs/prompt-pose-stack-picker.md — پرامپتی که با توجه به تأخیر، تعداد افراد و نیاز به حالت 2 بعدی یا 3 بعدی، گزینه‌ی مناسب را از میان MediaPipe ،YOLOv8-pose ،HRNet یا ViTPose انتخاب می‌کند.
  • فایل outputs/skill-heatmap-to-coords.md — مهارتی که روتین تبدیل نقشه حرارتی به مختصات با دقت زیرپیکسل را پیاده می‌کند؛ همان کدی که در تمام مدل‌های عملیاتی ژست به کار می‌رود.

تمرین‌ها

  1. (ساده) مدل کوچک نقاط کلیدی را روی مجموعه داده ساختگی 4 نقطه‌ای آموزش دهید. پس از 200 گام، میانگین خطای L2 میان نقاط پیش‌بینی‌شده و واقعی را گزارش کنید.
  2. (متوسط) اصلاح موقعیت زیرپیکسل را پیاده کنید: بر اساس موقعیت argmax، یک سهمی 1 بعدی در امتداد x و y روی پیکسل‌های همسایه برازش دهید. میزان بهبود دقت را در مقایسه با argmax با مقادیر صحیح گزارش کنید.
  3. (سخت) یک مجموعه داده ساختگی دونفره بسازید که در هر تصویر دو نمونه از الگوی 4 نقطه‌ای وجود داشته باشد. سپس یک پایپ‌لاین پایین به بالا همراه با PAFها آموزش دهید تا مشخص کند هر نقطه کلیدی متعلق به کدام نمونه است، و در نهایت OKS را بسنجید.

اصطلاحات کلیدی

اصطلاح در گفتار روزمره معنای واقعی و دقیق
Keypoint (نقطه کلیدی) «یک لندمارک» نقطه‌ای خاص و مرتب روی یک شیء (مفصل، گوشه، ویژگی ظاهری)
Pose (ژست) «اسکلت» مجموعه‌ای مرتب از نقاط کلیدی متعلق به یک نمونه
Top-down (بالا به پایین) «اول شناسایی کن، بعد ژست بگیر» پایپ‌لاین دومرحله‌ای: آشکارساز فرد + مدل نقاط کلیدی برای هر برش؛ بالاترین دقت
Bottom-up (پایین به بالا) «اول نقاط را پیدا کن، بعد گروه‌بندی کن» پیش‌بینی همه‌ی نقاط در یک گذر + گروه‌بندی؛ زمان اجرا مستقل از تعداد جمعیت
Heatmap (نقشه حرارتی) «هدف گاوسی» تنسور H x W به‌ازای هر نقطه کلیدی با قله‌ای در موقعیت واقعی؛ هدف ایده‌آل رگرسیون
PAF «میدان پیوستگی اندام‌ها» میدان بردار واحد 2 کاناله که جهت اندام‌ها را کدگذاری می‌کند؛ برای گروه‌بندی نقاط کلیدی در نمونه‌ها
OKS «مشابه IoU برای نقاط کلیدی» معیار سنجش شباهت نقاط کلیدی شیء (Object Keypoint Similarity)؛ معیار استاندارد COCO برای ارزیابی ژست
HRNet «شبکه با تفکیک‌پذیری بالا» معماری مرجع و مسلط بالا به پایین؛ حفظ ویژگی‌های با رزولوشن بالا در سراسر شبکه

مطالعه‌ی بیشتر

  • OpenPose (Cao et al., 2017) — روش پایین به بالا با PAFها؛ هنوز هم بهترین متن برای درک این رویکرد است
  • HRNet (Sun et al., 2019) — معماری مرجع بالا به پایین
  • ViTPose (Xu et al., 2022) — استفاده از ViT ساده به‌عنوان ستون فقرات تخمین ژست؛ برترین عملکرد فعلی در بنچمارک‌های متعدد
  • MediaPipe Pose — سیستم عملیاتی بلادرنگ تخمین ژست؛ سریع‌ترین پشته‌ی مستقرشده در سال 2026

خودآزمایی

به سؤال‌ها جواب بدهید تا ببینید چقدر از درس در ذهنتان مانده است.

  1. پیش از درسچرا مدل‌های تخمین ژست به جای مختصات مستقیم (x, y)، نقشه‌های حرارتی را رگرسیون می‌کنند؟
  2. پیش از درستخمین ژست بالا به پایین در برابر پایین به بالا: کدام روش مقیاس‌پذیری بهتری با افزایش تعداد افراد در تصویر دارد و چرا؟
  3. پس از درسمیدان‌های تمایل پاره‌بخش (PAFها) چه هستند؟
  4. پس از درسچرا بهبود زیرپیکسلی (sub-pixel) در اطراف پیکسل argmax، دقت نقاط کلیدی را به طور چشمگیری افزایش می‌دهد؟
  5. پس از درسمعیار OKS (تشابه نقاط کلیدی شیء) در تخمین ژست معادل کدام معیار در تشخیص شیء است؟

سؤالات متداول

چرا در تخمین ژست به جای پیش‌بینی مستقیم مختصات، از نقشه حرارتی استفاده می‌شود؟

چون ساختار لایه‌های کانولوشنی ذاتاً با خروجی‌های دوبعدی و فضایی هماهنگ است و اهداف گاوسی با ایجاد گرادیان ملایم در نزدیکی هدف، پایداری آموزش را بالا می‌برند.

تفاوت اصلی رویکرد بالا به پایین (Top-down) و پایین به بالا (Bottom-up) چیست؟

در رویکرد بالا به پایین ابتدا افراد پیدا شده و سپس نقاط هر شخص جداگانه استخراج می‌شوند که دقت بالاتری دارد؛ اما در رویکرد پایین به بالا تمام نقاط کلیدی در یک گذر شبکه شناسایی و با هم گروه‌بندی می‌شوند که سرعت ثابتی در جمعیت‌های شلوغ دارد.

چگونه می‌توان مختصات را با دقت زیرپیکسل (Sub-pixel) از نقشه حرارتی استخراج کرد؟

با برازش یک سهمی یک‌بعدی در اطراف نقطه بیشینه (argmax) یا محاسبه‌ی لغزش مختصات از طریق تفاضل مقادیر پیکسل‌های همسایه می‌توان به دقتی اعشاری و بالاتر از پیکسل رسید.

ما رو توی گوگل بیشتر ببین

با افزودن نکست ادمین به «منابع ترجیحی» گوگل، درس‌ها و مطالب ما را در بخش اخبار برتر جستجو بیشتر می‌بینید.