图形处理之抽取轮廓

    xiaoxiao2021-03-25  142

    等值面(线)

            抽取轮廓的操作对象是标量数据。其思想是:将数据集中标量值等于某一指定恒量值的部分提取出来。对于3D的数据集而言,产生的是一个等值面;对于2D的数据集而言,产生的是一个等值线。其典型的应用有气象图中的等温线、地形图中的等高线。对于医学数据而言,不同的标量值代表的是人体的不同部分,因而可以分别提取出人的皮肤或骨头。   抽取轮廓的功能是由一个过滤器实现的,如vtkContourFilter 。vtkContourFilter 可以接受任意数据集类型作为输入,因而具有 一般性。使用vtkContourFilter 时,除了需要设置输入数据集外,还需要指定一个或多个用于抽取的标量值。可用如下两种方法进行设置。

    使用方法SetValue()逐个设置抽取值。该方法有个两个参数:第一个参数是抽取值的索引号,表示第几个 抽取值。索引号从0开始计数;第二个参数就是指定的抽取值。使用方法GenerateValues()自动产生一系列抽取值。该方法有三个参数:第一个参数是抽取值的个数,后面两个参数是抽取值的取值范围。例如: vtkSmartPointer<vtkContourFilter> contours = vtkSmartPointer<vtkContourFilter>::New(); contours->GenerateValues(5.0, 0.0, 1.2);

    最终产生的抽取值为0.0, 0.3, 0.6, 0.9和1.0,这是一个等差数列。

    vtkContourFilter生成等值线示例

    CMakeLists.txt文件代码如下:

    CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(Contour) FIND_PACKAGE(VTK REQUIRED) INCLUDE(${VTK_USE_FILE}) ADD_EXECUTABLE(Contour Contour.cpp) TARGET_LINK_LIBRARIES(Contour ${VTK_LIBRARIES})

    Contour.cpp文件代码如下:

    #include <vtkActor.h> #include <vtkCamera.h> #include <vtkCellArray.h> #include <vtkFloatArray.h> #include <vtkPointData.h> #include <vtkPoints.h> #include <vtkPolyData.h> #include <vtkPolyDataMapper.h> #include <vtkRenderWindow.h> #include <vtkRenderer.h> #include <vtkLookupTable.h> #include <vtkContourFilter.h> #include <vtkRenderWindowInteractor.h> #include <vtkProperty.h> #include <vtkSmartPointer.h> int main() { int i; //定义网格的顶点坐标 vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New(); //第1行5个点 points->InsertNextPoint(-2.0, 2.0, 0.0); points->InsertNextPoint(-1.0, 2.0, 0.0); points->InsertNextPoint(0.0, 2.0, 0.0); points->InsertNextPoint(1.0, 2.0, 0.0); points->InsertNextPoint(2.0, 2.0, 0.0); //第2行5个点 points->InsertNextPoint(-2.0, 1.0, 0.0); points->InsertNextPoint(-1.0, 1.0, 0.0); points->InsertNextPoint(0.0, 1.0, 0.0); points->InsertNextPoint(1.0, 1.0, 0.0); points->InsertNextPoint(2.0, 1.0, 0.0); //第3行5个点 points->InsertNextPoint(-2.0, 0.0, 0.0); points->InsertNextPoint(-1.0, 0.0, 0.0); points->InsertNextPoint(0.0, 0.0, 0.0); points->InsertNextPoint(1.0, 0.0, 0.0); points->InsertNextPoint(2.0, 0.0, 0.0); //第4行5个点 points->InsertNextPoint(-2.0, -1.0, 0.0); points->InsertNextPoint(-1.0, -1.0, 0.0); points->InsertNextPoint(0.0, -1.0, 0.0); points->InsertNextPoint(1.0, -1.0, 0.0); points->InsertNextPoint(2.0, -1.0, 0.0); //第5行5个点 points->InsertNextPoint(-2.0, -2.0, 0.0); points->InsertNextPoint(-1.0, -2.0, 0.0); points->InsertNextPoint(0.0, -2.0, 0.0); points->InsertNextPoint(1.0, -2.0, 0.0); points->InsertNextPoint(2.0, -2.0, 0.0); //定义单元,每个顶点建立一个四边形单元,共计个单元 static vtkIdType pts[16][4] = { { 0, 5, 6, 1 }, { 1, 6, 7, 2 }, { 2, 7, 8, 3 }, { 3, 8, 9, 4 }, { 5, 10, 11, 6 }, { 6, 11, 12, 7 }, { 7, 12, 13, 8 }, { 8, 13, 14, 9 }, { 10, 15, 16, 11 }, { 11, 16, 17, 12 }, { 12, 17, 18, 13 }, { 13, 18, 19, 14 }, { 15, 20, 21, 16 }, { 16, 21, 22, 17 }, { 17, 22, 23, 18 }, { 18, 23, 24, 19 } }; //创建对象 vtkSmartPointer<vtkPolyData> pGrid = vtkSmartPointer<vtkPolyData>::New(); vtkSmartPointer<vtkCellArray> polys = vtkSmartPointer<vtkCellArray>::New(); for (i = 0; i < 16; i++) { polys->InsertNextCell(4, pts[i]); } vtkSmartPointer<vtkFloatArray> scalars = vtkSmartPointer<vtkFloatArray>::New(); //第1行 scalars->InsertTuple1(0, 0); scalars->InsertTuple1(1, 1); scalars->InsertTuple1(2, 1); scalars->InsertTuple1(3, 3); scalars->InsertTuple1(4, 2); //第2行 scalars->InsertTuple1(5, 1); scalars->InsertTuple1(6, 3); scalars->InsertTuple1(7, 6); scalars->InsertTuple1(8, 6); scalars->InsertTuple1(9, 3); //第3行 scalars->InsertTuple1(10, 3); scalars->InsertTuple1(11, 7); scalars->InsertTuple1(12, 9); scalars->InsertTuple1(13, 7); scalars->InsertTuple1(14, 3); //第4行 scalars->InsertTuple1(15, 2); scalars->InsertTuple1(16, 7); scalars->InsertTuple1(17, 8); scalars->InsertTuple1(18, 6); scalars->InsertTuple1(19, 2); //第5行 scalars->InsertTuple1(20, 1); scalars->InsertTuple1(21, 2); scalars->InsertTuple1(22, 3); scalars->InsertTuple1(23, 4); scalars->InsertTuple1(24, 3); pGrid->SetPoints(points); pGrid->SetPolys(polys); pGrid->GetPointData()->SetScalars(scalars); //定义颜色映射表 vtkSmartPointer<vtkLookupTable> pColorTable = vtkSmartPointer<vtkLookupTable>::New(); pColorTable->SetHueRange(0.667, 0.887); pColorTable->SetNumberOfColors(255); pColorTable->Build(); vtkSmartPointer<vtkPolyDataMapper> cubeMapper = vtkSmartPointer<vtkPolyDataMapper>::New(); cubeMapper->SetInputData(pGrid); cubeMapper->SetScalarRange(0, 9); cubeMapper->SetLookupTable(pColorTable); vtkSmartPointer<vtkActor> cubeActor = vtkSmartPointer<vtkActor>::New(); cubeActor->SetMapper(cubeMapper); //提取轮廓线 vtkSmartPointer<vtkContourFilter> pContourFilter = vtkSmartPointer<vtkContourFilter>::New(); pContourFilter->SetValue(0, 5.0); pContourFilter->SetInputData(pGrid); pContourFilter->Update(); vtkSmartPointer<vtkPolyDataMapper> pContourMapper = vtkSmartPointer<vtkPolyDataMapper>::New(); pContourMapper->SetInputData(pContourFilter->GetOutput()); pContourMapper->ScalarVisibilityOff(); vtkSmartPointer<vtkActor> pContourActor = vtkSmartPointer<vtkActor>::New(); pContourActor->SetMapper(pContourMapper); pContourActor->GetProperty()->SetColor(1.0, 1.0, 0.0); pContourActor->GetProperty()->SetLineWidth(5.0); vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New(); renderer->AddActor(pContourActor); renderer->AddActor(cubeActor); renderer->SetBackground(1.0, 1.0, 1.0); vtkSmartPointer<vtkRenderWindow> renWin = vtkSmartPointer<vtkRenderWindow>::New(); renWin->SetSize(300, 300); renWin->AddRenderer(renderer); renWin->SetWindowName("vtkContourFilter"); vtkSmartPointer<vtkRenderWindowInteractor> interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New(); interactor->SetRenderWindow(renWin); interactor->Initialize(); interactor->Start(); }

    运行结果

    示例原理

    定义规则网格数据顶点的属性值,示例中设置标量值。确定提取区域的属性值。用提取区域的属性值和每个网格数据的每个单元进行比对,确定其是否在该单元内,如果在该单元内,要用插值的方法确定其和该单元边界的交点,然后继续比对下一个单元,如果不在该单元内,继续比对下一个单元。将各个单元的交点相连成线,即为边界区域。 ##原理示意图:
    转载请注明原文地址: https://ju.6miu.com/read-13913.html

    最新回复(0)