VTK——使用包围盒切割医学图像

VTK 库

vtkDICOMImageReader:专门用于读取医学图像格式 DICOM 的类。DICOM(Digital Imaging and Communications in Medicine)是医学图像和信息的标准。

vtkImageGaussianSmooth:用于图像的高斯平滑处理,主要用于去噪和边缘模糊。

vtkMarchingCubes:Marching Cubes 算法用于从 3D 体积数据生成表面。这在医学成像中非常有用,可以用来生成器官、骨骼等结构的 3D 模型。

vtkStripper:用于优化网格数据,提高渲染速度。

vtkClipPolyData:多边形裁剪,通常用于去除不需要的部分或者进行 ROI(Region of Interest)分析。

vtkPolyDataMapper 和 vtkActor:这两个类用于设置渲染管线。Mapper 负责将数据映射为图形,而 Actor 则是场景中的图形对象。

vtkRenderer, vtkRenderWindow, vtkRenderWindowInteractor:这些组成部分用于创建渲染窗口和交互。

vtkBoxWidget:一个交互式的 3D 窗口小部件,通常用于裁剪或标注 3D 对象。

void test(QString path)
{
    vtkSmartPointer< vtkDICOMImageReader >reader =
        vtkSmartPointer< vtkDICOMImageReader >::New();
    reader->SetDataByteOrderToLittleEndian();
    reader->SetDirectoryName(""); //设置读取路径
    reader->SetDataSpacing(1.0, 1.0, 1.0); //设置每个体素的大小
    reader->Update();

    //对图像数据进行光滑处理
    vtkSmartPointer<vtkImageGaussianSmooth> gaussianSmoothFilter = vtkSmartPointer<vtkImageGaussianSmooth>::New();
    gaussianSmoothFilter->SetInputConnection(reader->GetOutputPort());
    gaussianSmoothFilter->SetDimensionality(3); //图片维数
    gaussianSmoothFilter->SetRadiusFactor(5); //半径因子决定了高斯核在被限制为零之前将走多远,默认为1.5/1.5/1.5
    gaussianSmoothFilter->SetStandardDeviation(1); //像素标准差,值越大越平滑,也越模糊,默认2/2/2
    gaussianSmoothFilter->Update(); //这是添加的图像平滑处理,高斯平滑

    vtkSmartPointer< vtkMarchingCubes > boneExtractor = vtkSmartPointer< vtkMarchingCubes >::New();
    boneExtractor->SetInputConnection(gaussianSmoothFilter->GetOutputPort());
    boneExtractor->SetValue(0, 250); //设置提取的等值信息
    boneExtractor->Update();

    double bounds[6];
    boneExtractor->GetOutput()->GetBounds(bounds); // 获取图像数据的边界
    // 计算中心和大小
    double center[3], halfSize[3];
    for (int i = 0; i < 3; i++) {
        center[i] = (bounds[i * 2] + bounds[i * 2 + 1]) / 2.0;
        halfSize[i] = (bounds[i * 2 + 1] - bounds[i * 2]) / 4.0; // 二分之一的大小
    }

    //剔除旧的或废除的数据单元,提高绘制速度(可略去这一步)
    vtkSmartPointer< vtkStripper > boneStripper = vtkSmartPointer< vtkStripper >::New(); //三角带连接
    boneStripper->SetInputConnection(boneExtractor->GetOutputPort());
    boneStripper->Update();

    vtkSmartPointer<vtkClipPolyData> clipper = vtkSmartPointer<vtkClipPolyData>::New();
    clipper->SetInputConnection(boneStripper->GetOutputPort());

    vtkSmartPointer< vtkPolyDataMapper > boneMapper = vtkSmartPointer< vtkPolyDataMapper >::New();
    boneMapper->SetInputData(clipper->GetOutput());
    boneMapper->ScalarVisibilityOff();

    vtkSmartPointer< vtkActor > bone = vtkSmartPointer< vtkActor >::New();
    bone->SetMapper(boneMapper);
    bone->SetMapper(boneMapper);

    bone->GetProperty()->SetDiffuseColor(1.0, 1.0, 1.0);
    bone->GetProperty()->SetSpecular(0.3);
    bone->GetProperty()->SetSpecularPower(20);

    bone->GetProperty()->SetOpacity(1.0);//透明度;

    bone->GetProperty()->SetColor(1, 0.52, 0.30);//设置角的颜色;
    bone->GetProperty()->SetRepresentationToWireframe();//线框;

    vtkSmartPointer< vtkRenderer > aRenderer = vtkSmartPointer< vtkRenderer >::New();
    vtkSmartPointer< vtkRenderWindow > renWin = vtkSmartPointer< vtkRenderWindow >::New();
    renWin->AddRenderer(aRenderer);
    vtkSmartPointer< vtkRenderWindowInteractor > iren = vtkSmartPointer< vtkRenderWindowInteractor >::New();
    iren->SetRenderWindow(renWin);

    aRenderer->AddActor(bone);

    // 创建包围盒并设置其位置和大小
    vtkSmartPointer<vtkBoxWidget> boxWidget = vtkSmartPointer<vtkBoxWidget>::New();
    boxWidget->SetInteractor(iren);
    boxWidget->SetPlaceFactor(1); // 根据需要调整
    boxWidget->SetProp3D(bone); // 将包围盒与图像的演员关联
    boxWidget->PlaceWidget(                 // 使用图像的边界设置包围盒的位置和大小
        center[0] - halfSize[0], center[0] + halfSize[0],
        center[1] - halfSize[1], center[1] + halfSize[1],
        center[2] - halfSize[2], center[2] + halfSize[2]
        );
    vtkSmartPointer<vtkBoxWidgetCallback> clipCallback = vtkSmartPointer<vtkBoxWidgetCallback>::New();
    clipCallback->SetClipper(clipper);
    boxWidget->AddObserver(vtkCommand::InteractionEvent, clipCallback);
    boxWidget->On(); // 开启交互

    iren->Initialize();
    iren->Start();
    return;
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
使用VTKvtkBoxWidget可以实现交互式裁剪DICOM图像。下面是一个简单的示例代码: ```python import vtk # 读取DICOM数据 reader = vtk.vtkDICOMImageReader() reader.SetDirectoryName("path/to/dicom/files") reader.Update() # 创建渲染器和交互器 renderer = vtk.vtkRenderer() renderWindow = vtk.vtkRenderWindow() renderWindow.AddRenderer(renderer) renderWindowInteractor = vtk.vtkRenderWindowInteractor() renderWindowInteractor.SetRenderWindow(renderWindow) # 创建BoxWidget并添加到渲染器中 boxWidget = vtk.vtkBoxWidget() boxWidget.SetInteractor(renderWindowInteractor) boxWidget.SetPlaceFactor(1.0) boxWidget.PlaceWidget() boxWidget.InsideOutOn() boxWidget.AddObserver("InteractionEvent", lambda obj, event: updateClippingBox(obj, renderer)) boxWidget.SetInputData(reader.GetOutput()) boxWidget.PlaceWidget() # 设置相机位置和方向 camera = renderer.GetActiveCamera() camera.SetPosition(-500, -500, 500) camera.SetFocalPoint(0, 0, 0) camera.SetViewUp(0, 0, 1) renderer.ResetCamera() # 更新裁剪框 def updateClippingBox(obj, renderer): box = vtk.vtkBoxRepresentation().SafeDownCast(obj.GetRepresentation()) if box: box.GetTransform(obj.GetProp3D().GetMatrix()) clip = vtk.vtkImageClip() clip.SetInputData(reader.GetOutput()) clip.SetOutputWholeExtent(box.GetBounds()) clip.ClipDataOn() clip.Update() actor = vtk.vtkImageActor() actor.GetMapper().SetInputData(clip.GetOutput()) renderer.RemoveAllViewProps() renderer.AddActor(actor) renderWindow.Render() # 开始渲染 renderWindow.Render() renderWindowInteractor.Start() ``` 该代码创建了一个vtkDICOMImageReader,读取DICOM数据,并将其传递给vtkBoxWidget。然后,使用vtkImageClip来裁剪DICOM数据,并通过vtkImageActor将结果添加到渲染器中。最后,使用vtkRenderWindowInteractor启动交互式窗口并开始渲染。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值