跳轉到內容

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);
}
華夏公益教科書