文章图片转自 https://blog.csdn.net/ljp1919/article/details/41487505
头文件:
#include "itkImage.h" //用来创建图像对象
#include "itkImageFileReader.h" //用来读图像文件
#include "itkImageFileWriter.h"//用来写图像文件
ImageFileReader< TOutputImage, ConvertPixelTraits >读取器模板类
对于这两个参数准确的定义我并没有找到,网上的例子没用到这种实例化方法,而是利用图像类型(ImageType)作为模板参数,定义数据加载到内存中后如何表示。除了将文件的像素类型转换为ImageFileReader的像素类型之外,读取器不会对像素数据应用任何转换。
using PixelType = short;
constexpr unsigned int Dimension = 2;
using ImageType = itk::Image<PixelType, Dimension>;
using ReaderType = itk::ImageFileReader<ImageType>;
此类型不必与文件中存储的类型对应,但必须足以准确的描述图像。
常见的格式及支持的像素格式如下图:
之后依旧利用智能指针和New()方法来创建一个reader对象。
ReaderType::Pointer reader = ReaderType::New();
读取器所需的最小信息是要加载到内存中的图像的文件名,我们通过SetFileName()来设置我们需要读的文件名,(这里的文件格式通过扩展名来判断),此外,用户还可以使用 ImageIOBase 类显式指定数据格式。
const char * filename = "文件名(最好使用绝对路径)";
reader->SetFileName(filename);
itk::ImageFileWriter< TInputImage > 写入器模板类
using WriterType = itk::ImageFileWriter<ImageType>;
WriterType::Pointer writer = WriterType::New();
const char * outputFilename = “输出图像的路径”;
writer->SetFileName(outputFilename);
ITK的数据处理管道结构
ITK中的数据处理对象分为3种类型
1)Source类型对象的输出为数据对象,包括各种图像文件读取类
2)Filter类型对象以一个或多个数据对象作为输入,然后输出一个或多个数据对象,包括数据处理算法类
3)Mapper类型对象是管道处理的最后一步,它将最终处理结果存到硬盘
负责读取和写入图像的类位于数据处理管道的开头和结尾。这些类称为数据源(读取器)和数据接收器(写入器)。一般来说,它们被称为过滤器,尽管读卡器没有管道输入,而编写器没有管道输出。
我们现在可以将这些读写器连接到过滤器以创建管道。例如,我们可以通过将读卡器的输出传递到写入器的输入来创建一个短管道。
writer->SetInput(reader->GetOutput());
管道的执行是由在最后一个对象中调用Update() 方法触发的,在本例中,最终的数据管道对象是writer。
try
{
writer->Update();
}
catch (itk::ExceptionObject & err)
{
std::cerr << "ExceptionObject caught !" << std::endl;
std::cerr << err << std::endl;
return EXIT_FAILURE;
}
插拔式工厂
官网上图像读写的例子到这里就结束了,我没试过读别的格式的文件可不可以,我测试使用的图片格式是jpg,一直在写入的时候报异常,说是内存错误
0x00007FFA843CA839 处(位于 Project1.exe 中)引发的异常: Microsoft C++ 异常: itk::ImageFileWriterException,位于内存位置 0x000000213DCFF438 处。
最后我发现在InsightSoftwareGuide-Book提到了类似这个问题,就是插拔式工厂。
从用户的观点看,读写文件的类是 itk::ImageFileReader 和 itk::ImageFileWriter。但是这两个类不知道读或写特殊文件格式(PNG,DICOM …)的细节,它们所做的就是:分派用户的要求给知道文件格式细节的类—— itk::ImageIO 。
图像文件 reader/writer 必须决定由哪一 个 ImageIO 类去执行 IO 操作。这个通过传递文件名给itk::ImageIOFactory 和确定读或写用户指定的文件的能力的 ImageIO 的子类来做。
来源于 ImageIO 的每一个类必须提供一个达到 ImageIO 类要求的关联的工厂类。
例如 JPG 文件,有一个知道如何读文件的 itk::JPGImageIO 的对象和一个能够构建 JPGImageIO 对象并能返回指向它的一个指针的 itk::JPGImageIOFactory 类。
我的理解就是,校长[reader,writer] 负责接受来报名补习班的学生[要读写的图片],按照他想学的 科目[格式] 安排 老师[xxxxfactory] 授课,如果没有对应科目的老师,就无法接收这个学生,,大概就这个意思。
所以我们要加入头文件
#include "itkJPEGImageIOFactory.h"
然后在写入图像之前注册对应格式的factory
itk::JPEGImageIOFactory::RegisterOneFactory();
程序就可以运行了,运行结果如下(bird222.jpg就是通过本程序写出的图像
源码
#include "itkImage.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkJPEGImageIOFactory.h"
int main(int, char * argv[])
{
typedef unsigned char PixelType;
const unsigned int Dimension = 2;
typedef itk::Image< PixelType, Dimension > ImageType;
typedef itk::ImageFileReader< ImageType > ReaderType;
typedef itk::ImageFileWriter< ImageType > WriterType;
ReaderType::Pointer reader = ReaderType::New();
WriterType::Pointer writer = WriterType::New();
reader->SetFileName("E:\\img\\bird.jpg");
writer->SetFileName("E:\\img\\bird22.jpg");
itk::JPEGImageIOFactory::RegisterOneFactory();
writer->SetInput(reader->GetOutput());
try
{
writer->Update();
}
catch (itk::ExceptionObject & err)
{
std::cerr << "ExceptionObject caught !" << std::endl;
std::cerr << err << std::endl;
return EXIT_FAILURE;
}
return 0;
}
附赠一个格式转换的源码
这个实现就很简单了,只要把两种格式对应的factory注册,改变你读写文件的扩展名就好了。我的是将jpg格式转换为BMP格式
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkImageIOFactory.h"
#include "itkBMPImageIOFactory.h"
#include "itkJPEGImageIOFactory.h"
#include <iostream>
int main(int argc, char *argv[])
{
itk::BMPImageIOFactory::RegisterOneFactory();
itk::JPEGImageIOFactory::RegisterOneFactory();
typedef itk::Image< unsigned char, 2 > ImageType;
typedef itk::ImageFileReader< ImageType > ReaderType;
typedef itk::ImageFileWriter< ImageType > WriterType;
ReaderType::Pointer reader = ReaderType::New();
WriterType::Pointer writer = WriterType::New();
reader->SetFileName("E:\\img\\bird.jpg");
writer->SetFileName("E:\\img\\bird2.BMP");
writer->SetInput(reader->GetOutput());
try
{
writer->Update();
}
catch (itk::ExceptionObject & err)
{
std::cerr << "ExceptionObject caught !" << std::endl;
std::cerr << err << std::endl;
return EXIT_FAILURE;
}
system("pause");
return 0;
}
运行结果:
参考:https://blog.csdn.net/ljp1919/article/details/41487505
https://itk.org/Doxygen/html/Examples_2IO_2ImageReadWrite_8cxx-example.html
https://www.cnblogs.com/fantianliang/p/11964899.html