当前位置: 首页 > article >正文

第05章 14 绘制人脸部的PolyData并使用小圆锥体来展现法线

在VTK中,绘制人脸部的PolyData并使用小圆锥体来展现法线是一个常见的任务。这个过程可以通过以下步骤实现:

  1. 读取人脸部的PolyData:可以使用VTK的读取模块读取一个包含人脸部的.vtk.obj文件。
  2. 计算法线:使用VTK的vtkPolyDataNormals类为每个面片(face)或顶点(vertex)计算法线。
  3. 创建小圆锥体:使用vtkConeSource创建小圆锥体。
  4. 生成法线的可视化:使用vtkGlyph3D将小圆锥体与法线关联,并在每个顶点绘制一个圆锥体,方向与法线一致。

下面是一个完整的C++/VTK示例代码,演示如何实现这一过程:


示例代码

#include <vtkSmartPointer.h>
#include <vtkPolyDataReader.h>
#include <vtkPolyDataNormals.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkConeSource.h>
#include <vtkGlyph3D.h>
#include <vtkNamedColors.h>

int main(int argc, char *argv[])
{
    // 检查输入文件
    if (argc < 2)
    {
        std::cerr << "Usage: " << argv[0] << " <FacePolyDataFile>" << std::endl;
        return EXIT_FAILURE;
    }

    // 读取人脸部的PolyData文件
    vtkSmartPointer<vtkPolyDataReader> reader = vtkSmartPointer<vtkPolyDataReader>::New();
    reader->SetFileName(argv[1]);
    reader->Update();

    vtkSmartPointer<vtkPolyData> polyData = reader->GetOutput();

    // 计算法线
    vtkSmartPointer<vtkPolyDataNormals> normals = vtkSmartPointer<vtkPolyDataNormals>::New();
    normals->SetInputData(polyData);
    normals->ComputePointNormalsOn(); // 计算顶点法线
    normals->SplittingOff();         // 不分割面片
    normals->Update();

    // 获取法线
    vtkSmartPointer<vtkPolyData> polyDataWithNormals = normals->GetOutput();

    // 创建小圆锥体源
    vtkSmartPointer<vtkConeSource> coneSource = vtkSmartPointer<vtkConeSource>::New();
    coneSource->SetHeight(0.05); // 圆锥体高度
    coneSource->SetRadius(0.02); // 圆锥体底部半径
    coneSource->SetResolution(20); // 圆锥体的分辨率
    coneSource->Update();

    // 使用Glyph3D将圆锥体与法线关联
    vtkSmartPointer<vtkGlyph3D> glyph3D = vtkSmartPointer<vtkGlyph3D>::New();
    glyph3D->SetInputData(polyDataWithNormals);
    glyph3D->SetSourceConnection(coneSource->GetOutputPort());
    glyph3D->SetVectorModeToUseNormal(); // 使用法线作为方向
    glyph3D->SetScaleFactor(0.5);        // 设置圆锥体的大小
    glyph3D->Update();

    // 创建映射器
    vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    mapper->SetInputConnection(glyph3D->GetOutputPort());

    // 创建演员
    vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
    actor->SetMapper(mapper);

    // 创建渲染器、渲染窗口和交互器
    vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
    vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
    renderWindow->AddRenderer(renderer);
    vtkSmartPointer<vtkRenderWindowInteractor> interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
    interactor->SetRenderWindow(renderWindow);

    // 添加演员到渲染器
    renderer->AddActor(actor);
    renderer->SetBackground(0.1, 0.2, 0.4); // 设置背景颜色

    // 渲染和启动交互
    renderWindow->Render();
    interactor->Start();

    return EXIT_SUCCESS;
}


代码说明

  1. 读取人脸部的PolyData

    • 使用vtkPolyDataReader读取一个包含人脸部的PolyData文件(例如.vtk.obj格式)。
  2. 计算法线

    • 使用vtkPolyDataNormals计算顶点法线,并通过ComputePointNormalsOn()开启顶点法线计算。
  3. 创建小圆锥体

    • 使用vtkConeSource创建一个小圆锥体,设置高度(Height)和底部半径(Radius),并设置分辨率(Resolution)。
  4. 使用Glyph3D生成法线可视化

    • 使用vtkGlyph3D将小圆锥体与法线关联,设置SetVectorModeToUseNormal()以使用法线方向,并通过SetScaleFactor()调整圆锥体的大小。
  5. 创建映射器和演员

    • 使用vtkPolyDataMapper将生成的数据映射到演员,并将演员添加到渲染器中。
  6. 渲染和交互

    • 创建渲染窗口和交互器,并启动渲染循环。

示例输入和输出

输入
  • 一个包含人脸部的.vtk.obj文件。例如,你可以使用一个简单的OBJ文件或VTK文件,其中包含一个人脸的网格数据。
输出
  • 一个窗口,显示人脸部的网格,并在每个顶点绘制一个小圆锥体,圆锥体的方向与该顶点的法线方向一致。

运行示例

编译并运行此代码时,需要提供一个人脸的PolyData文件作为输入。例如:

./FaceNormalsVisualization face.vtk


注意事项

  1. 文件格式:确保输入文件是VTK支持的格式(例如.vtk.obj)。
  2. 圆锥体大小:可以通过调整SetScaleFactor()的值来控制圆锥体的大小。
  3. 法线计算:如果法线方向不正确,可以尝试调整vtkPolyDataNormals的参数,例如反转法线方向。

http://www.kler.cn/a/522082.html

相关文章:

  • WebSocket 详解:全双工通信的实现与应用
  • 05-机器学习-数据标注
  • MV结构下设置Qt表格的代理
  • K8S 快速实战
  • Winform如何取消叉号,减号和放大(两种)
  • 【Linux探索学习】第二十七弹——信号(一):Linux 信号基础详解
  • Go反射指南
  • 爱的魔力转圈圈,基于carsim与simulink模拟仰望u8原地调头
  • DeepSeek-R1 是否才是 “Open” AI?
  • YOLOv11改进,YOLOv11检测头融合DynamicHead,并添加小目标检测层(四头检测),适合目标检测、分割等任务
  • 航空客户价值的数据挖掘与分析(numpy+pandas+matplotlib+scikit-learn)
  • 基于STM32的循迹小车设计与实现
  • torch.tile 手动实现 kron+矩阵乘法
  • MongoDB中常用的几种高可用技术方案及优缺点
  • 基础项目实战——3D赛车(c++)
  • 把本地搭建的hexo博客部署到自己的服务器上
  • 网络工程师 (4)存储系统
  • 21款炫酷烟花合集
  • python selenium 用法教程
  • Warm-Flow新春版:网关直连和流程图重构, 新增Ruoyi-Vue-Plus优秀开源集成案例
  • Python中容器类型的数据(下)
  • Linux 常用命令 - sort 【对文件内容进行排序】
  • (1)SpringBoot入门+彩蛋
  • JavaSE第十一天——集合框架Collection
  • java —— 面向对象(下)
  • 【数据结构】(2)时间、空间复杂度