图像处理之三维重建(切片级重建)

本文介绍使用分割后的切片数据进行3维图像重建。医学图像处理中,使用深度学习分割感兴趣区域是主流形式,当我们拿到连续分割后的mask区域,需要对mask区域进行可视化展示。完整代码放在最后啦(* ̄︶ ̄)


我使用c++结合vtk实现3维重建演示。

1、将分割后的结果放在一个文件夹中,因为要进行体积重现,一定要保证感兴趣区域正确顺序连续性。

     

2、读入切片图像数据,从文件夹中遍历图片,我的切片图像有37张,所以设置0-36。

std::vector<std::string> fileNames;
for (int i = 0; i <= 36; ++i) {
    std::stringstream ss;
    ss << R"(D:\tumor\1_0_)" << i << ".jpg"; // 替换为实际文件路径
    fileNames.push_back(ss.str());
}

// 创建JPEG读取器
vtkSmartPointer<vtkJPEGReader> reader = vtkSmartPointer<vtkJPEGReader>::New();
reader->SetFileName(fileNames[0].c_str()); // 设置第一个切片文件
reader->Update();

3、创建体数据volumeData,为每一体数据分配内存,我设置维度为(512,512,37)。

vtkSmartPointer<vtkImageData> volumeData = vtkSmartPointer<vtkImageData>::New();
volumeData->SetDimensions(512, 512, 37); // 设置体数据维度
volumeData->AllocateScalars(VTK_UNSIGNED_CHAR, 1); // 分配内存

 4、将每个切片图像的数据逐像素复制到三维体数据volumeData中,从而构建出一个完整的三维体。

for (int z = 0; z < fileNames.size(); ++z) {
    reader->SetFileName(fileNames[z].c_str());
    reader->Update();

    vtkImageData* slice = reader->GetOutput();
    for (int y = 0; y < 512; ++y) {
        for (int x = 0; x < 512; ++x) {
            unsigned char* pixel = static_cast<unsigned char*>(slice->GetScalarPointer(x, y, 0));
            volumeData->SetScalarComponentFromDouble(x, y, z, 0, *pixel);
        }
    }
}

5、最后就是经典的体渲染套路,创建颜色传递函数、mapper、volume等等。

                

                                                              数据展示效果

6、完整代码放在最后,希望可以帮助你ヾ(◍°∇°◍)ノ゙

std::vector<std::string> fileNames;
for (int i = 0; i <= 36; ++i) {
    std::stringstream ss;
    ss << R"(D:\tumor\1_0_)" << i << ".jpg"; // 替换为实际文件路径
    fileNames.push_back(ss.str());
}

// 创建JPEG读取器
vtkSmartPointer<vtkJPEGReader> reader = vtkSmartPointer<vtkJPEGReader>::New();
reader->SetFileName(fileNames[0].c_str()); // 设置第一个切片文件
reader->Update();

vtkSmartPointer<vtkImageData> volumeData = vtkSmartPointer<vtkImageData>::New();
volumeData->SetDimensions(512, 512, 37); // 设置体数据维度
volumeData->AllocateScalars(VTK_UNSIGNED_CHAR, 1); // 分配内存

for (int z = 0; z < fileNames.size(); ++z) {
    reader->SetFileName(fileNames[z].c_str());
    reader->Update();

    vtkImageData* slice = reader->GetOutput();
    for (int y = 0; y < 512; ++y) {
        for (int x = 0; x < 512; ++x) {
            unsigned char* pixel = static_cast<unsigned char*>(slice->GetScalarPointer(x, y, 0));
            volumeData->SetScalarComponentFromDouble(x, y, z, 0, *pixel);
        }
    }
}

// 设置不透明度传递函数
vtkSmartPointer<vtkPiecewiseFunction> opacityTransferFunction = vtkSmartPointer<vtkPiecewiseFunction>::New();
opacityTransferFunction->AddPoint(0, 0.0);   
opacityTransferFunction->AddPoint(255, 1.0);  

// 设置颜色传递函数
vtkSmartPointer<vtkColorTransferFunction> colorTransferFunction = vtkSmartPointer<vtkColorTransferFunction>::New();
colorTransferFunction->AddRGBPoint(0, 0.0, 0.0, 0.0);    
colorTransferFunction->AddRGBPoint(255, 1.0, 1.0, 1.0);  

// 设置体渲染属性
vtkSmartPointer<vtkVolumeProperty> volumeProperty = vtkSmartPointer<vtkVolumeProperty>::New();
volumeProperty->SetColor(colorTransferFunction);
volumeProperty->SetScalarOpacity(opacityTransferFunction);
volumeProperty->ShadeOn(); 
volumeProperty->SetInterpolationTypeToLinear(); 

// 设置体数据映射器
vtkSmartPointer<vtkFixedPointVolumeRayCastMapper> volumeMapper = vtkSmartPointer<vtkFixedPointVolumeRayCastMapper>::New();
volumeMapper->SetInputData(volumeData);

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

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

// 创建交互器
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);

// 将体数据添加到渲染器
renderer->AddVolume(volume);
renderer->SetBackground(0.1, 0.8, 0.8); 

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值