文章目录
- 将 `.ply` 点云或模型数据进行 Elevation 着色并可视化渲染的完整流程
- 🟦 1. **使用 ElevationFilter 给模型上色(根据 Z 值)**
- 🟩 2. **构造 Jet 风格的 Lookup Table(颜色映射表)**
- 🔷 3. **点变为可渲染的 Vertex 图元**
- 🔶 4. **构造映射器,设置颜色 LUT 和标量范围**
- 🟥 5. **创建并设置 Actor**
- ⚙️ 6. **清除旧场景并渲染新模型**
- ✅ 总结整体流程
- 除了Jet 风格的 Lookup Table(颜色映射表)还有哪些常见的渲染风格
- 🎨 1. **Cool to Warm(冷暖色)**
- 🌈 2. **Rainbow / HSV 彩虹色**
- 🌫 3. **Grayscale(灰度)**
- 🌿 4. **Viridis(Matplotlib 默认)**
- 🔳 5. **Blackbody / Thermal / Fire**
- 🟨 6. **Category / Discrete Colors(分类颜色)**
- 📊 7. **Custom 自定义色带**
将 .ply
点云或模型数据进行 Elevation 着色并可视化渲染的完整流程
前置代码 加载ply文件
vtkNew<vtkPLYReader> reader;
reader->SetFileName(filePath.toStdString().c_str());
reader->Update();
polyData = reader->GetOutput();
// 获取包围盒 (Bounds)
double bounds[6];
_poly_data->GetBounds(bounds);
// 计算模型中心
double center[3] = {
(bounds[0] + bounds[1]) / 2.0,
(bounds[2] + bounds[3]) / 2.0,
(bounds[4] + bounds[5]) / 2.0};
// 将整个模型向反方向移动,使其中心点对齐原点
vtkNew<vtkTransform> transform;
transform->Translate(-center[0], -center[1], -center[2]);
🟦 1. 使用 ElevationFilter 给模型上色(根据 Z 值)
vtkNew<vtkElevationFilter> elevationFilter;
elevationFilter->SetInputConnection(transformFilter->GetOutputPort());
elevationFilter->SetLowPoint(0, 0, bounds[4] - center[2]);
elevationFilter->SetHighPoint(0, 0, bounds[5] - center[2]);
elevationFilter->Update();
vtkElevationFilter
会根据模型每个点在 Z 轴方向的位置 生成一个标量值(类似“高度”)。LowPoint
和HighPoint
设置了 Z 轴范围,这里用了bounds[4/5] - center[2]
是因为模型已经被平移到以原点为中心。- 输出数据中每个点都带上了一个“Z 值标量”,用于后续着色。
🟩 2. 构造 Jet 风格的 Lookup Table(颜色映射表)
// Jet 颜色映射(蓝→青→绿→黄→红)非线性 Jet LUT
vtkNew<vtkLookupTable> colorLookupTable;
colorLookupTable->SetNumberOfTableValues(256);
double scalarRange[2];
elevationFilter->GetOutput()->GetScalarRange(scalarRange);
colorLookupTable->SetRange(scalarRange);
// colorLookupTable->SetRange(-50, 50); // 固定范围,确保色差
for (int i = 0; i < 256; ++i)
{
double t = i / 255.0;
// 非线性调整 t,使得颜色中段更密集,末端压缩
double gamma = 0.7; // 越小,中间越突出(类似 CloudCompare),可尝试 0.6 ~ 0.8
t = std::pow(t, gamma);
// Jet 调色映射(与 CloudCompare 相似的分布)
double r = std::clamp(1.5 - std::abs(4.0 * t - 3.0), 0.0, 1.0);
double g = std::clamp(1.5 - std::abs(4.0 * t - 2.0), 0.0, 1.0);
double b = std::clamp(1.5 - std::abs(4.0 * t - 1.0), 0.0, 1.0);
colorLookupTable->SetTableValue(i, r, g, b);
}
colorLookupTable->Build();
- 构造了一个 Jet 风格 的颜色映射(蓝→青→绿→黄→红),类似于 CloudCompare 的配色。
- 使用了
gamma=0.7
进行非线性压缩,使颜色分布更集中在中间(增加色彩层次感)。 - 范围固定为
[-50, 50]
,也就是说,无论模型多高,色差都按这个范围来映射,这是为了防止模型过扁而无法显著看到颜色过渡。
🔷 3. 点变为可渲染的 Vertex 图元
auto vertexGlyphFilter = vtkSmartPointer<vtkVertexGlyphFilter>::New();
vertexGlyphFilter->AddInputData(elevationFilter->GetOutput());
vertexGlyphFilter->Update();
- 给模型添加点拓扑(将点转换为可渲染的
vtkVertex
),如果省略这一段,纯点云将无法显示。
🔶 4. 构造映射器,设置颜色 LUT 和标量范围
auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(vertexGlyphFilter->GetOutputPort());
mapper->SetScalarRange(elevationFilter->GetOutput()->GetScalarRange());
mapper->SetLookupTable(colorLookupTable);
mapper->SetColorModeToMapScalars();
mapper->ScalarVisibilityOn();
mapper->Update();
- 设置输入数据、颜色映射表。
- 使用 ElevationFilter 输出的 Z 值作为“标量值”,根据 LUT 显示颜色。
SetScalarRange(...)
确保 mapper 知道颜色范围如何对应到颜色表中。
🟥 5. 创建并设置 Actor
ply_point_actor_ = vtkSmartPointer<vtkActor>::New();
ply_point_actor_->SetMapper(mapper);
ply_point_actor_->GetProperty()->SetPointSize(point_size_edit_->text().toInt());
- 使用上面的 Mapper 创建可渲染的 Actor。
SetPointSize(...)
设置点大小,读取自 UI 控件(point_size_edit_
),用户可调。
⚙️ 6. 清除旧场景并渲染新模型
renderer_->RemoveAllViewProps(); // 移除旧的内容
renderer_->SetBackground(1.0, 1.0, 1.0); // 设置白色背景
renderer_->AddActor(ply_point_actor_); // 添加新Actor
addCoordinateAxes(); // 添加坐标轴
addBoundingBox(transformFilter->GetOutput()); // 添加包围盒
renderer_->ResetCamera(); // 相机重置
renderWindow_->Render(); // 执行渲染
m_pScene->update(); // 通知 UI 更新(Qt)
- 将新的 actor 放入渲染器中,刷新场景。
- 添加坐标轴与包围盒用于辅助显示。
- 调用
ResetCamera()
让摄像头自动对准场景。 - 渲染窗口刷新,并通过 Qt 通知界面刷新。
✅ 总结整体流程
步骤 | 说明 |
---|---|
① ElevationFilter | 为每个点生成 Z 值标量 |
② LookupTable | 创建 Jet 风格 LUT |
③ VertexGlyphFilter | 点 → vtkVertex,确保可渲染 |
④ Mapper | 设置映射、颜色 LUT、标量范围 |
⑤ Actor | 设置点大小、构建可视化对象 |
⑥ Renderer | 清除旧内容、添加新 Actor、刷新界面 |
除了Jet 风格的 Lookup Table(颜色映射表)还有哪些常见的渲染风格
除了 Jet 风格(蓝→青→绿→黄→红)之外,VTK 和三维可视化中常见的颜色映射表(Lookup Table, LUT)还有以下几类,每种适合不同的可视化目的:
🎨 1. Cool to Warm(冷暖色)
- 🌊🔶 蓝 → 白 → 红(低值冷色,高值暖色)
- 用途:强调数据中“高/低”对比(如温度、压力)
- VTK 内置:
vtkColorTransferFunction::SetColorSpaceToDiverging()
+ 两端色设置
🌈 2. Rainbow / HSV 彩虹色
- 🟥🟧🟨🟩🟦🟪 类似色相环,覆盖整个色谱
- 缺点:视觉不连续、对人眼不友好(不推荐用于严肃科学展示)
- 用途:可用于展示离散类别或艺术可视化
- VTK:
vtkLookupTable::SetHueRange(0.0, 1.0);
🌫 3. Grayscale(灰度)
-
⚫→⚪ 从黑到白
-
用途:医学图像、形状对比、打印友好
-
设置方式:
lut->SetTableValue(i, t, t, t); // R=G=B
🌿 4. Viridis(Matplotlib 默认)
- 🌌🟢💛 深紫 → 蓝 → 青绿 → 黄绿
- 优点:感知均匀,对色盲友好
- 用途:科学绘图标准(推荐)
- 在 VTK 中可手动构造,或从 matplotlib colormap 读取 RGB 值
🔳 5. Blackbody / Thermal / Fire
- 🔴🟡⚪ 类似热红外风格(黑→红→黄→白)
- 用于:热成像、能量密度可视化
- VTK:
vtkColorTransferFunction::SetColorSpaceToRGB()
,然后插值这些颜色
🟨 6. Category / Discrete Colors(分类颜色)
- 固定 N 种颜色(适合整数 label 或分类)
- 不能用连续 ScalarRange
- 通常和
vtkUnsignedCharArray
配合使用 - 示例:红绿蓝紫等分配不同类别
📊 7. Custom 自定义色带
-
手动设置几个关键色,插值形成 LUT
-
用法灵活:地形图、高度图、材质图等
-
例子:
lut->SetTableValue(0, 0.0, 0.0, 0.5); // 深蓝 lut->SetTableValue(128, 0.0, 1.0, 0.0); // 绿色 lut->SetTableValue(255, 1.0, 1.0, 0.0); // 黄色