itk生成DRR图像(放射治疗中根据等中心点生成的DRR图像)

需要参数:

1、做计划的CT模拟图像的文件夹路劲

2、治疗计划的等中心点(300A,012C)  Isocenter Position

3、生成DRR图像的角度

代码如下(因为需要C#调用接口,所以该示例返回了生成DRR图像的像素值):

#ifndef __INTERFACE_H__
#define __INTERFACE_H__
# define xSize 512
# define ySize 512
# define zSize 1

#if defined(_WIN32)
#ifdef REG_COMPILE_LIBRARY
#define REG_CAPI_EXPORT __declspec(dllexport)
#else
#define REG_CAPI_EXPORT __declspec(dllimport)
#endif
#else
#define REG_CAPI_EXPORT
#endif

#ifdef __cplusplus
extern "C"
{
#endif
	struct DRRImage_Input
	{
		char* path;
		float Angle;
		float IsoCenterPosition[3];
	};
	struct DRRImage_Output
	{
		
		int Size[2];
		float Spacing[2];
		short ImageData[xSize * ySize * zSize];
	};
	REG_CAPI_EXPORT int GetDRRImagePixel(DRRImage_Input* input, DRRImage_Output* output);
#ifdef __cplusplus
}
#endif

#endif
#include "UtilHelper.h"
#include "itkResampleImageFilter.h"
#include "itkCenteredEuler3DTransform.h"
#include "itkRescaleIntensityImageFilter.h"
#include "itkGDCMImageIO.h" 
#include "itkGDCMSeriesFileNames.h"
#include "itkImageSeriesReader.h" 
#include "itkNumericSeriesFileNames.h" 
#include "itkRayCastInterpolateImageFunction.h"
int GetDRRImagePixel(DRRImage_Input* input, DRRImage_Output* output)
{
    float rx = -90.;
    float ry = 0.;
    float rz = input->Angle;

    float tx = 0.;
    float ty = 0.;
    float tz = 0.;

    float cx = 0.;
    float cy = 0.;
    float cz = 0.;

    float sid = -1000.;

    float sx = 1.;
    float sy = 1.;

    int dx = xSize;
    int dy = ySize;
    int dz = zSize;

    float o2Dx = 0;
    float o2Dy = 0;

    double threshold = 0;
    std::cout << "Input image: " << input->path << std::endl;
    std::cout << "DRR Angle: " << input->Angle << std::endl;
    std::cout << "IsoCenterPosition[0]: " << input->IsoCenterPosition[0] << std::endl;
    std::cout << "IsoCenterPosition[1]: " << input->IsoCenterPosition[1] << std::endl;
    std::cout << "IsoCenterPosition[2]: " << input->IsoCenterPosition[2] << std::endl;

    // Set these values from the treatment plan
    float isoCenterX = input->IsoCenterPosition[0];
    float isoCenterY = input->IsoCenterPosition[1];
    float isoCenterZ = input->IsoCenterPosition[2];
    // Software Guide : BeginLatex
    //
    // Although we generate a 2D projection of the 3D volume for the
    // purposes of the interpolator both images must be three dimensional.
    //
    // Software Guide : EndLatex

    // Software Guide : BeginCodeSnippet
    constexpr unsigned int Dimension = 3;
    using InputPixelType = short;

    using InputImageType = itk::Image<InputPixelType, Dimension>;

    InputImageType::Pointer image;
    // Software Guide : EndCodeSnippet

    // Software Guide : BeginLatex
    //
    // For the purposes of this example we assume the input volume has
    // been loaded into an \code{itk::Image image}.
    //
    // Software Guide : EndLatex

   /*
            using ReaderType = itk::ImageFileReader< InputImageType >;
            ReaderType::Pointer reader = ReaderType::New();
            reader->SetFileName( input_name );
        */
        //定义像素类型,图像类型,三维有符号数,定义指针
    typedef signed short PixelType;
    typedef itk::Image< PixelType, Dimension > ImageType;
    typedef itk::ImageSeriesReader< ImageType > ReaderType;

    //声明读、写DICOM图像的itk::GDCMImageIO对象
    //itk::GDCMSeriesFileNames对象将生成并将构成所有体数据的切片的文件名进行排序
    typedef itk::GDCMImageIO ImageIOType;
    typedef itk::GDCMSeriesFileNames NamesGeneratorType;
    ImageIOType::Pointer gdcmIO = ImageIOType::New();
    NamesGeneratorType::Pointer namesGenerator = NamesGeneratorType::New();

    //设置读取路径
    //用文件名发生器生成被读的文件名和被写的文件名
    namesGenerator->SetInputDirectory(input->path);
    const ReaderType::FileNamesContainer& filenames = namesGenerator->GetInputFileNames();

    //设置DICOM图像IO对象和被读的文件名的列表
    ReaderType::Pointer reader = ReaderType::New();
    reader->SetImageIO(gdcmIO);
    reader->SetFileNames(filenames);

    try
    {
        reader->Update();
    }
    catch (itk::ExceptionObject& err)
    {
        std::cerr << "ERROR: ExceptionObject caught !" << std::endl;
        std::cerr << err << std::endl;
        return EXIT_FAILURE;
    }
    image = reader->GetOutput();


    // Print out the details of the input volume
    std::cout << "Image Spacing:" << image->GetSpacing() << std::endl;
    std::cout << "Image BufferedRegion:" << image->GetBufferedRegion() << std::endl;
    std::cout << "Image Origin:" << image->GetOrigin() << std::endl;

    // Software Guide : BeginLatex
    //
    // Creation of a \code{ResampleImageFilter} enables coordinates for
    // each of the pixels in the DRR image to be generated. These
    // coordinates are used by the \code{RayCastInterpolateImageFunction}
    // to determine the equation of each corresponding ray which is cast
    // through the input volume.
    //
    // Software Guide : EndLatex

    // Software Guide : BeginCodeSnippet
    using FilterType = itk::ResampleImageFilter<InputImageType, InputImageType>;

    auto filter = FilterType::New();

    filter->SetInput(image);
    filter->SetDefaultPixelValue(0);
    // Software Guide : EndCodeSnippet

    // Software Guide : BeginLatex
    //
    // An Euler transformation is defined to position the input volume.
    // The \code{ResampleImageFilter} uses this transform to position the
    // output DRR image for the desired view.
    //
    // Software Guide : EndLatex

    // Software Guide : BeginCodeSnippet
    using TransformType = itk::CenteredEuler3DTransform<double>;

    auto transform = TransformType::New();

    transform->SetComputeZYX(true);

    TransformType::OutputVectorType translation;

    translation[0] = tx;
    translation[1] = ty;
    translation[2] = tz;

    // constant for converting degrees into radians
    const double dtr = (std::atan(1.0) * 4.0) / 180.0;

    transform->SetTranslation(translation);
    transform->SetRotation(dtr * rx, dtr * ry, dtr * rz);

    InputImageType::PointType   imOrigin = image->GetOrigin();
    InputImageType::SpacingType imRes = image->GetSpacing();

    using InputImageRegionType = InputImageType::RegionType;
    using InputImageSizeType = InputImageRegionType::SizeType;

    InputImageRegionType imRegion = image->GetBufferedRegion();
    InputImageSizeType   imSize = imRegion.GetSize();

    imOrigin[0] += isoCenterX;
    imOrigin[1] += isoCenterY;
    imOrigin[2] += isoCenterZ;

    TransformType::InputPointType center;
    center[0] = cx + isoCenterX;
    center[1] = cy + isoCenterY;
    center[2] = cz + isoCenterZ;

    transform->SetCenter(center);

    std::cout << "Image size: " << imSize[0] << ", " << imSize[1] << ", "
        << imSize[2] << std::endl
        << "   resolution: " << imRes[0] << ", " << imRes[1] << ", "
        << imRes[2] << std::endl
        << "   origin: " << imOrigin[0] << ", " << imOrigin[1] << ", "
        << imOrigin[2] << std::endl
        << "   center: " << center[0] << ", " << center[1] << ", "
        << center[2] << std::endl
        << "Transform: " << transform << std::endl;
    // Software Guide : EndCodeSnippet

    // Software Guide : BeginLatex
    //
    // The \code{RayCastInterpolateImageFunction} is instantiated and passed the
    // transform object. The \code{RayCastInterpolateImageFunction} uses this
    // transform to reposition the x-ray source such that the DRR image
    // and x-ray source move as one around the input volume. This coupling
    // mimics the rigid geometry of the x-ray gantry.
    //
    // Software Guide : EndLatex

    // Software Guide : BeginCodeSnippet
    using InterpolatorType =
        itk::RayCastInterpolateImageFunction<InputImageType, double>;
    auto interpolator = InterpolatorType::New();
    interpolator->SetTransform(transform);
    // Software Guide : EndCodeSnippet

    // Software Guide : BeginLatex
    //
    // We can then specify a threshold above which the volume's
    // intensities will be integrated.
    //
    // Software Guide : EndLatex

    // Software Guide : BeginCodeSnippet
    interpolator->SetThreshold(threshold);
    // Software Guide : EndCodeSnippet

    // Software Guide : BeginLatex
    //
    // The ray-cast interpolator needs to know the initial position of the
    // ray source or focal point. In this example we place the input
    // volume at the origin and halfway between the ray source and the
    // screen. The distance between the ray source and the screen
    // is the "source to image distance" \code{sid} and is specified by
    // the user.
    //
    // Software Guide : EndLatex

    // Software Guide : BeginCodeSnippet
    InterpolatorType::InputPointType focalpoint;

    focalpoint[0] = isoCenterX;
    focalpoint[1] = isoCenterY;
    focalpoint[2] = sid;

    interpolator->SetFocalPoint(focalpoint);
    // Software Guide : EndCodeSnippet

    std::cout << "Focal Point: " << focalpoint[0] << ", " << focalpoint[1]
        << ", " << focalpoint[2] << std::endl;

    // Software Guide : BeginLatex
    //
    // Having initialised the interpolator we pass the object to the
    // resample filter.
    //
    // Software Guide : EndLatex

    // Software Guide : BeginCodeSnippet
    interpolator->Print(std::cout);

    filter->SetInterpolator(interpolator);
    filter->SetTransform(transform);
    // Software Guide : EndCodeSnippet

    // Software Guide : BeginLatex
    //
    // The size and resolution of the output DRR image is specified via the
    // resample filter.
    //
    // Software Guide : EndLatex

    // Software Guide : BeginCodeSnippet

    // setup the scene
    InputImageType::SizeType size;

    size[0] = dx; // number of pixels along X of the 2D DRR image
    size[1] = dy; // number of pixels along Y of the 2D DRR image
    size[2] = dz;  // only one slice

    filter->SetSize(size);

    InputImageType::SpacingType spacing;

    spacing[0] = sx;  // pixel spacing along X of the 2D DRR image [mm]
    spacing[1] = sy;  // pixel spacing along Y of the 2D DRR image [mm]
    spacing[2] = 1.0; // slice thickness of the 2D DRR image [mm]

    filter->SetOutputSpacing(spacing);

    // Software Guide : EndCodeSnippet

    std::cout << "Output image size: " << size[0] << ", " << size[1] << ", "
        << size[2] << std::endl;

    std::cout << "Output image spacing: " << spacing[0] << ", " << spacing[1]
        << ", " << spacing[2] << std::endl;

    // Software Guide : BeginLatex
    //
    // In addition the position of the DRR is specified. The default
    // position of the input volume, prior to its transformation is
    // half-way between the ray source and screen and unless specified
    // otherwise the normal from the "screen" to the ray source passes
    // directly through the centre of the DRR.
    //
    // Software Guide : EndLatex

    // Software Guide : BeginCodeSnippet

    double origin[Dimension];

    origin[0] = isoCenterX + o2Dx - sx * (static_cast<double>(dx) - 1.) / 2.;
    origin[1] = isoCenterY + o2Dy - sy * (static_cast<double>(dy) - 1.) / 2.;
    origin[2] = isoCenterZ;

    filter->SetOutputOrigin(origin);
    // Software Guide : EndCodeSnippet

    std::cout << "Output image origin: " << origin[0] << ", " << origin[1]
        << ", " << origin[2] << std::endl;

    filter->Update();
    std::cout << filter->GetOutput()->GetBufferPointer() << std::endl;

    short* inptr = filter->GetOutput()->GetBufferPointer();
    const int n = dx * dy * dz;
    //config->imageData[n];
    for (int i = 0; i < n; ++i) 
    {
        output->ImageData[i] = inptr[i];
    }
    output->Size[0] = size[0];
    output->Size[1] = size[1];
    output->Spacing[0] = spacing[0];
    output->Spacing[1] = spacing[1];
    
    return EXIT_SUCCESS;
}

得到的图像示例(0度):

图像中的绿点就是治疗等中心点(坐标【0,0,0】)

如果需要把结构集数据展示在DRR图像上,只需要用[0,1,0]的法向量旋转一定角度,在计算出新的法向量,用新的法向量切面去切ROI的三维模型即可(生成ROI三维模型的方法在RTSTRUCT ROI三维模型

最终得到的图像如下:

CT数字成像(Computed Tomography Digital Imaging)是一种以X射线为基础的成像技术,在CT扫描中用于获取人体内部组织的详细断层图像。而DRR(Digital Reconstructed Radiograph)是由CT图像数据生成的二维投影图像,可以模拟实际的X射线拍摄。 在c itk生成DRR的过程中,首先需要将CT图像数据导入c itk软件中。然后,根据设定的参数和算法,利用c itk中的图像重建技术对CT图像数据进行处理,从而生成三维的体素模型。接下来,根据体素模型的位置姿态和探测器的参数,模拟X射线透射过程,生成一系列的X射线投影图像。最后,将投影图像进行处理和叠加,得到最终的DRR图像。 在c itk生成DRR的过程中,需要注意以下几个关键点: 1. CT图像质量对DRR图像质量的影响较大。因此,在生成DRR之前,应确保CT图像的扫描参数和重建算法都得到了优化,以获取高质量的CT图像数据。 2. DRR生成需要考虑探测器的位置、角度和参数等信息,以及源到探测器的路径。这些参数需要事先确定并进行准确的设置。 3. DRR图像生成也需要根据实际需求进行参数调整,以获取符合临床需要的投影图像。 通过c itk生成DRR图像,可以在临床放射学中发挥重要的作用。DRR图像可以用于虚拟放射治疗计划、手术规划以及教学培训等方面,为医生提供了更准确的辅助诊断和决策依据,同时降低了患者接受实际X射线检查的风险和剂量。因此,c itk生成DRR图像的技术在医学影像领域具有广泛的应用前景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ran-莫待无花

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值