首页 > 其他分享 >ITK 简单使用

ITK 简单使用

时间:2023-07-13 11:44:40浏览次数:47  
标签:typedef 配准 itk 简单 使用 图像 Pointer ITK

第一个ITK程序

1、CMakeLists.txt

 1 # This is the root ITK CMakeLists file.
 2 cmake_minimum_required(VERSION 3.10)
 3  
 4 # This project is designed to be built outside the Insight source tree.
 5 project(ITK_demo)
 6  
 7 # Find VTK
 8 set(ITK_DIR D:/ProgramFiles/ITK-5.1.1/lib/cmake/ITK-5.1) # add wmz
 9 find_package(ITK REQUIRED)
10 include_directories(${ITK_INCLUDE_DIRS})
11 message("ITK dir = ${ITK_INCLUDE_DIRS}")
12 message("ITK lib = ${ITK_LIBRARIES}") 
13 
14 include(${ITK_USE_FILE})
15 #aux_source_directory(src SRC_LIST) 
16 set(SRC_LIST
17     ./itk_demo.cpp)
18 
19 add_executable(itk_demo ${SRC_LIST} ) 
20 target_link_libraries(itk_demo ${ITK_LIBRARIES})

关于 include(${ITK_USE_FILE}) 的说明可以在 UseITK.cmake 中找到:

 1 #  -------------
 2 #
 3 # This file is not part of the ITK API.  It exists purely as an
 4 # implementation detail.  This CMake module may change from version to
 5 # version without notice, or even be removed.
 6 #
 7 # We mean it.
 8 #
 9 
10 # This file sets up include directories, link directories, IO settings and
11 # compiler settings for a project to use ITK.  It should not be
12 # included directly, but rather through the ITK_USE_FILE setting
13 # obtained from ITKConfig.cmake.

2、 测试数据
测试数据下载路径:https://github.com/InsightSoftwareConsortium/ITK/tree/master/Examples/Data
其实编译ITK时的目录下就有需要的测试数据,比如我的ITK-5.1.1目录下。

\ITK-5.1.1\Examples\Data

3、代码
作为第一个示例程序本来应该写一个很简单的像HelloWorld的程序,但是一些比较简单的官网的程序 要么依赖VTK,要么版本高于ITK5.1.1.
所以就找了一个比较长的程序,是一个配准的程序。
代码来自:https://github.com/InsightSoftwareConsortium/ITK/blob/master/Examples/RegistrationITKv4/MultiResImageRegistration1.cxx
我找了一个其他人做过的中文注释版

  1 #include "itkImageRegistrationMethodv4.h"
  2 #include "itkTranslationTransform.h"
  3 #include "itkMeanSquaresImageToImageMetricv4.h"
  4 #include "itkRegularStepGradientDescentOptimizerv4.h"
  5 #include "itkImageFileReader.h"
  6 #include "itkImageFileWriter.h"
  7 #include "itkPNGImageIOFactory.h"
  8 #include "itkResampleImageFilter.h"
  9 #include "itkCastImageFilter.h"
 10 #include "itkRescaleIntensityImageFilter.h"
 11 #include "itkSubtractImageFilter.h"
 12 /*****************************************************************************************************************
 13 * 本例子是一个图像配准的Demo
 14 *   0、创建了一个Command对象,用于监控配准的过程,被后面的对象调用
 15 *   1、首先要定义像素的维度以及像素类型:进进而链接参考图像以及浮动图像
 16 *   2、定义框架的基本组件:
 17 *               确定变换种类:TransformType:二维变换
 18 *               确定优化方法:OptimizerType:梯度下降
 19 *               确定相似度度量:MetricType:链接两个图像:浮动图像以及参考图像
 20 *   3、创建图像组件,并且通过创建上述框架,进而进行设置(链接)
 21 *   4、设置插值方法:LinearInterpolateImageFunction并且链接在一起
 22 *   5、6:通过ImageFileReader方法进行读取,链接到 registration并更新
 23 *   7、针对前面的TransformType进行实例化:平移变换用于配准SetInitialTransformParameters:用于设置初始值
 24 *   8、针对优化方法的设置:OptimizerType:前面在创建的时候已经设置了其梯度下降方法,此步骤用于对其微调:初始步长,收敛公差,最大迭代次数
 25 *   9、通过RegistrationParameterScalesFromPhysicalShift:将每一个配准要素链接到配准方法中执行,
 26 *   10、实例化Common对象,监控配准过程的执行,触发配准过程--迭代
 27 *   11、通过update函数触发配准的执行
 28 *   12、配准结果定义空间变换的参数序列:其结果由GetLastTransformParameters( )获得并且输出
 29 *           X、Y的变换:TranslationAlongX;TranslationAlongY
 30 *           迭代次数:numberOfIterations
 31 *           最后的结果:bestValue
 32 *       通过CompositeTransform:AddTransform将转换添加到堆栈的背面,并且拥有可优化的参数。
 33 *           也就是说:添加堆栈,副本??
 34 *   13、14、15、16、ResampleFilterType方法:
 35 *           用变换参数将两幅图像进行叠加比较,并设置重采样滤波器:输入两幅图像
 36 *           输出的是一个变换
 37 *           对滤波器进行相关参数的设置:大小、原点、间距、位置
 38 *           并通过CastFilterType:setInput:weiter进行相关的输出
 39 *           此时:这个图象就是配准结束后的图像
 40 *   17、通过itk::SubtractImageFilter对两幅图像进行比较:
 41 *           fixedImageReader;resampler
 42 *   18、对图像进行处理 itk::RescaleIntensityImageFilter:调节一下亮度;并进行输出
 43 *   19、一致性转发计算参考图像与正在移动图像之间的不同,输出图片5
 44 ******************************************************************************************************************/
 45 /*CommandIterationUpdate 类:
 46     继承Command,监视配准过程的执行。每调用一次,输出相应参数
 47         object类指向事件的观察者
 48         Execute方法,类似cellbake,回转
 49         observer方法:
 50 
 51   */
 52 class CommandIterationUpdate : public itk::Command
 53 {
 54 public:
 55     typedef CommandIterationUpdate   Self;
 56     typedef itk::Command             Superclass;
 57     typedef itk::SmartPointer<Self>  Pointer;
 58     itkNewMacro(Self);//宏,包装了所有的new()所有代码
 59 protected:
 60     CommandIterationUpdate() {};
 61 
 62 public:
 63 
 64     typedef itk::RegularStepGradientDescentOptimizerv4<double> OptimizerType;
 65     typedef const OptimizerType* OptimizerPointer;
 66 
 67     void Execute(itk::Object* caller, const itk::EventObject& event) ITK_OVERRIDE
 68     {
 69         Execute((const itk::Object*)caller, event);
 70     }
 71     //Object表示激活事件的对象,event表示被激活的事件
 72     void Execute(const itk::Object* object, const itk::EventObject& event) ITK_OVERRIDE
 73     {
 74         OptimizerPointer optimizer = static_cast<OptimizerPointer>(object);
 75         //checkEvent表示是否观察的对象
 76         if (!itk::IterationEvent().CheckEvent(&event))
 77         {
 78             return;
 79         }
 80 
 81         std::cout << optimizer->GetCurrentIteration() << " = ";
 82         std::cout << optimizer->GetValue() << " : ";
 83         std::cout << optimizer->GetCurrentPosition() << std::endl;
 84     }
 85 
 86 };
 87 
 88 
 89 int main()
 90 {
 91 
 92 
 93     //1、定义图像的维度以及像素执行
 94     const    unsigned int    Dimension = 2;//定义维度
 95     typedef  float           PixelType;//图像像素类型
 96     typedef itk::Image< PixelType, Dimension >  FixedImageType;//输入数据的类型:参考图像 
 97     typedef itk::Image< PixelType, Dimension >  MovingImageType;//浮动图像
 98 
 99 
100 
101     //2、定义配准框架的基本组件:变换、优化、测度配准组件
102     //用于2D图像的一个刚性配准,变换的唯一参数是:空间坐标类型
103    //配准
104     typedef itk::TranslationTransform< double, Dimension > TransformType;//把参考图像的空间映射到待配准图像的映射
105    //优化
106     typedef itk::RegularStepGradientDescentOptimizerv4<double> OptimizerType;//优化算法:牛顿梯度下降法
107    //度量
108     typedef itk::MeanSquaresImageToImageMetricv4<//相似度测量:均方根
109         FixedImageType,
110         MovingImageType >    MetricType;
111 
112 
113 
114     //3、该组件用用于连接其他组件
115     typedef itk::ImageRegistrationMethodv4<
116         FixedImageType,
117         MovingImageType,
118         TransformType   >    RegistrationType;
119 
120     MetricType::Pointer         metric = MetricType::New();
121     OptimizerType::Pointer      optimizer = OptimizerType::New();
122     RegistrationType::Pointer   registration = RegistrationType::New();
123     //连接组件:变换、优化组件
124     registration->SetMetric(metric);
125     registration->SetOptimizer(optimizer);
126 
127     //4、插值方法
128     typedef itk::LinearInterpolateImageFunction<//选择校对机类型,校对机会对配准图像在非网格位置的程度进行评估
129         FixedImageType,
130         double > FixedLinearInterpolatorType;
131     typedef itk::LinearInterpolateImageFunction<
132         MovingImageType,
133         double > MovingLinearInterpolatorType;
134     FixedLinearInterpolatorType::Pointer fixedInterpolator =//每一个配准要素需要其new创建
135         FixedLinearInterpolatorType::New();
136     MovingLinearInterpolatorType::Pointer movingInterpolator =
137         MovingLinearInterpolatorType::New();
138     metric->SetFixedInterpolator(fixedInterpolator);
139     metric->SetMovingInterpolator(movingInterpolator);
140 
141     //5、设置待配准图像以及变换区域
142     typedef itk::ImageFileReader< FixedImageType  >   FixedImageReaderType;
143     typedef itk::ImageFileReader< MovingImageType >   MovingImageReaderType;
144     FixedImageReaderType::Pointer   fixedImageReader = FixedImageReaderType::New();
145     MovingImageReaderType::Pointer  movingImageReader = MovingImageReaderType::New();
146 
147 
148     //6、读图像!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
149     itk::PNGImageIOFactory::RegisterOneFactory();
150     fixedImageReader->SetFileName("E:\\documents\\vs2019\\itk_demo\\build\\RelWithDebInfo\\data\\BrainProtonDensitySliceBorder20.png");//输入图像文件
151     movingImageReader->SetFileName("E:\\documents\\vs2019\\itk_demo\\build\\RelWithDebInfo\\data\\BrainProtonDensitySliceShifted13x17y.png");
152     //因为图像是从文件读取的,所以下面方法是用于获取图像数据的
153     //需要 itk::ImageRegistrationMethod 从 file readers 的输出获取输入
154     registration->SetFixedImage(fixedImageReader->GetOutput());
155     registration->SetMovingImage(movingImageReader->GetOutput());
156     //更新reader,确保其有效
157    // fixedImageReader->Update();
158    // movingImageReader->Update();
159 
160 
161     //7、平移变换用于配准
162     TransformType::Pointer movingInitialTransform = TransformType::New();
163     TransformType::ParametersType initialParameters(
164         movingInitialTransform->GetNumberOfParameters());
165     initialParameters[0] = 0.0;  // Initial offset in mm along X
166     initialParameters[1] = 0.0;  // Initial offset in mm along Y
167     movingInitialTransform->SetParameters(initialParameters);
168     registration->SetMovingInitialTransform(movingInitialTransform);
169 
170     //8、准备执行配准方法:对优化器参数进行微调
171     TransformType::Pointer   identityTransform = TransformType::New();
172     identityTransform->SetIdentity();
173 
174     registration->SetFixedInitialTransform(identityTransform);
175     //初始振幅的长度用SetMaximumStepLength( ) 定义
176     //建立迭代的次数需要谨慎。最大数用SetNumberOfIterations()定义:
177     optimizer->SetLearningRate(4);
178     optimizer->SetMinimumStepLength(0.001);//优化器的收敛公差
179     optimizer->SetRelaxationFactor(0.5);
180 
181     //9、将每一个配准要素连接到配准方法执行中
182     bool useEstimator = false;
183 
184     //useEstimator = atoi(argv[6]) != 0;
185 
186 
187     if (useEstimator)
188     {
189 
190 
191         typedef itk::RegistrationParameterScalesFromPhysicalShift<MetricType> ScalesEstimatorType;
192         ScalesEstimatorType::Pointer scalesEstimator = ScalesEstimatorType::New();
193         scalesEstimator->SetMetric(metric);
194         scalesEstimator->SetTransformForward(true);
195         optimizer->SetScalesEstimator(scalesEstimator);
196         optimizer->SetDoEstimateLearningRateOnce(true);
197     }
198     optimizer->SetNumberOfIterations(200);//最大迭代次数
199 
200 
201     //10、实例化commend对象,监视配准过程的执行,并处触发配准过程
202     CommandIterationUpdate::Pointer observer = CommandIterationUpdate::New();
203     optimizer->AddObserver(itk::IterationEvent(), observer);
204 
205 
206     const unsigned int numberOfLevels = 1;
207 
208     RegistrationType::ShrinkFactorsArrayType shrinkFactorsPerLevel;
209     shrinkFactorsPerLevel.SetSize(1);
210     shrinkFactorsPerLevel[0] = 1;
211 
212     RegistrationType::SmoothingSigmasArrayType smoothingSigmasPerLevel;
213     smoothingSigmasPerLevel.SetSize(1);
214     smoothingSigmasPerLevel[0] = 0;
215 
216     registration->SetNumberOfLevels(numberOfLevels);
217     registration->SetSmoothingSigmasPerLevel(smoothingSigmasPerLevel);
218     registration->SetShrinkFactorsPerLevel(shrinkFactorsPerLevel);
219 
220 
221 
222     //11、通过调用Update函数触发配准执行
223     try
224     {
225         registration->Update();
226         std::cout << "Optimizer stop condition: "
227             << registration->GetOptimizer()->GetStopConditionDescription()
228             << std::endl;
229     }
230     catch (itk::ExceptionObject& err)
231     {
232         std::cerr << "ExceptionObject caught !" << std::endl;
233         std::cerr << err << std::endl;
234         return EXIT_FAILURE;
235     }
236 
237     //12、配准结果是一系列定义空间变换的参数序列,结果由get获得
238     TransformType::ConstPointer transform = registration->GetTransform();
239     TransformType::ParametersType finalParameters = transform->GetParameters();
240     const double TranslationAlongX = finalParameters[0];//队列中每个元素对应着沿着一个空间维度的平移
241     const double TranslationAlongY = finalParameters[1];
242 
243     //优化器能够询问抵达收敛的迭代的实际次数并通过GetCurrentIteration()返回出来
244     const unsigned int numberOfIterations = optimizer->GetCurrentIteration();//迭代次数
245     //最终参数集合的图像量规值通过优化器的GetValue();
246     const double bestValue = optimizer->GetValue();//最优化的度量
247 
248     //将上述输出
249     std::cout << "Result = " << std::endl;
250     std::cout << " Translation X = " << TranslationAlongX << std::endl;//输出移动X的值
251     std::cout << " Translation Y = " << TranslationAlongY << std::endl;//输出移动Y的值
252     std::cout << " Iterations    = " << numberOfIterations << std::endl;//输出迭代次数
253     std::cout << " Metric value  = " << bestValue << std::endl;//输出优化的度量
254 
255     typedef itk::CompositeTransform<
256         double,
257         Dimension > CompositeTransformType;
258     CompositeTransformType::Pointer outputCompositeTransform =
259         CompositeTransformType::New();
260     outputCompositeTransform->AddTransform(movingInitialTransform);
261     outputCompositeTransform->AddTransform(
262         registration->GetModifiableTransform());
263 
264 
265     //13、用变换结果将待配准图映射到参考图像中
266     typedef itk::ResampleImageFilter<
267         MovingImageType,
268         FixedImageType >    ResampleFilterType;
269 
270     //14、创建一个重采样滤波器,输入待配准图像
271     ResampleFilterType::Pointer resampler = ResampleFilterType::New();
272     resampler->SetInput(movingImageReader->GetOutput());
273     //配准函数生成的变换也作为重采样滤波器的输入被传递
274     resampler->SetTransform(outputCompositeTransform);
275 
276     //15、ResampleImageFilter要求指定额外的参数,特别是输出图像的间 距、原点和大小
277     FixedImageType::Pointer fixedImage = fixedImageReader->GetOutput();
278     resampler->SetSize(fixedImage->GetLargestPossibleRegion().GetSize());//尺寸
279     resampler->SetOutputOrigin(fixedImage->GetOrigin());//原点
280     resampler->SetOutputSpacing(fixedImage->GetSpacing());//间距
281     resampler->SetOutputDirection(fixedImage->GetDirection());//位置
282     resampler->SetDefaultPixelValue(100);
283 
284     //16、滤波器的输出被传递给一个在文件中存储图像的writer
285     typedef unsigned char OutputPixelType;
286 
287     typedef itk::Image< OutputPixelType, Dimension > OutputImageType;
288 
289     typedef itk::CastImageFilter<//转化重采样的像素类型到最终的writer类型
290         FixedImageType,
291         OutputImageType >          CastFilterType;
292     typedef itk::ImageFileWriter< OutputImageType >  WriterType;
293     //调用new函数创建新的滤波器
294     WriterType::Pointer      writer = WriterType::New();
295     CastFilterType::Pointer  caster = CastFilterType::New();
296     writer->SetFileName("E:\\documents\\vs2019\\itk_demo\\build\\RelWithDebInfo\\output\\RegistrationITKv4Moving13x17yInputType.png");//写到文件夹位置
297     caster->SetInput(resampler->GetOutput());
298     writer->SetInput(caster->GetOutput());
299     writer->Update();//触发更新
300 
301     //17、参照图像和被变换的待配准图像很容易用itk::SubtractImageFilter比较
302     //pixel-wise滤波器 计算两幅输入的同源像素的不同:
303     typedef itk::SubtractImageFilter<
304         FixedImageType,
305         FixedImageType,
306         FixedImageType > DifferenceFilterType;
307 
308     DifferenceFilterType::Pointer difference = DifferenceFilterType::New();
309 
310     difference->SetInput1(fixedImageReader->GetOutput());//不同
311     difference->SetInput2(resampler->GetOutput());
312 
313     //18、两幅图像的不同也许比较暗,我们用下面方法对其进行调节亮度,使之更加的明显
314     typedef itk::RescaleIntensityImageFilter<
315         FixedImageType,
316         OutputImageType >   RescalerType;
317 
318     RescalerType::Pointer intensityRescaler = RescalerType::New();
319 
320     intensityRescaler->SetInput(difference->GetOutput());
321     intensityRescaler->SetOutputMinimum(0);
322     intensityRescaler->SetOutputMaximum(255);
323 
324     resampler->SetDefaultPixelValue(1);
325 
326 
327     //输出到另外一个位置(调亮)
328     WriterType::Pointer writer2 = WriterType::New();
329     writer2->SetInput(intensityRescaler->GetOutput());
330 
331     writer2->SetFileName("E:\\documents\\vs2019\\itk_demo\\build\\RelWithDebInfo\\output\\Moving13x17yInputType.png");
332     writer2->Update();
333 
334     //设置了一致性转换,计算参考图像的不同
335 
336     resampler->SetTransform(identityTransform);
337 
338     writer2->SetFileName("E:\\documents\\vs2019\\itk_demo\\build\\RelWithDebInfo\\output\\DifferenceBeforeRegistration.png");
339     writer2->Update();
340 
341     return EXIT_SUCCESS;
342 
343 }

4、结果

输入图像

 输出图像

 

标签:typedef,配准,itk,简单,使用,图像,Pointer,ITK
From: https://www.cnblogs.com/ybqjymy/p/17549977.html

相关文章

  • SimpleITK 简单使用
    SimpleITKITK是一个开源、跨平台的框架,提供给开发者增强功能的图像分析和处理套件(推荐使用)。Note:注意SimpleITK不支持中文,即路径中不能有中文X射线图像对应的读取1#@file:itk_p1.py2#@Time:2021/8/2816:273#@Author:wmz4importSimpleITKassitk......
  • 使用Clion开发esp32
    一、概述Clion是一款专门开发C以及C++所设计的跨平台的IDE。它是以IntelliJ为基础设计的,包含了许多智能功能来提高开发人员的生产力。这种强大的IDE帮助开发人员在Linux、OSX和Windows上来开发C/C++,同时它还能使用智能编辑器来提高代码质量、自动代码重构并且深度整合Cmake编......
  • Jmeter各组件介绍 及 使用(二)
    本篇主要讲述Jmeter的各个组件及简单使用,其中包括以下内容:一、测试片段及使用二、用户自定义变量  测试片段及使用测试片段添加--TestPlan--添加--测试片段--测试片段测试片段使用【第一种方式】--线程组--添加--逻辑控制器--include控制器测试片段使用【第二种方式】-......
  • 如何实现只有80对外开放的宿主机,使用docker实现mysql和redis和外部通信的具体操作步
    使用Docker实现MySQL和Redis与外部通信引言在现代软件开发中,往往需要使用到各种数据库和缓存技术。MySQL是一种常用的关系型数据库,而Redis是一种常用的内存缓存数据库。在部署这些数据库和缓存时,我们常常需要与外部的系统进行通信,例如通过网络连接,提供服务给其他系统。本文将介绍......
  • 如何实现在前端使用typescript的具体操作步骤
    在前端使用Typescript介绍Typescript是一种由微软开发的开源编程语言,它是JavaScript的超集,可以编译为纯JavaScript代码。Typescript增加了静态类型检查、面向对象编程和更好的工具支持,使得前端开发更加可靠和可维护。本文将教你如何在前端项目中使用Typescript。步骤下......
  • [Vue] 使用pdf-lib和@pdf-lib/fontkit 报错 fontkit.create is not a function
    描述:pdf-lib注册了@pdf-lib/fontkit后(pdfDoc.registerFontkit(fontkit)),内部调用了fontkit的create方法,但是这个方法不存在。我在控制台打印了下fontkit对象,发现fontkit包了一层default,即 fontkit.default.create(),所以找不到这个方法, pdf-lib使用的是 fo......
  • 使用Notepad++做下划线与驼峰的互换
    下划线转驼峰匹配规则:([a-z])_([a-z])替换规则:\1\U\2\E原:转换后:驼峰转下划线匹配规则:([a-z])([A-Z])替换规则:\1_\L\2\E原:转换后......
  • ubuntu20使用iptables-persistent libfakeroot libxtables-dev netfilter-persistent
    实施防火墙是保护服务器安全的重要一步。其中很大一部分是决定将对您的网络实施流量限制的单个规则和策略。像iptables这样的防火墙还允许您对应用规则的结构框架有发言权。在本指南中,您将学习如何构建防火墙,作为更复杂规则集的基础。该防火墙将主要关注提供合理的默认值和建立......
  • Linux 命令都无法使用
    配置javaJDK后,错误export之后linux所有命令无法使用经检查是因为jdk的环境变量PATH和调用命令的环境变量相同导致调用命令的环境变量无法使用解决方法1:直接在linux命令界面输入如下,然后回车导入环境变量以及常用命令的地址exportPATH=/usr/local/sbin:/usr/local/bin:/sbin:/......
  • 使用C#编写.NET分析器(完结)
    译者注这是在Datadog公司任职的KevinGosse大佬使用C#编写.NET分析器的系列文章之一,在国内只有很少很少的人了解和研究.NET分析器,它常被用于APM(应用性能诊断)、IDE、诊断工具中,比如Datadog的APM,VisualStudio的分析器以及Rider和Reshaper等等。之前只能使用C++编写,自从.NETNative......