前言
为了使用CT模拟照射生成drr(关于drr,默认大家已经知道),捣鼓了一阵itk,现在将有关内容记录一下,同时希望对其他同学有帮助。
1. 编译itk
1.1 准备工具
- cmake,按照相关教程下载安装
- visual studio 2022,按照相关教程下载安装
- itk官网下载itk的压缩包
1.2 准备3个文件夹
- src,用来放置解压的itk源文件,解压下载的itk压缩包到这个文件夹中
- bin,用来放置cmake的生成文件
- release,用来放置visual studio 2022生成的最终可使用的文件
1.3 cmake的工作
- 首先放置好文件夹路径,勾上对应旋转
- 然后点击:
config
\textbf{config}
config
- 设置
vs2022
\textbf{vs2022}
vs2022 和
x64
\textbf{x64}
x64,点击完成
然后它自己会运行一会儿,等出现
C
o
n
f
i
g
u
r
i
n
g
?
d
o
n
e
Configuring\ done
Configuring?done的时候,会出现一大片红色区域,不用慌,且看下一步。 - 修改cmke的
2
\textbf{2}
2个地方
- 第1个地方是: 添加勾选BUILD_SHARED_LIBS,生成dll
- 第2个地方是:在CMAKE下,修改CMAKE_INSTALL_PREFIX为之前建好的release文件夹
然后再点击
c
o
n
f
i
g
config
config。它又会运行一段时间,然后等出现
C
o
n
f
i
g
u
r
i
n
g
?
d
o
n
e
Configuring\ done
Configuring?done的时候,就只有1个地方是红的了。 没关系,继续点
c
o
n
f
i
g
config
config,不出意外,这次就没有红的了。 综上所述,总共点了
3
3
3次
c
o
n
f
i
g
config
config。 - 点击
Generate
\textbf{Generate}
Generate,生成文件到
b
i
n
bin
bin文件夹
等出现
G
e
n
e
r
a
t
i
n
g
?
d
o
n
e
Generating\ done
Generating?done的时候,点击
O
p
e
n
?
P
r
o
j
e
c
t
Open\ Project
Open?Project 这个时候会通过vs2022打开bin文件夹下的一个项目,加载需要一段时间,耐心等待。
1.4 visual studio 2022的工作
- 第1步,选择
生成
?
批生成
生成\longrightarrow批生成
生成?批生成
- 第2步,勾选ALL_BUILD,选择release,点击生成。这一步费时较长。
检查是否生成成功: - 第3步,安装。
同样也是通过
生成
?
批生成
生成\longrightarrow批生成
生成?批生成,取消掉之前的ALL_BUILD的勾选,勾选INSTALL的release版本,点击生成。 等生成完毕之后,就会在之前建的
r
e
l
e
a
s
e
release
release文件夹下生成4个文件夹: 其中,主要用到这个三个目录
- bin文件夹:保存生成的dll,后面要配置到环境变量中
- include: 包含目录
- lib:库目录
至此,第1部分,编译itk就做完了。
2. 使用编译完成的itk
为了测试我们生成的文件是否有效,应该搞一段代码来测试一下
2.1 配置bin目录的环境变量
2.2 重启电脑
这是为了使得配置的bin目录生效。
2.3 新建工程测试
新建一个空项目,添加一个cpp文件,把下面这段代码贴上去:
#include <itkImage.h>
#include <itkImageFileReader.h>
#include <itkImageFileWriter.h>
#include <itkResampleImageFilter.h>
#include <itkCenteredEuler3DTransform.h>
#include <itkNearestNeighborInterpolateImageFunction.h>
#include <itkImageRegionIteratorWithIndex.h>
#include <itkRescaleIntensityImageFilter.h>
#include <itkGDCMImageIO.h>
#include <itkPNGImageIO.h>
#include <itkPNGImageIOFactory.h>
#include <itkGDCMSeriesFileNames.h>
#include <itkImageSeriesReader.h>
#include <itkImageSeriesWriter.h>
#include <itkNumericSeriesFileNames.h>
#include <itkGiplImageIOFactory.h>
#include <itkCastImageFilter.h>
#include <itkNIFTIImageIO.h>
#include <itkNIFTIImageIOFactory.h>
#include <itkMetaImageIOFactory.h>
#include <itkRayCastInterpolateImageFunction.h>
#include <iostream>
#include <io.h>
using namespace std;
int main() {
const string file_path = "E:/hip_data/images/001.nii.gz";
const string out_drr = "drr/";
string save_path = out_drr + "dr4.png";
cout << "input_path = " << file_path << endl;
cout << "save_path = " << save_path << endl;
bool ok;
bool verbose = false;
float rx = -90;
float ry = 0;
float rz = 0;
float tx = 0;
float ty = 0;
float tz = 0;
float cx = 0;
float cy = 0;
float cz = 0;
float sid = 400;
float sx = 1.5;
float sy = 1.5;
int dx = 512;
int dy = 512;
float o2Dx = 0;
float o2Dy = 0;
double threshold = -400;
const unsigned int Dimension = 3;
using InputPixelType = float;
using OutputPixelType = unsigned char;
using InputImageType = itk::Image<InputPixelType, Dimension>;
using OutputImageType = itk::Image<OutputPixelType, Dimension>;
InputImageType::Pointer image;
using ReaderType = itk::ImageFileReader<InputImageType>;
ReaderType::Pointer reader = ReaderType::New();
itk::NiftiImageIOFactory::RegisterOneFactory();
reader->SetFileName(file_path);
try {
reader->Update();
}
catch (itk::ExceptionObject& err) {
cerr << "error exception object caught!" << endl;
cerr << err.what() << endl;
return EXIT_FAILURE;
}
image = reader->GetOutput();
if (verbose) {
const InputImageType::SpacingType spacing = image->GetSpacing();
cout << endl << "Input: ";
InputImageType::RegionType region = image->GetBufferedRegion();
region.Print(cout);
cout << " Resolution: [";
for (int i = 0; i < Dimension; i++) {
cout << spacing[i];
if (i < Dimension - 1) cout << ", ";
}
cout << "]" << endl;
const InputImageType::PointType origin = image->GetOrigin();
cout << " Origin: [";
for (int i = 0; i < Dimension; i++) {
cout << origin[i];
if (i < Dimension - 1) cout << ", ";
}
cout << "]" << endl << endl;
}
using FilterType = itk::ResampleImageFilter<InputImageType, InputImageType>;
FilterType::Pointer filter = FilterType::New();
filter->SetInput(image);
filter->SetDefaultPixelValue(0);
using TransformType = itk::CenteredEuler3DTransform<double>;
TransformType::Pointer transform = TransformType::New();
transform->SetComputeZYX(true);
TransformType::OutputVectorType translation;
translation[0] = tx;
translation[1] = ty;
translation[2] = tz;
const double dtr = 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] += imRes[0] * static_cast<double>(imSize[0]) / 2.0;
imOrigin[1] += imRes[1] * static_cast<double>(imSize[1]) / 2.0;
imOrigin[2] += imRes[2] * static_cast<double>(imSize[2]) / 2.0;
TransformType::InputPointType center;
center[0] = cx + imOrigin[0];
center[1] = cy + imOrigin[1];
center[2] = cz + imOrigin[2];
transform->SetCenter(center);
if (verbose) {
cout << "Image size: " << imSize[0] << ", " << imSize[1] << ", " << imSize[2]
<< endl << " resolution: " << imRes[0] << ", " << imRes[1] << ", " << imRes[2]
<< endl << " origin: " << imOrigin[0] << ", " << imOrigin[1] << ", " <<
imOrigin[2] << endl << " center: " << center[0] << ", " << center[1]
<< ", " << center[2] << endl << "Transform: " << transform << endl;
}
using InterpolatorType = itk::RayCastInterpolateImageFunction<InputImageType, double>;
InterpolatorType::Pointer interpolator = InterpolatorType::New();
interpolator->SetTransform(transform);
interpolator->SetThreshold(threshold);
InterpolatorType::InputPointType focalpoint;
focalpoint[0] = imOrigin[0];
focalpoint[1] = imOrigin[1];
focalpoint[2] = imOrigin[2] - sid / 2.0;
interpolator->SetFocalPoint(focalpoint);
if (verbose) {
cout << "Focal Point: "
<< focalpoint[0] << ", "
<< focalpoint[1] << ", "
<< focalpoint[2] << endl;
}
interpolator->Print(std::cout);
filter->SetInterpolator(interpolator);
filter->SetTransform(transform);
InputImageType::SizeType size;
size[0] = dx;
size[1] = dy;
size[2] = 1;
filter->SetSize(size);
InputImageType::SpacingType spacing;
spacing[0] = sx;
spacing[1] = sy;
spacing[2] = 1.0;
filter->SetOutputSpacing(spacing);
if (verbose)
{
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;
}
double origin[Dimension];
origin[0] = imOrigin[0] + o2Dx - sx * ((double)dx - 1.) / 2.;
origin[1] = imOrigin[1] + o2Dy - sy * ((double)dy - 1.) / 2.;
origin[2] = imOrigin[2] + sid / 2.;
filter->SetOutputOrigin(origin);
if (verbose)
{
std::cout << "Output image origin: "
<< origin[0] << ", "
<< origin[1] << ", "
<< origin[2] << std::endl;
}
using RescaleFilterType = itk::RescaleIntensityImageFilter<InputImageType, OutputImageType>;
RescaleFilterType::Pointer rescaler = RescaleFilterType::New();
rescaler->SetOutputMinimum(0);
rescaler->SetOutputMaximum(255);
rescaler->SetInput(filter->GetOutput());
using WriterType = itk::ImageFileWriter<OutputImageType>;
WriterType::Pointer writer = WriterType::New();
using pngType = itk::PNGImageIO;
pngType::Pointer pngIO1 = pngType::New();
itk::PNGImageIOFactory::RegisterOneFactory();
writer->SetFileName(save_path);
writer->SetImageIO(pngIO1);
writer->SetImageIO(itk::PNGImageIO::New());
writer->SetInput(rescaler->GetOutput());
try
{
std::cout << "Writing image: " << save_path << std::endl;
writer->Update();
}
catch (itk::ExceptionObject& err)
{
std::cerr << "ERROR: ExceptionObject caught !" << std::endl;
std::cerr << err << std::endl;
}
return 0;
}
显然会报很多错误,因为我们还没有对项目进行配置。
- 第1,构造属性表,选择
属性管理器 —>release|x64 ,右键,选择添加新的属性表 随意命名一下吧,然后双击打开它。 - 包含目录,添加
i
n
c
l
u
d
e
include
include文件夹
- 库目录,选择
l
i
b
lib
lib文件夹
- lib文件添加。在
链接器 —>输入 —>附加依赖项 里面将
l
i
b
lib
lib文件夹下的所有后缀为
.
l
i
b
.lib
.lib的文件全部添加进去。 在该文件夹下使用cmd命令行生成txt: 打开txt复制粘贴上去。点击确定 点击应用,确定 - 最后一步
回来发现还是红的,最后将debug改成release就可以了。因为我们编译的是release版本。 - 在当前项目下新建drr文件夹,修改自己的ct数据路径,就可以调试运行了
最后在drr文件夹中生成的drr图像
大功告成
|