zoukankan      html  css  js  c++  java
  • VTK 图形基本操作进阶_网格平滑(点云的曲面重建技术)

    1.网格平滑

    现代扫描技术的发展使得获取点云数据不再困难,通过曲线重建技术可以获取表面网格来表示各种复杂的实体。但是点云数据中往往存在噪声,这样得到的重建网格通常都需要进行平滑处理。
    拉普拉斯平滑是一种常用的网格平滑算法。该方法的原理比较简单,如下图所示:
    将每个点用其邻域点的中心来代替。通过不断地迭代,可以得到较为光滑的网格。
    VTK中,VTKSmoothPolyDataFilter类实现了网格的拉普拉斯平滑算法,使用方法如下:
     1 #include <vtkAutoInit.h>
     2 VTK_MODULE_INIT(vtkRenderingOpenGL);
     3 VTK_MODULE_INIT(vtkInteractionStyle);
     4 VTK_MODULE_INIT(vtkRenderingFreeType);
     5  
     6 #include <vtkSmartPointer.h>
     7 #include <vtkPolyDataReader.h>
     8 #include <vtkSmoothPolyDataFilter.h>
     9 #include <vtkPolyDataMapper.h>
    10 #include <vtkActor.h>
    11 #include <vtkRenderer.h>
    12 #include <vtkRenderWindow.h>
    13 #include <vtkRenderWindowInteractor.h>
    14 int main()
    15 {
    16     vtkSmartPointer<vtkPolyDataReader> reader =
    17         vtkSmartPointer<vtkPolyDataReader>::New();
    18     reader->SetFileName("fran_cut.vtk");
    19     reader->Update();
    20  
    21     vtkSmartPointer<vtkSmoothPolyDataFilter> smoothFilter =
    22         vtkSmartPointer<vtkSmoothPolyDataFilter>::New();
    23     smoothFilter->SetInputConnection(reader->GetOutputPort());
    24     smoothFilter->SetNumberOfIterations(100);
    25     smoothFilter->Update();
    26     /
    27     vtkSmartPointer<vtkPolyDataMapper> inputMapper =
    28         vtkSmartPointer<vtkPolyDataMapper>::New();
    29     inputMapper->SetInputConnection(reader->GetOutputPort());
    30     vtkSmartPointer<vtkActor> inputActor =
    31         vtkSmartPointer<vtkActor>::New();
    32     inputActor->SetMapper(inputMapper);
    33  
    34     vtkSmartPointer<vtkPolyDataMapper> smoothedMapper =
    35         vtkSmartPointer<vtkPolyDataMapper>::New();
    36     smoothedMapper->SetInputConnection(smoothFilter->GetOutputPort());
    37     vtkSmartPointer<vtkActor> smoothedActor =
    38         vtkSmartPointer<vtkActor>::New();
    39     smoothedActor->SetMapper(smoothedMapper);
    40     /
    41     double leftViewport[4] = { 0.0, 0.0, 0.5, 1.0 };
    42     double rightViewport[4] = { 0.5, 0.0, 1.0, 1.0 };
    43  
    44     vtkSmartPointer<vtkRenderer> leftRenderer =
    45         vtkSmartPointer<vtkRenderer>::New();
    46     leftRenderer->SetViewport(leftViewport);
    47     leftRenderer->AddActor(inputActor);
    48     leftRenderer->SetBackground(1, 0, 0);
    49     leftRenderer->ResetCamera();
    50  
    51     vtkSmartPointer<vtkRenderer> rightRenderer =
    52         vtkSmartPointer<vtkRenderer>::New();
    53     rightRenderer->SetViewport(rightViewport);
    54     rightRenderer->AddActor(smoothedActor);
    55     rightRenderer->SetBackground(0, 0, 0);
    56     rightRenderer->ResetCamera();
    57     /
    58     vtkSmartPointer<vtkRenderWindow> rw =
    59         vtkSmartPointer<vtkRenderWindow>::New();
    60     rw->AddRenderer(leftRenderer);
    61     rw->AddRenderer(rightRenderer);
    62     rw->SetSize(640, 320);
    63     rw->SetWindowName("PolyData Grid Smooth By LapLasian");
    64  
    65     vtkSmartPointer<vtkRenderWindowInteractor> rwi =
    66         vtkSmartPointer<vtkRenderWindowInteractor>::New();
    67     rwi->SetRenderWindow(rw);
    68     rwi->Initialize();
    69     rwi->Start();
    70     return 0;
    71 }
    vtkSmoothPolyDataFilter::SetNumberOfIterations()控制平滑次数,次数越多平滑的越厉害。200次的平滑效果如下图所示:
    左图为原始模型,右图为平滑后模型。从图中可以看出,经过200次Laplace平滑后,模型变得相当的光滑,但是在平滑的同事也损失了一些细节信息。
    其实在该类中还有多个变量来控制平滑过程,利用这些变量在一定程度上可以控制细节的损失。
    BoundarySmoothing:控制是否对边界点平滑。这里需要理解边界点的概念,在一个网格模型中,一条边只被一个单元包含那么这条边就是边界边,而边界边上的点则为边界点。如果一个模型中含有边界边,则说明该模型不是封闭的,正如图中的一样。
    FeatureEdgeSmoothing:控制是否对特征边上的点进行平滑。如果一条边被两个邻近的多边形共用,若两个多边形法向量的夹角(特征角)大于定义的阈值,则说明该边为一条特征边。因此,FeatureEdgeSmoothing设置开始时,需要调用SetFeatureAngle()函数设置特征角的阈值。具体如图所示:
    特征角越大,说明改边越尖锐。特征边/角往往表达模型的细节,平滑过程中最好不要进行处理,以保护细节不受损伤。
    虽然通过特征边平滑设置可以降低一部分细节损失,但并不能完全避免,且随着laplace平滑的不断迭代,模型会逐渐向网格的中心收缩。所以,vtkWindowSincPolyDataFilter是一种更好的选择,该算法采用窗口Sinc函数实现网格平滑,能够最小程度地避免收缩,vtkWindowSincPolyDataFilter的用法和VTKSmoothPolyDataFilter用法完全一致。
    1 vtkSmartPointer<vtkWindowedSincPolyDataFilter> wndSincSmoothFilter =
    2         vtkSmartPointer<vtkWindowedSincPolyDataFilter>::New();
    3     wndSincSmoothFilter->SetInputConnection(reader->GetOutputPort());
    4     wndSincSmoothFilter->SetNumberOfIterations(10);
    5     wndSincSmoothFilter->Update();
    算法的输出结果如下所示:
  • 相关阅读:
    在Android中通过导入静态数据库来提高应用第一次的启动速度
    《sqlite权威指南》读书笔记 (一)
    Android APK反编译详解(附图)
    Android如何防止apk程序被反编译
    PopupWindow 学习总结
    Android开源框架Afinal第一篇——揭开圣女的面纱
    教程] 《开源框架-Afinal》之FinalHttp 01一步一脚
    android 下改变默认的checkbox的 选中 和被选中 图片
    Android设置RadioButton在文字的右边
    Android Selector 与 Shape 基本用法
  • 原文地址:https://www.cnblogs.com/ybqjymy/p/14241824.html
Copyright © 2011-2022 走看看