MINC/软件开发/EZMINC/教程
外观
#include "minc_1_rw.h"
using namespace minc;
//...
try
{
minc_1_reader rdr;
rdr.open(input_minc_file);
} catch (const minc::generic_error & err) {
std::cerr << "Got an error at:" << err.file () << ":" << err.line () << std::endl;
std::cerr << err.msg()<<std::endl;
}
Minc 文件是一个复杂的结构,许多参数必须设置正确才能生成有意义的文件,最简单的方法是从另一个 minc 文件中复制它们
minc_1_writer wrt;
wrt.open(output_minc_file,example_minc_file);
或者,如果另一个文件已经打开:syntaxhighlight lang="text"
wrt.open(output_minc_file,rdr);
</syntaxhighlight>
或者,如果只需要保留尺寸(创建一个具有浮点类型体素和 2D 切片的 minc 文件):syntaxhighlight lang="text"
wrt.open(output_minc_file,rdr.info(),2,NC_FLOAT);
</syntaxhighlight>
- 确定维度数:
rdr.dim_no()
- 计算矩阵大小、分辨率
syntaxhighlight lang="text"
std::cout<<"Dimensions:"<<std::endl << " Vector:"<<rdr.ndim(0)<<std::endl << " X:"<<rdr.ndim(1)<<" step:"<<rdr.nspacing(1)<<" start:"<<rdr.nstart(1)<<std::endl << " Y:"<<rdr.ndim(2)<<" step:"<<rdr.nspacing(2)<<" start:"<<rdr.nstart(2)<<std::endl << " Z:"<<rdr.ndim(3)<<" step:"<<rdr.nspacing(3)<<" start:"<<rdr.nstart(3)<<std::endl << " Time:"<<rdr.ndim(4)<<" step:"<<rdr.nspacing(4)<<" start:"<<rdr.nstart(4)<<std::endl;
</syntaxhighlight> 注意 这些是物理参数,不依赖于 minc 文件中信息存储的方式
- 输出方向余弦矩阵
for(int i=0;i<3;i++)
{
if(rdr.have_dir_cos(i))
for(int j=0;j<3;j++)
std::cout<<rdr.ndir_cos(i,j)<<" ";
std::cout<<std::endl;
}
- 读取 minc 文件历史记录
std::cout<<"Minc history:"<<rdr.history().c_str()<<std::endl;
- 读取字符串属性
std::cout<<"Subject name:"<<rdr.att_value_string("patient","full_name").c_str()<<std::endl;
- 读取双精度属性
syntaxhighlight lang="text"
std::cout<<"Echo time:"<<rdr.att_value_double("acquisition","echo_time")[0]<<std::endl;
</syntaxhighlight> 注意:读取双精度属性按值返回 std::vector<double>
图像数据存储为给定类型的多维值数组。数组按切片组织(整个文件可能只有一个切片),存储在 minc 文件中的值可能是归一化的,请参阅MINC/参考以获取完整详细信息。EZMINC 的开发旨在隐藏数据表示的复杂性,使其远离程序员,但同时允许对数据存储方式进行完全控制,如果需要的话。有几种方法可以使用 EZMINC 库从文件中读取图像信息
- 最简单的方法是将整个体积复制到内存中的多维数组中。通常这是最方便的方法
- 读取表示实值的体积(将它们解释为浮点数)
syntaxhighlight lang="text"
#include <minc_1_simple.h> #include <minc_1_simple_rw.h> using namespace minc; //.... simple_volume<float> src; minc_1_reader rdr; rdr1.open(input_file); load_simple_volume<float>(rdr,src); std::cout<<"Voxel at voxel coordinates (1,2,3) is "<<src.get(1,2,3)<<std::endl; //using safe_get to make sure that we don't read beyond the allocated space std::cout<<"Voxel at world coordinates (1,2,3) is "<<src.safe_get(src.world_to_voxel(IDX<double>(1.0,2.0,3.0)))<<std::endl;
</syntaxhighlight>
- 读取具有二进制掩码(或离散标签)的体积
#include <minc_io_simple_volume.h>
#include <minc_1_simple.h>
#include <minc_1_simple_rw.h>
using namespace minc;
//....
simple_volume<unsigned char> src;
minc_1_reader rdr;
rdr1.open(input_file);
load_simple_volume<unsigned char>(rdr,src);
std::cout<<"Labels at (1,2,3) is "<<(int)src.get(1,2,3)<<std::endl;
- 读取 4D 体积
simple_4d_volume<float> vol;
load_4d_volume<float>(rdr,vol);
std::cout<<"Voxel at voxel coordinates (1,2,3) slice 0 is "<<src.get(1,2,3,0)<<std::endl;
- 读取整个 minc 文件作为单个连续缓冲区,以向量维度为最快变化(如果存在),X、Y、Z 和时间为最慢变化(如果存在)的方式组织
#include <minc_1_rw.h>
#include <minc_1_simple.h>
using namespace minc;
//...
minc_1_reader rdr;
rdr.open(input_file);
rdr.setup_read_float(); //we have to setup the file to a proper data type
size_t size=1;
for(i=0;i<rdr.dim_no();i++)
size*=rdr.dim(i).length;
float* array=new float[size];
load_standard_volume<float>(rdr,array);
- 逐个体素读取整个 minc 文件,按照数据在文件中存储的顺序。当处理大量输入文件并且将它们全部一起存储在内存中存在问题时,此方法非常有用
#include <minc_1_rw.h>
#include <minc_1_simple.h>
using namespace minc;
//...
minc_1_reader rdr;
rdr.open(input_file);
rdr.setup_read_float(); //we have to setup the file to a proper data type
minc_input_iterator<float> in(rdr);
double avg=0;
int cnt=0;
for(in.begin();!in.last();in.next())
{
avg+=in.value()
cnt++;
}
std::cout<<"Average value="<<avg/cnt<<std::endl;
- 最低级接口,按数据在文件中存储的顺序逐片读取 minc 文件
#include <minc_1_rw.h>
using namespace minc;
//...
minc_1_reader rdr;
rdr.open(input_file);
rdr.setup_read_float(); //we have to setup the file to a proper data type
float* slice_buffer=new float[rdr.slice_len()];
for(rdr.begin();!rdr.last();rdr.next_slice())//minc_1_reader is actually an iterator!
{
rdr.read(slice_buffer);
//do something usefull with the data
}
- 复制历史记录 注意:如果使用 minc_1_writer::open 的第一种形式,历史记录将自动复制
wrt.copy_headers(rdr);
- 将新行追加到 MINC 历史记录
wrt.append_history("minc_test was used to produce this file\n");
- 写入字符串属性
wrt.insert("patient","full_name","John Doe");
- 写入双精度属性
wrt.insert("acquisition","echo_time",0.120); //echo time was 120ms
- 写入双精度值数组
std::vector<double> bvalues(64); //... wrt.insert("acquisition","bvalues",bvalues);
- 从另一个 minc 文件复制所有头
wrt.copy_headers(rdr);
- 最简单的接口,使用 simple_volume 或 simple_4d_volume
simple_volume<float> output_vol;
//...
minc_1_writer wrt;
wrt.open(output_minc,rdr);
save_simple_volume<float>(wrt,output_vol);
simple_4d_volume<float> output_vol;
//...
minc_1_writer wrt;
wrt.open(output_minc,rdr);
save_4d_volume(wrt,vol);
- 从连续数组写入图像
float *output_vol=new float[size];
//...
minc_1_writer wrt;
wrt.open(output_minc,rdr);
wrt.setup_write_float(); //have to setup the data type
save_standard_volume<float>(wrt,output_vol);
- 使用输出迭代器
//adding a value c to all voxels
minc_1_reader rdr;
rdr.open(input_minc);
rdr.setup_read_float();
minc_1_writer wrt;
wrt.open(output_minc,rdr);
wrt.setup_write_float();
minc_input_iterator<float> in(rdr);
minc_output_iterator<float> out(wrt);
for(in.begin(),out.begin();!in.last();in.next(),out.next())
{
out.value(in.value()+c);
}
- 最低级,逐片写入图像
#include <minc_1_rw.h>
using namespace minc;
//...
minc_1_reader rdr;
rdr.open(input_file);
rdr.setup_read_float(); //we have to setup the file to a proper data type
minc_1_writer wrt;
wrt.open(output_minc,rdr);
wrt.setup_write_float();
float* slice_buffer=new float[rdr.slice_len()];
for(rdr.begin(),wrt.begin();!rdr.last();rdr.next_slice(),wrt.next_slice())
{
rdr.read(slice_buffer);
//do something usefull with the data
wrt.write(slice_buffer);
}