CUDA-BEVFusion中,src/common/visualize.cu 源文件的当前部分代码class BEVArtistImplement
主要作用是**将3D点云数据和3D边界框(Bounding Box)投影到2D图像平面,并在图像上进行可视化。
一、src/common/visualize.cu 部分源码
// 定义half5结构体,用于存储5个half类型的值
typedef struct {
half val[5];
} half5;
// 限制函数:将value限制在[amin, amax]范围内
template <typename _T>
static __host__ __device__ _T limit(_T value, _T amin, _T amax) {
return value < amin ? amin : (value > amax ? amax : value);
}
// CUDA核函数:将点云数据投影到图像上并绘制
static __global__ void draw_point_to(unsigned int num, const half5* points, float4* view_port, unsigned char* image,
int image_width, int stride, int image_height) {
unsigned int idx = cuda_linear_index; // 获取当前线程的全局索引
if (idx >= num) return; // 如果索引超出点云数量,直接返回
half5 point = points[idx]; // 获取当前点
float px = point.val[0]; // 点的x坐标
float py = point.val[1]; // 点的y坐标
float pz = point.val[2]; // 点的z坐标
float reflection = point.val[3]; // 反射率(未使用)
float indensity = point.val[4]; // 强度(未使用)
// 获取视口变换矩阵的行
float4 r0 = view_port[0];
float4 r1 = view_port[1];
float4 r2 = view_port[2];
// 将3D点投影到图像平面
float x = px * r0.x + py * r0.y + pz * r0.z + r0.w;
float y = px * r1.x + py * r1.y + pz * r1.z + r1.w;
float w = px * r2.x + py * r2.y + pz * r2.z + r2.w;
if (w <= 0) return; // 如果投影点在相机后方,直接返回
x = x / w; // 归一化x坐标
y = y / w; // 归一化y坐标
// 检查投影点是否在图像范围内
if (x < 0 || x >= image_width || y < 0 || y >= image_height) {
return;
}
int ix = static_cast<int>(x); // 计算图像像素的x坐标
int iy = static_cast<int>(y); // 计算图像像素的y坐标
// 计算点的深度透明度
float alpha = limit((pz + 5.0f) / 8.0f, 0.35f, 1.0f);
unsigned char gray = limit(alpha * 255, 0.0f, 255.0f); // 将透明度转换为灰度值
// 将灰度值写入图像
*(uchar3*)&image[iy * stride + ix * 3] = make_uchar3(gray, gray, gray);
}
// Rodrigues旋转公式:根据旋转角度和旋转轴生成旋转矩阵
static std::vector<nvtype::Float4> rodrigues_rotation(float radian, const std::vector<float>& axis) {
std::vector<nvtype::Float4> output(4); // 输出4x4旋转矩阵
memset(&output[0], 0, output.size() * sizeof(nvtype::Float4)); // 初始化矩阵为0
float nx = axis[0]; // 旋转轴x分量
float ny = axis[1]; // 旋转轴y分量
float nz = axis[2]; // 旋转轴z分量
float cos_val = cos(radian); // 旋转角度的余弦值
float sin_val = sin(radian); // 旋转角度的正弦值
output[3].w = 1; // 设置矩阵的右下角为1
float a = 1 - cos_val; // Rodrigues公式中的系数
float identity[3][3] = {