MINC/教程/编程05
上一个教程遍历了体积中的每个体素,对其加了1,并将输出写回同一个体积。在这里我们将改进该示例:输出将写入一个新的体积,我们将使用超立方体进行数据处理。
超立方体是 minc 中的核心概念。它允许您从体积中提取任意(但连续)的数据块,对其进行操作,然后将其写回体积。这比单独获取每个体素快得多;但是,它需要更多的内存。
因此,继续示例:此代码获取一个体积,创建一个副本,该副本在所有方面都相同,只是每个体素都加了 1。新体积也将始终使用全局缩放,无论输入是否具有切片缩放。
#include <minc2.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
int main(int argc, char **argv) {
mihandle_t minc_volume, new_volume;
midimhandle_t dimensions[3], *dimensions_new;
double min, max;
int result, i;
unsigned long start[3], count[3];
unsigned int sizes[3];
double *slab;
if (argc != 3) {
fprintf(stderr, "Usage: input.mnc output.mnc\n");
}
/* open the volume - first command line argument */
result = miopen_volume(argv[1], MI2_OPEN_READ, &minc_volume);
/* check for error on opening */
if (result != MI_NOERROR) {
fprintf(stderr, "Error opening input file: %d.\n", result);
return(1);
}
/* get the dimension sizes */
miget_volume_dimensions(minc_volume, MI_DIMCLASS_SPATIAL,
MI_DIMATTR_ALL, MI_DIMORDER_FILE,
3, dimensions);
miget_dimension_sizes(dimensions, 3, sizes);
printf("Volume sizes: %u %u %u\n", sizes[0], sizes[1], sizes[2]);
到目前为止,一切都很好 - 这些代码对你来说应该都不陌生。请注意为新体积和新维度创建了两个新变量。
/* allocate new dimensions */
dimensions_new = malloc(sizeof(midimhandle_t) * 3);
/* copy the dimensions */
for(i=0; i < 3; i++) {
micopy_dimension(dimensions[i], &dimensions_new[i]);
}
在这里,我们为新体积的维度分配内存,并从旧体积复制维度定义。
/* allocate memory for the hyperslab - make it size of entire volume */
slab = malloc(sizeof(double) * sizes[0] * sizes[1] * sizes[2]);
start[0] = start[1] = start[2] = 0.0;
if (miget_real_value_hyperslab(minc_volume, MI_TYPE_DOUBLE,
start, count, slab) != MI_NOERROR) {
fprintf(stderr, "Error getting hyperslab\n");
return(1);
}
为超立方体分配了内存,并获得了超立方体 - 在这种情况下,超立方体是整个体积。关键函数是miget_real_value_hyperslab,它接受五个参数:minc 体积句柄,您想要数据所在的类型,开始的数组(在本例中全为零),计数的数组(体积大小)和写入数据的地址。
/* set min and max to the first voxel plus 1
* (since we add one to everything anyway) */
min = slab[0]+1;
max = slab[0]+1;
/* loop over all voxels */
for (i=0; i < sizes[0] * sizes[1] * sizes[2]; i++) {
/* increment voxel by 1 */
slab[i] += 1;
/* check if min or max should be changed */
if (slab[i] < min) {
min = slab[i];
}
else if (slab[i] > max) {
max = slab[i];
}
}
现在我们循环遍历超立方体中的每个体素(注意它是如何作为一维数组处理的),确保保留修改后的图像最小值和最大值。
/* create the new volume */
if (micreate_volume(argv[2], 3, dimensions_new, MI_TYPE_UBYTE,
MI_CLASS_REAL, NULL, &new_volume) != MI_NOERROR) {
fprintf(stderr, "Error creating new volume\n");
return(1);
}
然后我们使用micreate_volume创建实际的体积。它接受七个参数:文件名,维度数,实际维度的数组(通过上面的复制操作创建),数据类型(此处设置为无符号字节),数据类,特殊体积属性(此处设置为 NULL),以及体积句柄的地址。
/* create the data for the new volume */
if (micreate_volume_image(new_volume) != MI_NOERROR) {
fprintf(stderr, "Error creating volume data\n");
return(1);
}
现在,我们使用micreate_volume_image确保数据在 minc 体积句柄中创建。
/* set valid and real range */
miset_volume_valid_range(new_volume, 255, 0);
miset_volume_range(new_volume, max, min);
/* write the modified hyperslab to the file */
if (miset_real_value_hyperslab(new_volume, MI_TYPE_DOUBLE,
start, count, slab) != MI_NOERROR) {
fprintf(stderr, "Error setting hyperslab\n");
return(1);
}
然后我们设置有效范围 - 从 0 到 255,因为这是无符号字节数据 - 以及体积范围,这是通过在循环遍历体素时跟踪最小值和最大值确定的。超立方体使用miset_real_value_hyperslab放回体积,它接受与miget_real_value_hyperslab完全相同的参数。
/* closes the volume and makes sure all data is written to file */
miclose_volume(minc_volume);
miclose_volume(new_volume);
/* free memory */
free(dimensions_new);
free(slab);
return(0);
}
最后,我们关闭体积,释放已分配的内存并退出。
#include <minc2.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
int main(int argc, char **argv) {
mihandle_t minc_volume, new_volume;
midimhandle_t dimensions[3], *dimensions_new;
double min, max;
int result, i;
unsigned long start[3], count[3];
unsigned int sizes[3];
double *slab;
if (argc != 3) {
fprintf(stderr, "Usage: input.mnc output.mnc\n");
}
/* open the volume - first command line argument */
result = miopen_volume(argv[1], MI2_OPEN_READ, &minc_volume);
/* check for error on opening */
if (result != MI_NOERROR) {
fprintf(stderr, "Error opening input file: %d.\n", result);
return(1);
}
/* get the dimension sizes */
miget_volume_dimensions(minc_volume, MI_DIMCLASS_SPATIAL,
MI_DIMATTR_ALL, MI_DIMORDER_FILE,
3, dimensions);
miget_dimension_sizes(dimensions, 3, sizes);
printf("Volume sizes: %u %u %u\n", sizes[0], sizes[1], sizes[2]);
/* allocate new dimensions */
dimensions_new = malloc(sizeof(midimhandle_t) * 3);
/* copy the dimensions */
for(i=0; i < 3; i++) {
micopy_dimension(dimensions[i], &dimensions_new[i]);
}
start[0] = start[1] = start[2] = 0;
for (i=0; i < 3; i++) {
count[i] = (unsigned long) sizes[i];
}
/* allocate memory for the hyperslab - make it size of entire volume */
slab = malloc(sizeof(double) * sizes[0] * sizes[1] * sizes[2]);
if (miget_real_value_hyperslab(minc_volume, MI_TYPE_DOUBLE,
start, count, slab) != MI_NOERROR) {
fprintf(stderr, "Error getting hyperslab\n");
return(1);
}
/* set min and max to the first voxel plus 1
* (since we add one to everything anyway) */
min = slab[i]+1;
max = slab[i]+1;
/* loop over all voxels */
for (i=0; i < sizes[0] * sizes[1] * sizes[2]; i++) {
/* increment voxel by 1 */
slab[i] += 1;
/* check if min or max should be changed */
if (slab[i] < min) {
min = slab[i];
}
else if (slab[i] > max) {
max = slab[i];
}
}
/* create the new volume */
if (micreate_volume(argv[2], 3, dimensions_new, MI_TYPE_UBYTE,
MI_CLASS_REAL, NULL, &new_volume) != MI_NOERROR) {
fprintf(stderr, "Error creating new volume\n");
return(1);
}
/* create the data for the new volume */
if (micreate_volume_image(new_volume) != MI_NOERROR) {
fprintf(stderr, "Error creating volume data\n");
return(1);
}
/* set valid and real range */
miset_volume_valid_range(new_volume, 255, 0);
miset_volume_range(new_volume, max, min);
/* write the modified hyperslab to the file */
if (miset_real_value_hyperslab(new_volume, MI_TYPE_DOUBLE,
start, count, slab) != MI_NOERROR) {
fprintf(stderr, "Error setting hyperslab\n");
return(1);
}
/* closes the volume and makes sure all data is written to file */
miclose_volume(minc_volume);
miclose_volume(new_volume);
/* free memory */
free(dimensions_new);
free(slab);
return(0);
}