手把手教你用Python处理LSP人体姿态数据集(附可视化代码)

在计算机视觉领域,人体姿态估计是一个热门研究方向,而高质量的数据集是算法开发的基础。Leeds Sports Pose(LSP)数据集作为早期经典的人体姿态标注数据集,至今仍被广泛用于学术研究和算法验证。但对于刚接触该领域的新手来说,面对原始的 .mat 文件和一堆图片,往往会感到无从下手。本文将带你从零开始,用Python一步步解析LSP数据集,并实现关键点可视化。

1. 环境准备与数据加载

在开始处理LSP数据集前,我们需要搭建合适的Python环境。推荐使用Anaconda创建虚拟环境,避免包版本冲突:

conda create -n lsp_processing python=3.8
conda activate lsp_processing

安装必要的依赖库:

pip install numpy matplotlib opencv-python scipy

LSP数据集通常包含以下文件结构:

  • images/ :原始运动图像(2000张)
  • joints.mat :MATLAB格式的关节点标注文件
  • visualized/ :已标注的可视化图像(可选参考)

提示:下载数据集后,建议保持原始目录结构不变,方便后续处理。

2. 解析MATLAB格式的标注文件

LSP数据集的核心标注信息存储在 joints.mat 文件中,这是一个MATLAB格式的二进制文件。Python中可以使用 scipy.io 模块来加载:

import scipy.io

def load_lsp_mat(mat_path):
    """加载LSP标注的.mat文件"""
    mat_data = scipy.io.loadmat(mat_path)
    joints = mat_data['joints']  # 获取关节点数据
    return joints

joints 是一个3×14×2000的numpy数组,其中:

  • 第一维(3)表示:[x坐标, y坐标, 可见性]
  • 第二维(14)对应14个关节点
  • 第三维(2000)对应2000张图片

14个关节点的顺序如下:

索引 关节点名称 索引 关节点名称
0 Right ankle 7 Right shoulder
1 Right knee 8 Left shoulder
2 Right hip 9 Left elbow
3 Left hip 10 Left wrist
4 Left knee 11 Neck
5 Left ankle 12 Head top
6 Right wrist

3. 数据预处理与坐标转换

原始标注数据可能需要一些预处理才能用于实际应用。常见的处理包括:

  1. 坐标归一化 :将像素坐标转换为相对坐标
  2. 可见性过滤 :根据可见性标志过滤不可见关节点
  3. 镜像增强 :通过左右翻转生成更多训练样本

以下是坐标归一化的示例代码:

def normalize_joints(joints, img_width, img_height):
    """将关节点坐标归一化到[0,1]范围"""
    normalized = joints.copy()
    normalized[0, :, :] /= img_width   # x坐标归一化
    normalized[1, :, :] /= img_height  # y坐标归一化
    return normalized

注意:LSP数据集的图像尺寸不一,需要根据每张图片的实际尺寸分别处理。

4. 可视化关节点与骨架连接

可视化是理解数据集的关键步骤。我们可以使用OpenCV和Matplotlib来绘制关节点和骨架:

import cv2
import matplotlib.pyplot as plt

def visualize_pose(image_path, joints, save_path=None):
    """可视化单张图片的关节点"""
    img = cv2.imread(image_path)
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    
    # 关节点连接关系(起点索引,终点索引)
    skeleton = [
        (0, 1), (1, 2), (2, 3), (3, 4), (4, 5),  # 右腿到左腿
        (6, 7), (7, 8), (8, 11),                 # 右手到颈部
        (9, 10), (10, 11),                       # 左手到颈部
        (11, 12)                                 # 颈部到头顶
    ]
    
    # 绘制骨架连接
    for (i, j) in skeleton:
        if joints[2, i] > 0 and joints[2, j] > 0:  # 只绘制可见关节点
            x1, y1 = joints[0, i], joints[1, i]
            x2, y2 = joints[0, j], joints[1, j]
            cv2.line(img, (int(x1), int(y1)), (int(x2), int(y2)), (255, 0, 0), 2)
    
    # 绘制关节点
    for i in range(joints.shape[1]):
        if joints[2, i] > 0:
            x, y = joints[0, i], joints[1, i]
            cv2.circle(img, (int(x), int(y)), 3, (0, 0, 255), -1)
    
    plt.figure(figsize=(10, 10))
    plt.imshow(img)
    plt.axis('off')
    if save_path:
        plt.savefig(save_path, bbox_inches='tight')
    plt.show()

5. 批量处理与数据增强实战

实际项目中,我们通常需要批量处理整个数据集。下面是一个完整的处理流程示例:

import os
from tqdm import tqdm

def process_lsp_dataset(data_dir, output_dir):
    """批量处理LSP数据集"""
    mat_path = os.path.join(data_dir, 'joints.mat')
    images_dir = os.path.join(data_dir, 'images')
    vis_dir = os.path.join(output_dir, 'visualizations')
    
    os.makedirs(vis_dir, exist_ok=True)
    
    joints = load_lsp_mat(mat_path)
    image_files = sorted(os.listdir(images_dir))
    
    for idx in tqdm(range(len(image_files))):
        img_path = os.path.join(images_dir, image_files[idx])
        img = cv2.imread(img_path)
        h, w = img.shape[:2]
        
        # 获取当前图片的关节点
        current_joints = joints[:, :, idx]
        
        # 可视化并保存
        vis_path = os.path.join(vis_dir, f'vis_{image_files[idx]}')
        visualize_pose(img_path, current_joints, vis_path)

为了提高数据利用率,可以考虑以下增强技术:

  1. 随机旋转 :小幅旋转图片和关节点
  2. 随机缩放 :改变图片尺寸
  3. 颜色抖动 :调整亮度、对比度
  4. 水平翻转 :交换左右关节点
def augment_pose(image, joints):
    """数据增强示例:水平翻转"""
    flipped_img = cv2.flip(image, 1)
    flipped_joints = joints.copy()
    
    # 交换左右关节点
    left_indices = [3, 4, 5, 8, 9, 10]  # 左半身关节点索引
    right_indices = [0, 1, 2, 7, 6]     # 右半身关节点索引
    
    # 更新x坐标(镜像)
    flipped_joints[0, :] = image.shape[1] - joints[0, :]
    
    # 交换左右关节点位置
    for left, right in zip(left_indices, right_indices):
        flipped_joints[:, [left, right]] = flipped_joints[:, [right, left]]
    
    return flipped_img, flipped_joints

6. 实际应用中的注意事项

在使用LSP数据集进行模型训练时,有几个关键点需要注意:

  • 数据分布 :LSP主要包含运动场景,可能不适用于其他姿态
  • 标注质量 :部分标注可能存在误差,建议可视化检查
  • 评估协议 :论文中常用的PCKh@0.5指标
  • 与其他数据集的结合 :可以考虑与MPII等数据集联合训练

对于想进一步探索的开发者,可以尝试:

  1. 实现更复杂的数据增强策略
  2. 将LSP转换为COCO格式以便使用现有工具链
  3. 开发基于LSP的基准测试程序
  4. 研究跨数据集的迁移学习
def convert_to_coco_format(joints, image_info):
    """将LSP格式转换为COCO格式的示例"""
    coco_keypoints = []
    # COCO关键点顺序与LSP不同,需要重新映射
    # 这里只是示例,实际转换需要更详细的处理
    return coco_keypoints

处理这类数据集时,最常遇到的坑是坐标系的转换问题。特别是在结合不同库时(如OpenCV和Matplotlib的坐标系差异),需要格外小心。另一个常见问题是内存管理,当处理大量高分辨率图像时,合理的批处理策略至关重要。

更多推荐