跳转到内容

MINC/教程/编程04

来自维基教科书,开放世界中的开放书籍

将 minc 卷写入文件,以及关于切片缩放的说明

[编辑 | 编辑源代码]

本教程中的代码读取一个 MINC 文件,将每个体素加 1,然后将修改后的体积写回文件。

在进入代码之前,需要注意两点:(1) 这将覆盖作为第一个参数传递的文件,因此如果您实际尝试代码,请务必小心,(2) 这是完成任务的缓慢方式 - 请参阅下一个教程以了解完成相同目标的更明智的方式。

进入代码

#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;
  midimhandle_t dimensions[3];
  double        voxel, max;
  int           result;
  unsigned long v[3];
  unsigned int  sizes[3];
  miboolean_t   slice_scaling;

  /* open the volume - first command line argument */
  result = miopen_volume(argv[1], MI2_OPEN_RDWR, &minc_volume);
  /* check for error on opening */
  if (result != MI_NOERROR) {
    fprintf(stderr, "Error opening input file: %d.\n", result);
    return(1);
  }

到目前为止,没有新内容 - 变量已声明,体积已读取(注意 miopen_volume 的第二个参数 - 它现在允许读取和写入此体积)。

  /* check whether this volume uses slice scaling */
  miget_slice_scaling_flag(minc_volume, &slice_scaling);

第一个新的 minc 函数 miget_slice_scaling_flag 在此处出现。它执行一个非常简单的操作,询问体积是否使用切片缩放或全局缩放,并将输出置于布尔类型 miboolean_t 中。

缩放是 MINC 中的关键概念之一,此处介绍:MINC/教程/教程01(向下滚动到数据类型部分)。我们的程序需要知道是否使用切片缩放,原因如下:体积中表示的范围通常设置为遵循体积中存在的实际值范围。这意味着如果我们将所有体素增加 1,我们必须确保允许在体积中使用的值范围也更新。正如您将在下面看到的,更新范围取决于缩放是针对全局体积设置还是针对每个切片独立设置。

继续查看更多源代码

  /* get the dimension sizes */
  miget_volume_dimensions(minc_volume, MI_DIMCLASS_SPATIAL,
			  MI_DIMATTR_ALL, MI_DIMORDER_FILE,
			  3, dimensions);
  result = miget_dimension_sizes(dimensions, 3, sizes);
  printf("Volume sizes: %u %u %u\n", sizes[0], sizes[1], sizes[2]);

我们再次获取维度大小...

  /* global scaling: increment the maximum by one */
  if (slice_scaling == FALSE) {
    miget_volume_max(minc_volume, &max);
    miset_volume_max(minc_volume, max+1);
  }

...然后继续进行缩放问题的第一个部分。如果没有切片缩放,我们只需要更改全局缩放,这可以通过使用 miget_volume_max 获取体积最大值,并使用 miset_volume_max 将其设置为以前的 max+1 来完成。还有类似的函数用于 volume_min,我们也可以在这里合理地更新它们。

  /* loop over all voxels in the volume, add 1 to each voxel */
  for (v[0]=0; v[0] < sizes[0]; v[0]++) {
    /* slice scaling: increment the maximum of each slice by one */
    if(slice_scaling == TRUE) {
      miget_slice_max(minc_volume, v, 3, &max);
      miset_slice_max(minc_volume, v, 3, max+1);
    }
    for (v[1]=0; v[1] < sizes[1]; v[1]++) {
      for (v[2]=0; v[2] < sizes[2]; v[2]++) {
	miget_real_value(minc_volume, v, 3, &voxel);
	voxel += 1;
	miset_real_value(minc_volume, v, 3, voxel);
      }
    }
  }

这是代码的核心 - 我们使用维度大小信息遍历所有体素以了解何时终止每个循环,获取每个体素的实际值,将其增加 1,并使用 miset_real_value 将其写回体积。第一个维度是切片维度 - 因此,如果此体积使用切片缩放,我们将使用 miget_slice_max 获取切片最大值,将其增加 1 并使用 miset_slice_max 将其写回。

  /* closes the volume and makes sure all data is written to file */
  miclose_volume(minc_volume);

  return(0);
}

遍历完所有体素后,我们使用 miclose_volume 关闭体积。就这样,我们完成了。作为第一个参数读取的文件现在应该将其所有值增加 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;
  midimhandle_t dimensions[3];
  double        voxel, max;
  int           result;
  unsigned long v[3];
  unsigned int  sizes[3];
  miboolean_t   slice_scaling;

  /* open the volume - first command line argument */
  result = miopen_volume(argv[1], MI2_OPEN_RDWR, &minc_volume);
  /* check for error on opening */
  if (result != MI_NOERROR) {
    fprintf(stderr, "Error opening input file: %d.\n", result);
    return(1);
  }

  /* check whether this volume uses slice scaling */
  miget_slice_scaling_flag(minc_volume, &slice_scaling);

  /* get the dimension sizes */
  miget_volume_dimensions(minc_volume, MI_DIMCLASS_SPATIAL,
			  MI_DIMATTR_ALL, MI_DIMORDER_FILE,
			  3, dimensions);
  result = miget_dimension_sizes(dimensions, 3, sizes);
  printf("Volume sizes: %u %u %u\n", sizes[0], sizes[1], sizes[2]);

  /* global scaling: increment the maximum by one */
  if (slice_scaling == FALSE) {
    miget_volume_max(minc_volume, &max);
    miset_volume_max(minc_volume, max+1);
  }
  /* loop over all voxels in the volume, add 1 to each voxel */
  for (v[0]=0; v[0] < sizes[0]; v[0]++) {
    /* slice scaling: increment the maximum of each slice by one */
    if(slice_scaling == TRUE) {
      miget_slice_max(minc_volume, v, 3, &max);
      miset_slice_max(minc_volume, v, 3, max+1);
    }
    for (v[1]=0; v[1] < sizes[1]; v[1]++) {
      for (v[2]=0; v[2] < sizes[2]; v[2]++) {
	miget_real_value(minc_volume, v, 3, &voxel);
	voxel += 1;
	miset_real_value(minc_volume, v, 3, voxel);
      }
    }
  }
  
  /* closes the volume and makes sure all data is written to file */
  miclose_volume(minc_volume);

  return(0);
}
华夏公益教科书