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 144 145 146 147
| import numpy as np from typing import List, Dict
class PseudoLabelPipeline: """ 多视角车内标注伪标签生成管道 论文: Gorelik et al., 2026 流程: 2D检测 → 3D姿态估计 → 跨视角追踪 → 3D包围盒提取 """ def __init__(self, camera_intrinsics: List[dict], extrinsics: List[np.ndarray]): """ Args: camera_intrinsics: 各相机内参列表 extrinsics: 各相机外参列表 (4x4 变换矩阵) """ self.num_cameras = len(camera_intrinsics) self.intrinsics = camera_intrinsics self.extrinsics = extrinsics def process_frame( self, rgb_images: List[np.ndarray], depth_images: List[np.ndarray], lidar_points: np.ndarray ) -> Dict: """ 处理一帧多视角数据 Args: rgb_images: 4个相机的RGB图, shape=(4, H, W, 3) depth_images: 4个相机的深度图, shape=(4, H, W) lidar_points: LiDAR点云, shape=(N, 3) Returns: annotations: 标注结果 """ results = {} detections_2d = [] for i in range(self.num_cameras): dets = self._detect_2d(rgb_images[i]) detections_2d.append(dets) poses_3d = [] for i in range(self.num_cameras): pose = self._estimate_3d_pose( rgb_images[i], depth_images[i], detections_2d[i] ) poses_3d.append(pose) tracks = self._cross_view_track(detections_2d, poses_3d) boxes_3d = self._extract_3d_bbox(poses_3d, tracks, lidar_points) results['detections_2d'] = detections_2d results['poses_3d'] = poses_3d results['tracks'] = tracks results['boxes_3d'] = boxes_3d return results def _detect_2d(self, rgb: np.ndarray) -> list: """2D人员检测 (模拟YOLO)""" return [{'bbox': [100, 200, 150, 400], 'score': 0.95}] def _estimate_3d_pose(self, rgb, depth, detections): """单视角3D姿态估计""" poses = [] for det in detections: pose_3d = self._depth_to_3d(depth, det['bbox']) poses.append(pose_3d) return poses def _depth_to_3d(self, depth, bbox): """深度图 → 3D坐标""" h, w = depth.shape cx, cy = w // 2, h // 2 fx = fy = 615.0 x1, y1, x2, y2 = bbox center_u = (x1 + x2) // 2 center_v = (y1 + y2) // 2 z = depth[center_v, center_x] x = (center_u - cx) * z / fx y = (center_v - cy) * z / fy return {'center_3d': [x, y, z], 'confidence': 0.9} def _cross_view_track(self, detections, poses): """跨视角追踪关联""" tracks = [] for i in range(len(detections)): for j in range(i+1, len(detections)): if poses[i] and poses[j]: dist = np.linalg.norm( np.array(poses[i][0]['center_3d']) - np.array(poses[j][0]['center_3d']) ) if dist < 500: tracks.append({'view_a': i, 'view_b': j, 'dist': dist}) return tracks def _extract_3d_bbox(self, poses, tracks, lidar): """从姿态和LiDAR提取3D包围盒""" boxes = [] for pose_list in poses: for pose in pose_list: center = pose['center_3d'] w, h, l = 600, 1700, 400 box = { 'center': center, 'dimensions': [w, h, l], 'orientation': [0, 0, 0] } boxes.append(box) return boxes
if __name__ == "__main__": intrinsics = [{'fx': 615, 'fy': 615, 'cx': 320, 'cy': 240}] * 4 extrinsics = [np.eye(4)] * 4 pipeline = PseudoLabelPipeline(intrinsics, extrinsics) rgb = np.random.randint(0, 255, (4, 480, 640, 3), dtype=np.uint8) depth = np.random.randint(500, 2000, (4, 480, 640), dtype=np.uint16) lidar = np.random.randn(10000, 3) result = pipeline.process_frame(rgb, depth, lidar) print(f"检测到的3D包围盒: {len(result['boxes_3d'])}")
|