对VTK中的Volume Data体数据进行二维图像处理

文章目录

概要

在 VTK 中对体数据进行二维图像处理的过程通常涉及从三维体数据中提取二维切片,并对这些切片进行处理。然后,可以选择性地将处理后的切片数据重新合并成新的体数据。

以下是对 VTK 中的体数据进行二维图像处理的基本步骤:

  1. 提取二维切片

    体数据通常是三维数据(例如,CT 扫描、MRI 扫描等)。在进行二维图像处理时,通常从三维数据中提取出单个切片(沿某个方向的切片)。这可以使用 vtkImageReslice 完成,vtkImageReslice 可以帮助从三维数据中生成二维切片。

  2. 对二维切片进行图像处理

    一旦您提取了二维切片,就可以对其进行各种图像处理操作,如平滑、滤波、阈值化、边缘检测等。可以使用 VTK 提供的一些滤波器(如 vtkImageGaussianSmooth)和图像处理类(如 vtkImageThreshold)。

  3. 将处理后的切片重新合并成体数据

    处理过的二维切片可以重新组合为新的三维体数据。这可以通过逐层更新 vtkImageData 中的像素值来实现。

Cpp代码

cpp 复制代码
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);
VTK_MODULE_INIT(vtkRenderingFreeType);

#include <vtkSmartPointer.h>
#include <vtkGPUVolumeRayCastMapper.h>
#include <vtkVolumeProperty.h>
#include <vtkColorTransferFunction.h>
#include <vtkPiecewiseFunction.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkImageReslice.h>
#include <vtkDirectory.h>
#include <vtkDICOMReader.h>
#include <windows.h>
#include <psapi.h>
#include <vtkDICOMImageReader.h>
#include <vtkImageMedian3D.h>
#include <vtkImageData.h>
#include <vtkImageGaussianSmooth.h>
#include <vtkImageThreshold.h>
#include <vtkImageHybridMedian2D.h>

int main(int argc, char* argv[]) {
    // 验证目录是否存在
    vtkSmartPointer<vtkDirectory> dir = vtkSmartPointer<vtkDirectory>::New();
    if (!dir->Open("E:/yp/vtk/3DMR-main/dicom3/")) {
        std::cerr << "错误:无法打开DICOM目录" << std::endl;
        return EXIT_FAILURE;
    }
    // 1. 读取DICOM序列
    vtkSmartPointer<vtkDICOMImageReader> reader = vtkSmartPointer<vtkDICOMImageReader>::New();
    reader->SetDirectoryName("E:/yp/vtk/3DMR-main/dicom/"); // 替换为实际路径
    reader->Update();
 

    vtkSmartPointer<vtkImageData> imageData = reader->GetOutput();

    // 2. 数据预处理(可选)
    // 如果需要对每个切片进行处理(例如阈值化或平滑),可以遍历每个切片并进行处理
    int* extent = imageData->GetExtent();
    int dims[3];
    dims[0] = extent[1] - extent[0] + 1;
    dims[1] = extent[3] - extent[2] + 1;
    dims[2] = extent[5] - extent[4] + 1;

    // 获取图像的原点和间距
    double origin[3];
    imageData->GetOrigin(origin);

    double spacing[3];
    imageData->GetSpacing(spacing);

    // 遍历每个z切片
    for (int z = 0; z < dims[2]; ++z) {
        // 使用vtkImageReslice提取当前切片
        vtkSmartPointer<vtkImageReslice> reslice = vtkSmartPointer<vtkImageReslice>::New();
        reslice->SetInputData(imageData);
        reslice->SetOutputDimensionality(2);
        reslice->SetResliceAxesDirectionCosines(1, 0, 0, 0, 1, 0, 0, 0, 1);
        // 设置正确的切片原点
        double currentOriginZ = origin[2] + z * spacing[2];
        reslice->SetResliceAxesOrigin(origin[0], origin[1], currentOriginZ);

        reslice->SetInterpolationModeToNearestNeighbor();
        reslice->Update();

        // 创建并配置vtkImageHybridMedian2D滤波器
/*
        vtkSmartPointer<vtkImageHybridMedian2D> hybridMedian = vtkSmartPointer<vtkImageHybridMedian2D>::New();
        hybridMedian->SetInputConnection(reslice->GetOutputPort());
        hybridMedian->Update();*/

        vtkNew<vtkImageGaussianSmooth> filter;
        filter->SetDimensionality(2);
        filter->SetInputConnection(reslice->GetOutputPort());
        filter->SetStandardDeviations(4, 4);
        filter->SetRadiusFactors(2.0, 2.0);
        filter->Update();

        // 获取处理后的切片数据
        vtkSmartPointer<vtkImageData> tempSlice = filter->GetOutput();

        // 将处理后的数据写回原始体数据
        for (int y = 0; y < dims[1]; ++y) {
            for (int x = 0; x < dims[0]; ++x) {
                double  pixel = tempSlice->GetScalarComponentAsDouble(x, y, 0, 0);
                imageData->SetScalarComponentFromDouble(x, y, z, 0, pixel);
            }
        }
    }

  
    // 3. 创建体积映射器
    vtkSmartPointer<vtkGPUVolumeRayCastMapper> volumeMapper = vtkSmartPointer<vtkGPUVolumeRayCastMapper>::New();
    volumeMapper->SetInputData(imageData);
    volumeMapper->SetBlendModeToComposite(); // 使用合成模式
    volumeMapper->SetSampleDistance(0.25); // 调整该值来增加/减少采样精度

    // 4. 配置传输函数
    vtkSmartPointer<vtkColorTransferFunction> colorFun = vtkSmartPointer<vtkColorTransferFunction>::New();
    colorFun->AddRGBPoint(0, 0.0, 0.0, 0.0);
    colorFun->AddRGBPoint(200, 1.0, 0.5, 0.3); // 软组织
    colorFun->AddRGBPoint(500, 0.9, 0.9, 0.9); // 骨骼

    vtkSmartPointer<vtkPiecewiseFunction> opacityFun = vtkSmartPointer<vtkPiecewiseFunction>::New();
    opacityFun->AddPoint(0, 0.00);
    opacityFun->AddPoint(200, 0.05);
    opacityFun->AddPoint(500, 0.85);

    // 5. 配置体积属性
    vtkSmartPointer<vtkVolumeProperty> volumeProperty = vtkSmartPointer<vtkVolumeProperty>::New();
    // 开启体积光照
    volumeProperty->SetAmbient(0.3);
    volumeProperty->SetDiffuse(0.7);
    volumeProperty->SetSpecular(0.2);
    volumeProperty->SetSpecularPower(50.0);
    
    volumeProperty->SetColor(colorFun);
    volumeProperty->SetScalarOpacity(opacityFun);
    volumeProperty->SetInterpolationTypeToLinear();
    volumeProperty->ShadeOn(); // 启用阴影

    // 6. 创建体积对象
    vtkSmartPointer<vtkVolume> volume = vtkSmartPointer<vtkVolume>::New();
    volume->SetMapper(volumeMapper);
    volume->SetProperty(volumeProperty);

    // 7. 创建渲染管线
    vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
    renderer->AddVolume(volume);
    renderer->SetBackground(0.2, 0.3, 0.4);

    vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
    renderWindow->AddRenderer(renderer);
    renderWindow->SetSize(1280, 720);
    renderWindow->SetMultiSamples(8);  // 启用抗锯齿,8x 超采样

    vtkSmartPointer<vtkRenderWindowInteractor> interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
    interactor->SetRenderWindow(renderWindow);

    // 8. 启动交互
    renderWindow->Render();
    interactor->Start();

    return 0;
}

处理前效果

处理后效果

相关推荐
智驱力人工智能19 分钟前
小区高空抛物AI实时预警方案 筑牢社区头顶安全的实践 高空抛物检测 高空抛物监控安装教程 高空抛物误报率优化方案 高空抛物监控案例分享
人工智能·深度学习·opencv·算法·安全·yolo·边缘计算
qq_1601448722 分钟前
亲测!2026年零基础学AI的入门干货,新手照做就能上手
人工智能
Howie Zphile22 分钟前
全面预算管理难以落地的核心真相:“完美模型幻觉”的认知误区
人工智能·全面预算
人工不智能57725 分钟前
拆解 BERT:Output 中的 Hidden States 到底藏了什么秘密?
人工智能·深度学习·bert
盟接之桥27 分钟前
盟接之桥说制造:引流品 × 利润品,全球电商平台高效产品组合策略(供讨论)
大数据·linux·服务器·网络·人工智能·制造
kfyty72528 分钟前
集成 spring-ai 2.x 实践中遇到的一些问题及解决方案
java·人工智能·spring-ai
h64648564h1 小时前
CANN 性能剖析与调优全指南:从 Profiling 到 Kernel 级优化
人工智能·深度学习
数据与后端架构提升之路1 小时前
论系统安全架构设计及其应用(基于AI大模型项目)
人工智能·安全·系统安全
忆~遂愿1 小时前
ops-cv 算子库深度解析:面向视觉任务的硬件优化与数据布局(NCHW/NHWC)策略
java·大数据·linux·人工智能
Liue612312311 小时前
YOLO11-C3k2-MBRConv3改进提升金属表面缺陷检测与分类性能_焊接裂纹气孔飞溅物焊接线识别
人工智能·分类·数据挖掘