1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
| import numpy as np import torch import torch.nn as nn from typing import Tuple
class SimulationDataGenerator: """ 阶段1:仿真数据生成 使用 SMPL-X 统计人体模型生成合成深度+IR 图像 流程: 1. 采样姿态参数 Z (15关节 × 3D) 2. 采样体型参数 s (身高/体重/比例) 3. 通过 SMPL-X 生成人体网格 4. 渲染深度图和 IR 图 """ def __init__(self, num_joints: int = 15): self.num_joints = num_joints self.kinematic_tree = { 'pelvis': 0, 'abdomen': 1, 'thorax': 2, 'neck': 3, 'head': 4, 'left_hip': 5, 'left_knee': 6, 'right_hip': 7, 'right_knee': 8, 'left_shoulder': 9, 'left_elbow': 10, 'left_wrist': 11, 'right_shoulder': 12, 'right_elbow': 13, 'right_wrist': 14 } self.posture_ranges = { 'normal_driving': {'neck_pitch': (-10, 10), 'torso_pitch': (-5, 15)}, 'leaning_forward': {'neck_pitch': (20, 45), 'torso_pitch': (20, 40)}, 'leaning_left': {'neck_yaw': (-30, -15), 'torso_roll': (-20, -10)}, 'leaning_right': {'neck_yaw': (15, 30), 'torso_roll': (10, 20)}, 'feet_up': {'hip_flexion': (60, 90), 'knee_flexion': (-30, 0)}, 'sleeping': {'neck_pitch': (30, 60), 'torso_roll': (-15, 15)} } def generate_sample(self) -> Tuple[np.ndarray, np.ndarray, np.ndarray]: """ 生成一个仿真样本 Returns: depth_image: (H, W) 深度图 ir_image: (H, W) 红外图 posture_3d: (15, 3) 3D 关节坐标 """ posture_type = np.random.choice(list(self.posture_ranges.keys())) ranges = self.posture_ranges[posture_type] angles = {} for joint, (low, high) in ranges.items(): angles[joint] = np.random.uniform(low, high) height = np.random.uniform(1.5, 1.9) weight = np.random.uniform(50, 100) posture_3d = self._forward_kinematics(angles, height) H, W = 480, 640 depth_image = self._render_depth(posture_3d, H, W) ir_image = self._render_ir(posture_3d, H, W) return depth_image, ir_image, posture_3d def _forward_kinematics(self, angles: dict, height: float) -> np.ndarray: """简化版前向运动学""" posture = np.zeros((15, 3)) posture[0] = [0, 0, 0.4 * height] posture[1] = posture[0] + [0, 0, 0.15 * height] posture[2] = posture[1] + [0, 0, 0.15 * height] neck_pitch = np.radians(angles.get('neck_pitch', 0)) posture[3] = posture[2] + [0, 0.05 * height * np.sin(neck_pitch), 0.08 * height * np.cos(neck_pitch)] posture[4] = posture[3] + [0, 0.05 * height * np.sin(neck_pitch), 0.12 * height * np.cos(neck_pitch)] posture[5] = posture[0] + [0.08, 0, -0.05] posture[6] = posture[5] + [0, 0, -0.2] posture[7] = posture[0] + [-0.08, 0, -0.05] posture[8] = posture[7] + [0, 0, -0.2] posture[9] = posture[2] + [0.15, 0, 0] posture[10] = posture[9] + [0.1, 0, -0.1] posture[11] = posture[10] + [0.1, 0, -0.1] posture[12] = posture[2] + [-0.15, 0, 0] posture[13] = posture[12] + [-0.1, 0, -0.1] posture[14] = posture[13] + [-0.1, 0, -0.1] return posture def _render_depth(self, posture: np.ndarray, H: int, W: int) -> np.ndarray: """模拟深度图渲染""" depth = np.full((H, W), 5.0) for joint in posture: x = int(W/2 + joint[0] * 100) y = int(H/2 - joint[2] * 100) z = joint[1] + 1.0 if 0 <= x < W and 0 <= y < H: cv2_circle(depth, (x, y), 15, z, -1) return depth def _render_ir(self, posture: np.ndarray, H: int, W: int) -> np.ndarray: """模拟 IR 图渲染""" ir = np.zeros((H, W), dtype=np.float32) for joint in posture: x = int(W/2 + joint[0] * 100) y = int(H/2 - joint[2] * 100) if 0 <= x < W and 0 <= y < H: ir[y-10:y+10, x-10:x+10] = 0.8 return ir
def cv2_circle(img, center, radius, color, thickness): """简化版圆形绘制""" H, W = img.shape[:2] cx, cy = center for y in range(max(0, cy-radius), min(H, cy+radius)): for x in range(max(0, cx-radius), min(W, cx+radius)): if (x-cx)**2 + (y-cy)**2 <= radius**2: img[y, x] = color
|