c++ 为什么SimpleITK的PasteImageFilter这么慢?有没有其他替代方法?

bvk5enib  于 2023-04-13  发布在  其他
关注(0)|答案(1)|浏览(151)

我试图从不同的图像创建一个3D体积(尺寸为4000 x 4000 x 1600)。我有一个for循环,在这里我首先创建一个std::vector,然后使用ImportImageFilter创建一个尺寸为4000 x 4000 x 1的图像。之后我使用PasteImageFilter将创建的图像插入到体积中。所以每个图像就像大体积中的一个层。

下面的代码可以工作,但使用PasteImageFilter导入图像需要20-25秒。
有什么我可以做的,让它运行得更快?

重要的是,我不能有多个卷副本在同一时间,因为我会用完内存。

sitk::PixelIDValueEnum pixelTypeM1 = sitk::sitkUInt8;
sitk::PixelIDValueEnum pixelTypeM2 = sitk::sitkFloat32;

std::vector<unsigned int> sitkVolumeSize{4000,4000,1600};

sitk::Image sitk_m1_volume( sitkVolumeSize, pixelTypeM1 );
sitk::Image sitk_m2_volume( sitkVolumeSize, pixelTypeM2 );

sitk::PasteImageFilter pasteFilter;
for(int idx = 0; idx < 1600; idx++){

    std::vector<measurement> s1, s2;
    std::tie (s1, s2) = load_data();

    std::vector<float> m1_vec(4000*4000);
    std::vector<uint8_t> m2_vec(4000*4000);
    //some computations here to fill the m1_vec and m2_vec

    std::vector<unsigned int> imageDims{4000, 4000, 1};
    sitk::ImportImageFilter importer;

    importer.SetSize( imageDims );
    importer.SetBufferAsUInt8(m1_vec.data());
    sitk::Image m1_image = importer.Execute();

    importer.SetBufferAsFloat( m2_vec.data() );
    sitk::Image m2_image = importer.Execute();

    pasteFilter.SetDestinationIndex({0,0,idx});
    pasteFilter.SetSourceSize(m2_image.GetSize());
    sitk_m2_volume = pasteFilter.Execute(sitk_m2_volume, m2_image);
    sitk_m1_volume = pasteFilter.Execute(sitk_m1_volume, m1_image);

}
gopyfrb3

gopyfrb31#

请确保您是在Release模式下编译,而不是调试,这是在C++中使用ITK和SimpleITK时性能低下的最常见原因。

sitk_m2_volume = pasteFilter.Execute(sitk_m2_volume, m2_image);
sitk_m1_volume = pasteFilter.Execute(sitk_m1_volume, m1_image);

通过执行上述调用,它将创建sitk_m{2,1}_volumes的副本。对于大型图像,这可能会很昂贵。sitk::PasteImageFilter还支持使用第一个参数移动symatics:

Image itk::simple::PasteImageFilter::Execute(Image && destinationImage, const Image &   sourceImage 
)

如果你不熟悉C++ move语义和右值引用,请找一个好的现代C++参考来学习。这个签名可以这样使用:

sitk_m2_volume = pasteFilter.Execute(std::move(sitk_m2_volume), m2_image);
sitk_m1_volume = pasteFilter.Execute(std::move(sitk_m1_volume), m1_image);

通过此调用,图像缓冲区将从输入参数移动到输出,并且不会复制整个缓冲区,从而提高性能。

相关问题