Files
yolov26_3d/tools/scripts_for_gt/visualization/README.md

379 lines
10 KiB
Markdown
Raw Normal View History

2026-06-24 09:35:46 +08:00
# 真值可视化脚本说明
## 概述
本目录包含用于单帧图像真值可视化的脚本可以实现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框参数到文件
- 与预测结果对比
- 统计分析(深度分布、尺寸分布等)