Phân tích và triển khai YOLO12 cho phát hiện điểm chính và ước tính tư thế cơ thể

Giới thiệu

Trong lĩnh vực thị giác máy tính, phát hiện điểm chính và ước tính tư thế (pose estimation) là một nhiệm vụ quan trọng, liên quan đến việc xác định vị trí của các điểm đặc trưng trên cơ thể người trong một hình ảnh. Các điểm này thường bao gồm các khớp xương, mắt, mũi, và các bộ phận khác. YOLO12, phiên bản mới nhất của chuỗi mô hình YOLO, đã giới thiệu các cải tiến trong kiến trúc, bao gồm cơ chế chú ý (attention mechanism) và các lớp tích hợp hiệu quả, giúp cải thiện độ chính xác và tốc độ xử lý. Bài viết này sẽ hướng dẫn bạn cách sử dụng YOLO12 để phát hiện các điểm chính trên cơ thể và ước tính tư thế, sử dụng bộ dữ liệu COCO Pose.

Cấu trúc của bài viết

  • Phần 1: Cơ sở lý thuyết - Giới thiệu về pose estimation và các điểm chính trên cơ thể.
  • Phần 2: Kiến trúc YOLO12 - Phân tích các cải tiến trong YOLO12, đặc biệt là cơ chế chú ý vùng (Area Attention).
  • Phần 3: Cài đặt và huấn luyện - Hướng dẫn cài đặt môi trường, cấu hình dữ liệu và huấn luyện mô hình.
  • Phần 4: Thực thi và đánh giá - Cách sử dụng mô hình đã huấn luyện để dự đoán và phân tích kết quả.
  • Phần 5: Mở rộng và cải tiến - Các hướng cải tiến mô hình như CBAM và GhostConv.

Phần 1: Cơ sở lý thuyết

Ước tính tư thế là một nhiệm vụ trong thị giác máy tính, liên quan đến việc xác định vị trí của các điểm đặc trưng (gọi là điểm chính hoặc keypoints) trên cơ thể người trong một hình ảnh. Các điểm chính này thường bao gồm các khớp xương, mắt, mũi, và các bộ phận khác. Mô hình ước tính tư thế sẽ trả về một tập hợp các điểm, mỗi điểm có tọa độ 2D hoặc 3D và một độ tin cậy (confidence score).

Bộ dữ liệu COCO Pose chứa 17 điểm chính trên cơ thể, mỗi điểm tương ứng với một bộ phận cụ thể. Dưới đây là danh sách các điểm chính và bộ phận tương ứng:

0: Mũi
1: Mắt trái
2: Mắt phải
3: Tai trái
4: Tai phải
5: Vai trái
6: Vai phải
7: Cẳng tay trái
8: Cẳng tay phải
9: Cổ tay trái
10: Cổ tay phải
11: Hông trái
12: Hông phải
13: Gối trái
14: Gối phải
15: Mắt cá chân trái
16: Mắt cá chân phải

Phần 2: Kiến trúc YOLO12

YOLO12 đã cải tiến kiến trúc so với các phiên bản trước, tập trung vào việc tối ưu hóa hiệu suất và độ chính xác. Một trong những cải tiến chính là việc sử dụng cơ chế chú ý vùng (Area Attention).

Cơ chế chú ý vùng (Area Attention)

Cơ chế chú ý vùng được thiết kế để xử lý các vùng quan tâm lớn mà không làm tăng chi phí tính toán. Nó chia feature map thành các vùng nhỏ hơn, giúp giảm độ phức tạp tính toán từ O(n²) xuống O(n²/2) trong khi vẫn duy trì một trường quan sát lớn.

Lớp A2C2f

Lớp A2C2f là một module tích hợp cơ chế chú ý vùng vào kiến trúc C2f. Dưới đây là một ví dụ về triển khai lớp A2C2f:

import torch
import torch.nn as nn

class A2C2f(nn.Module):
    """
    Module A2C2f tích hợp cơ chế chú ý vùng (Area Attention) để trích xuất đặc trưng.
    """
    def __init__(self, c1, c2, n=1, a2=True, area=1, residual=False, mlp_ratio=2.0, e=0.5, g=1, shortcut=True):
        super().__init__()
        c_ = int(c2 * e)
        assert c_ % 32 == 0, "Kích thước của ABlock phải là bội số của 32."

        self.cv1 = nn.Conv2d(c1, c_, 1, 1)
        self.cv2 = nn.Conv2d((1 + n) * c_, c2, 1)

        self.gamma = nn.Parameter(0.01 * torch.ones(c2), requires_grad=True) if a2 and residual else None
        self.m = nn.ModuleList(
            nn.Sequential(*(ABlock(c_, c_ // 32, mlp_ratio, area) for _ in range(2)))
            if a2
            else C3k(c_, c_, 2, shortcut, g)
            for _ in range(n)
        )

    def forward(self, x):
        y = [self.cv1(x)]
        y.extend(m(y[-1]) for m in self.m)
        y = self.cv2(torch.cat(y, 1))
        if self.gamma is not None:
            return x + self.gamma.view(-1, len(self.gamma), 1, 1) * y
        return y

Phần 3: Cài đặt và huấn luyện

Cài đặt môi trường

Để bắt đầu, bạn cần cài đặt PyTorch và Miniconda. Sau đó, bạn có thể sử dụng các lệnh sau để cài đặt các thư viện cần thiết:

pip install -v -e .

Cấu hình dữ liệu

Bạn cần cấu hình đường dẫn đến bộ dữ liệu COCO Pose trong tệp cấu hình. Dưới đây là ví dụ về tệp cấu hình `my_data.yaml`:

# Đường dẫn đến bộ dữ liệu
path: /đường/dẫn/đến/bộ/dữ/liệu/coco-pose
train: train2017.txt
val: val2017.txt
test: test-dev2017.txt

# Điểm chính
kpt_shape: [17, 3]  # 17 điểm chính, 3 chiều (x, y, visible)
flip_idx: [0, 2, 1, 4, 3, 6, 5, 8, 7, 10, 9, 12, 11, 14, 13, 16, 15]

# Lớp
names:
  0: person

Huấn luyện mô hình

Sử dụng script `train.py` để huấn luyện mô hình. Bạn cần chỉ định đường dẫn đến tệp cấu hình dữ liệu và các tham số huấn luyện khác.

python train.py --data my_data.yaml --cfg yolov12-pose.yaml --weights yolov12n-pose.pt --epochs 100

Phần 4: Thực thi và đánh giá

Dự đoán trên hình ảnh

Sau khi huấn luyện, bạn có thể sử dụng mô hình để dự đoán trên hình ảnh. Dưới đây là một ví dụ về script sử dụng Gradio để tạo giao diện web:

import gradio as gr
import torch
from PIL import Image
from yolov12 import YOLO12Pose

model = YOLO12Pose("runs/yolov12n-pose/weights/best.pt")

def predict(image):
    results = model(image)
    annotated_image = results[0].plot()
    return Image.fromarray(annotated_image[..., ::-1])

iface = gr.Interface(
    fn=predict,
    inputs=gr.Image(type="pil"),
    outputs=gr.Image(type="pil"),
    title="YOLO12 Pose Estimation",
    description="Upload an image to perform pose estimation."
)

iface.launch()

Đánh giá mô hình

Để đánh giá mô hình, bạn có thể sử dụng các chỉ số như mAP (mean Average Precision), Precision, và Recall. Các chỉ số này thường được lưu trong thư mục `runs` sau khi huấn luyện.

Phần 5: Mở rộng và cải tiến

Cải tiến bằng CBAM

CBAM (Convolutional Block Attention Module) là một module chú ý nhẹ, có thể được thêm vào mô hình để cải thiện độ chính xác.

class ChannelAttention(nn.Module):
    def __init__(self, in_channels, reduction=16):
        super().__init__()
        self.avg_pool = nn.AdaptiveAvgPool2d(1)
        self.max_pool = nn.AdaptiveMaxPool2d(1)
        self.fc = nn.Sequential(
            nn.Linear(in_channels, in_channels // reduction, bias=False),
            nn.ReLU(inplace=True),
            nn.Linear(in_channels // reduction, in_channels, bias=False)
        )
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        avg_out = self.fc(self.avg_pool(x).view(x.size(0), -1))
        max_out = self.fc(self.max_pool(x).view(x.size(0), -1))
        out = avg_out + max_out
        return x * self.sigmoid(out).view(x.size(0), -1, 1, 1)

class SpatialAttention(nn.Module):
    def __init__(self, kernel_size=7):
        super().__init__()
        self.conv = nn.Conv2d(2, 1, kernel_size, padding=kernel_size//2, bias=False)
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        avg_out = torch.mean(x, dim=1, keepdim=True)
        max_out, _ = torch.max(x, dim=1, keepdim=True)
        x = torch.cat([avg_out, max_out], dim=1)
        x = self.conv(x)
        return x * self.sigmoid(x)

Cải tiến bằng GhostConv

GhostConv là một phép toán tích chập nhẹ, giúp giảm số lượng tính toán và tham số.

class GhostConv(nn.Module):
    def __init__(self, in_channels, out_channels, kernel_size=1, stride=1, padding=0, ratio=2, dw_kernel_size=3):
        super().__init__()
        self.out_channels = out_channels
        self.primary_channels = out_channels // ratio
        self.ghost_channels = out_channels - self.primary_channels

        self.primary_conv = nn.Conv2d(in_channels, self.primary_channels, kernel_size, stride, padding, bias=False)
        self.ghost_conv = nn.Conv2d(self.primary_channels, self.ghost_channels, dw_kernel_size, 1, dw_kernel_size//2, groups=self.primary_channels, bias=False)

    def forward(self, x):
        primary = self.primary_conv(x)
        ghost = self.ghost_conv(primary)
        return torch.cat([primary, ghost], dim=1)

Thẻ: YOLO12 pose estimation keypoint detection computer vision deep learning

Đăng vào ngày 30 tháng 5 lúc 23:40