# 真值可视化脚本说明 ## 概述 本目录包含用于单帧图像真值可视化的脚本,可以实现2D和3D边界框的可视化。 ## 真值读取到可视化的完整流程 ### 1. 数据加载流程(utils/dataloaders3d.py) #### 1.1 标签读取 (`load_label()`) ```python # 标签文件格式(47维数组): # - 列0: class (类别ID) # - 列1-4: x, y, w, h (归一化的2D边界框中心和宽高) # - 列5: score (置信度) # - 列6-8: x3d, y3d, z3d (3D中心点在相机坐标系下的坐标) # - 列9-11: length, height, width (3D框的尺寸) # - 列12: rot_y (偏航角旋转) # - 列13-14: xc, yc (3D框中心投影到2D的归一化坐标) # - 列15: alpha (观测角) # - 列16-23: 前面信息 [x3d, y3d, z3d, alpha, xc, yc, score, visible] # - 列24-31: 后面信息 # - 列32-39: 左面信息 # - 列40-47: 右面信息 ``` 支持三种标签格式: - **2D only (6列)**: 仅包含2D边界框 - **2D+3D simple (18列)**: 针对行人、自行车、骑手,包含基本3D信息 - **2D+3D+faces (50列)**: 针对车辆、三轮车,包含完整的4个面信息 #### 1.2 图像读取 (`load_image()`) ```python # 使用cv2.imread读取BGR格式图像 img = cv2.imread(image_path) # (H, W, 3) BGR ``` #### 1.3 标定参数读取 ```python # 从 camera4.json 读取相机内参 { "focal_u": fx, # x方向焦距 "focal_v": fy, # y方向焦距 "cu": cx, # x方向主点 "cv": cy, # y方向主点 "pitch": pitch, # 相机俯仰角 "distort_coeffs": [] # 畸变系数 } ``` ### 2. 数据预处理流程 #### 2.1 ROI变换(可选) ```python # 计算消失点和裁剪中心 vanish_y = cy - fy * tan(pitch * π/180) crop_center = (oriW/2, vanish_y) # 计算ROI边界 roi_x1 = crop_center_x - roi_width/2 roi_y1 = crop_center_y - roi_height/2 roi_x2 = roi_x1 + roi_width roi_y2 = roi_y1 + roi_height # 裁剪图像 img_roi = img[roi_y1:roi_y2, roi_x1:roi_x2] ``` #### 2.2 标签坐标转换 ```python # 将2D边界框从原始图像坐标转换到ROI坐标 # 1. 归一化xywh -> 绝对xyxy # 2. 平移到ROI相对坐标 # 3. 裁剪到ROI边界内 # 4. 重新归一化 # UV坐标(面中心投影)也需要相应转换 ``` #### 2.3 深度归一化(可选) ```python # 当使用虚拟焦距时,需要缩放z3d深度值 # 只缩放Z坐标,X和Y从UV和Z恢复 scale = virtual_fx / fx_original z3d_normalized = z3d_original * scale # 包括: # - 列7: 整体中心z3d # - 列17: 前面中心z3d # - 列25: 后面中心z3d # - 列33: 左面中心z3d # - 列41: 右面中心z3d ``` ### 3. 可视化流程(test_val_visualize.py) #### 3.1 2D可视化 ```python # 使用 plot_2d_boxes_to_image() 或类似逻辑 # 1. 放大图像(scale_factor=2)获得更清晰的可视化 # 2. 将归一化坐标转换为像素坐标 # 3. 使用Annotator绘制边界框和类别标签 # 4. 添加标签文字(如"2D GT") ``` #### 3.2 3D可视化 **步骤1:解码3D框** (`decode_and_reconstruct_3d_box_from_target()`) ```python # 针对不同类别采用不同策略: # 车辆类(class 0, 13):基于最佳可见面重建 # 1. 遍历4个面(前、后、左、右) # 2. 选择可见且得分最高的面 # 3. 从面中心(u,v,z)反投影得到3D中心 # 4. 使用dimensions和rot_y计算8个3D角点 # 行人类(class 1, 2, 3):基于完整3D框 # 1. 直接使用(x3d, y3d, z3d)作为3D中心 # 2. 使用dimensions和rot_y计算8个3D角点 # 3. 注意:需要将归一化深度转换回原始尺度 # z3d_original = z3d_normalized * depth_scale ``` **步骤2:投影和绘制** (`plot_3d_boxes_from_decoded_targets()`) ```python # 1. 将3D角点投影到2D图像平面 # u = fx * X/Z + cx # v = fy * Y/Z + cy # 2. 绘制3D框的12条边 # 3. 使用不同颜色区分前后面 # 4. 对于车辆类,标记最佳可见面的中心点 ``` #### 3.3 BEV可视化 ```python # 1. 创建空白BEV图像 (draw_bev_blank) # 2. 对每个3D框调用 drawbev() 绘制俯视图 # 3. 使用不同颜色区分真值(绿色)和预测(红色) ``` ### 4. 关键坐标系统 #### 4.1 图像坐标系 - 原点:图像左上角 - x轴:向右 - y轴:向下 - 单位:像素或归一化[0,1] #### 4.2 相机坐标系 - 原点:相机光心 - x轴:向右 - y轴:向下 - z轴:向前(深度方向) - 单位:米 #### 4.3 投影关系 ``` u = fx * X/Z + cx v = fy * Y/Z + cy # 反投影(已知u,v,Z求X,Y): X = (u - cx) * Z / fx Y = (v - cy) * Z / fy ``` ## 使用方法 ### 基本用法(不应用ROI) ```bash python scripts_for_gt/visualize_single_frame.py \ --image /path/to/images/frame_001.jpg \ --label /path/to/labels/frame_001.txt \ --output ./gt_visualization ``` ### 带ROI变换(与训练一致) ```bash python scripts_for_gt/visualize_single_frame.py \ --image /path/to/images/frame_001.jpg \ --label /path/to/labels/frame_001.txt \ --output ./gt_visualization \ --roi 704 352 \ --virtual-fx 500 \ --ori-img-size 1920 1080 ``` ### 参数说明 - `--image`: 图像文件路径(必需) - `--label`: 标签文件路径(必需) - `--output`: 输出目录(默认:./gt_visualization) - `--calib`: 相机标定文件路径(camera4.json),如不提供会自动从图像路径推断 - `--roi`: ROI尺寸(宽 高),如:`--roi 704 352` - `--virtual-fx`: 虚拟焦距,用于深度归一化 - `--ori-img-size`: 原始图像尺寸(宽 高),如不提供则从图像自动获取 ### 输出文件 脚本会在输出目录生成以下文件: - `{filename}_2d_gt.jpg`: 2D边界框可视化 - `{filename}_3d_gt.jpg`: 3D边界框投影可视化 - `{filename}_bev_gt.jpg`: 鸟瞰图(BEV)可视化 - `{filename}_combined.jpg`: 组合可视化(2D + 3D + BEV) ## 示例 假设数据结构如下: ``` /data/ ├── images/ │ └── frame_001.jpg ├── labels/ │ └── frame_001.txt └── calib/ └── L2_calib/ └── camera4.json ``` 运行命令: ```bash python scripts_for_gt/visualize_single_frame.py \ --image /data/images/frame_001.jpg \ --label /data/labels/frame_001.txt \ --output ./output \ --roi 704 352 \ --virtual-fx 500 ``` ## 注意事项 1. **标定文件自动推断**:如果不指定`--calib`,脚本会自动查找与图像路径对应的标定文件(`../calib/L2_calib/camera4.json`) 2. **深度归一化**:当使用`--virtual-fx`时,z3d坐标会被缩放以匹配虚拟焦距,这与训练时的处理一致 3. **坐标系统**: - 输入标签使用归一化坐标[0,1] - 3D坐标使用相机坐标系(米) - 深度归一化后需要在可视化时转换回原始尺度 4. **支持的类别**: - 0: vehicle(车辆)- 使用面策略 - 1: pedestrian(行人)- 使用完整框 - 2: bicycle(自行车)- 使用完整框 - 3: rider(骑手)- 使用完整框 - 13: tricycle(三轮车)- 使用面策略 ## 快速测试 提供了一个自动测试脚本,可以自动从验证集中找到第一个有效样本并进行可视化: ```bash # 使用默认数据集配置 python scripts_for_gt/test_visualization.py # 指定数据集配置 python scripts_for_gt/test_visualization.py --data data/mono3d.yaml --output ./test_output ``` 测试脚本会: 1. 从数据集配置中读取验证集路径 2. 自动查找第一个有标签的样本 3. 分别测试原始图像可视化和ROI变换可视化 4. 生成所有可视化结果到指定目录 ## 批量处理 如果需要批量处理多帧图像,可以使用批量脚本: ```bash python scripts_for_gt/visualize_batch.py \ --image-dir /path/to/images \ --label-dir /path/to/labels \ --output ./batch_output \ --roi 704 352 \ --virtual-fx 500 \ --max-samples 10 ``` 参数说明: - `--image-dir`: 图像目录 - `--label-dir`: 标签目录 - `--output`: 输出目录 - `--calib-dir`: 标定文件目录(可选) - `--roi`: ROI尺寸 - `--virtual-fx`: 虚拟焦距 - `--max-samples`: 最大处理样本数(可选) ## 条件过滤可视化 如果需要从训练集或验证集中筛选特定条件的样本进行可视化,可以使用过滤脚本: ### 示例1: 可视化包含两轮车的样本(空间范围过滤) ```bash # 只可视化两轮车在左右各10米、纵向50米范围内的样本 python scripts_for_gt/visualize_filtered_train.py \ --data data/mono3d.yaml \ --target-class bicycle \ --x-range -10 10 \ --z-range 0 50 \ --max-samples 20 \ --output ./bicycle_samples ``` ### 示例2: 可视化包含行人的样本 ```bash # 可视化前50个包含行人的训练样本 python scripts_for_gt/visualize_filtered_train.py \ --data data/mono3d.yaml \ --target-class pedestrian \ --max-samples 50 \ --output ./pedestrian_samples ``` ### 示例3: 可视化特定空间范围内的车辆 ```bash # 可视化车辆在左右5米、纵向10-30米范围内的样本 python scripts_for_gt/visualize_filtered_train.py \ --data data/mono3d.yaml \ --target-class vehicle \ --x-range -5 5 \ --z-range 10 30 \ --max-samples 30 \ --output ./vehicle_samples ``` ### 过滤参数说明 - `--target-class`: 目标类别(vehicle, pedestrian, bicycle, rider, motorcycle, tricycle) - `--x-range MIN MAX`: X坐标范围(左右方向),单位:米 - `--y-range MIN MAX`: Y坐标范围(上下方向),单位:米 - `--z-range MIN MAX`: Z坐标范围(前后方向/深度),单位:米 - `--min-targets`: 最少目标数量(默认1) - `--max-samples`: 最大可视化样本数 - `--split`: 数据集划分(train或val,默认train) - `--use-roi`: 使用ROI变换 ### 坐标系说明 相机坐标系: - **X轴**: 向右为正(单位:米) - **Y轴**: 向下为正(单位:米) - **Z轴**: 向前为正(深度方向,单位:米) 示例: - `--x-range -10 10`: 左右各10米范围 - `--z-range 0 50`: 前方0到50米范围 - `--y-range -2 1`: 相机水平面上下2米到下方1米范围 ## 脚本说明 本目录包含以下脚本: 1. **visualize_single_frame.py** - 单帧可视化脚本 - 核心功能:读取单帧图像和标签,生成2D、3D和BEV可视化 - 支持ROI变换和深度归一化 2. **visualize_batch.py** - 批量可视化脚本 - 批量处理多帧图像 - 自动匹配图像和标签文件 3. **test_visualization.py** - 快速测试脚本 - 自动查找验证集样本 - 测试不同配置的可视化效果 ## 扩展功能 可以基于此脚本进行扩展: - 添加不同的可视化风格 - 输出3D框参数到文件 - 与预测结果对比 - 统计分析(深度分布、尺寸分布等)