MINC/軟體開發/MINC1-程式設計師指南
MINC 檔案格式(醫學影像 NetCDF)基於 Unidata 程式中心釋出的 NetCDF 檔案格式(網路通用資料格式)。NetCDF 提供了一個軟體介面,用於以機器無關的方式在檔案中儲存命名、多維變數。這個介面使應用程式擺脫了可移植性和檔案結構的困擾,並鼓勵使用自描述形式的資料。
檔案中每個 NetCDF 多維變數都由名稱、維度和屬性描述。例如,儲存在檔案中的影像可以作為位元組資料儲存在一個名為“image”的變數中,其維度為“x”和“y”(每個長度為 256),並且有一個名為“long_name”的屬性,它是一個字串,描述了影像的內容。一個檔案中可以儲存多個變數,每個變數可以有多個屬性。維度獨立於變數存在,並且可以對多個變數進行下標。
MINC 在 NetCDF 介面之上提供了三項功能。它提供了一套適用於醫學成像的維度、變數和屬性名稱標準;它提供了一些補充 NetCDF 介面的便利函式(並非特定於 MINC 約定);它還提供了一些用於使用 MINC 檔案的便利函式。
(有關完整描述,請參閱NetCDF 使用者指南)。
在考慮 NetCDF 介面時,檢視一個示例檔案會很有用。幸運的是,NetCDF 包提供了一些實用程式(ncdump 和 ncgen),用於將二進位制 NetCDF 檔案轉換為名為 CDL 的 ASCII 格式。下面是一個簡單的 NetCDF 檔案,由 ncdump 轉換為 CDL 表示法。
netcdf test {
dimensions:
ycoord = 3 ;
xcoord = 4 ;
variables:
double image(ycoord, xcoord) ;
image:long_name = "My favorite tiny image" ;
double xcoord(xcoord) ;
data:
image =
1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12 ;
xcoord = 100, 200, 300, 400 ;
}
示例檔案儲存了一個 3 x 4 的雙精度值影像。首先定義了維度:xcoord 和 ycoord。維度可以表示物理維度,如 x 座標、y 座標等,也可以表示抽象事物,如查詢表索引。每個維度都有一個名稱和一個長度,當與其他維度組合時,定義了變數的形狀——變數影像由ycoord 和xcoord 進行下標。
維度也可以跨變數使用,將它們相互關聯。例如,如果該檔案包含另一個也由ycoord 和xcoord 進行下標的影像,那麼我們會得到重要資訊,即這兩個變數在同一個網格上進行取樣。此外,可以透過建立與維度同名的變數(如示例中的xcoord)來定義座標系,從而給出影像中每個點的 x 座標。
變數是在 CDL 檔案中定義的下一個內容。每個變數都有一個名稱、資料型別和一個由維度列表(每個變數最多為MAX_VAR_DIMS = 32 個維度)指定的形狀。資料型別為NC_CHAR、NC_BYTE、NC_SHORT、NC_INT、NC_FLOAT和NC_DOUBLE。有關每個變數的資訊都儲存在屬性中。屬性“long_name”給出了描述變數“image”的字元字串。屬性是標量或上述六種型別之一的向量(字元字串是型別為NC_CHAR的向量)。
使用 NetCDF 進行程式設計非常簡單。上面列出的檔案是由以下程式生成的。
#include <netcdf.h>
#define THE_NAME "My favorite tiny image"
static double vals[][4]={
1.0, 2.0, 3.0, 4.0,
5.0, 6.0, 7.0, 8.0,
9.0,10.0,11.0,12.0
};
static int ysize=sizeof(vals)/sizeof(vals[0]);
static int xsize=sizeof(vals[0])/sizeof(vals[0][0]);
static double xcoord[]={100.,200.,300.,400.};
main()
{
int cdf, img, xvar;
int dim[MAX_VAR_DIMS];
long count[MAX_VAR_DIMS], start[MAX_VAR_DIMS];
/* Create the file */
cdf=nccreate("test.cdf",NC_CLOBBER);
/* Define the dimensions */
dim[0]=ncdimdef(cdf, "ycoord", ysize);
dim[1]=ncdimdef(cdf, "xcoord", xsize);
/* Define the variables */
img=ncvardef(cdf, "image", NC_DOUBLE, 2, dim);
xvar=ncvardef(cdf,"xcoord", NC_DOUBLE, 1, &dim[1]);
/* Add an attribute */
ncattput(cdf, img, "long_name", NC_CHAR, strlen(THE_NAME)+1, THE_NAME);
/* End definition mode */
ncendef(cdf);
/* Write the variable values */
start[0]=start[1]=0;
count[0]=ysize; count[1]=xsize;
ncvarput(cdf, img, start, count, vals);
ncvarput(cdf, xvar, &start[1], &count[1], xcoord);
ncclose(cdf);
}
程式的第一行可執行程式碼建立了一個新的 NetCDF 檔案。開啟的檔案要麼處於“define”模式,要麼處於“data”模式。在 define 模式下,可以定義維度、變數和屬性,但不能寫入或讀取變數資料。在 data 模式下,可以寫入或讀取變數值,但不能對維度或變數進行任何更改,並且屬性只能在它們已存在的情況下寫入,並且在寫入時不會變得更大。新建立的檔案會自動處於 define 模式。
在呼叫 nccreate 後的行中定義了檔案中的維度和變數。請注意,NetCDF 檔案、維度和變數都由在建立它們時返回的整數標識。這些 ID 隨後用於引用每個物件。變數 image 的屬性“long_name”僅由其名稱標識。
一旦所有內容都定義好,ncendef 會將檔案置於 data 模式,然後寫入值。要寫入的值由一個起始索引向量和一個每個維度中要寫入的值數量向量定義。這在變數中定義了一個多維矩形,稱為超平面。在 C 介面中,向量的第一個元素引用變數變化最慢的索引,因此在本例中,陣列 vals 中的xcoord 變化最快。在 FORTRAN 介面中,約定是第一個下標變化最快。這些約定遵循語言對多維陣列的約定。
可以使用僅 NetCDF 函式呼叫來構建 MINC 格式檔案,但是提供了一個 C 包含檔案來促進(並幫助確保)符合標準。這個檔案定義了有用的常量、標準維度、變數和屬性名稱以及一些屬性值。它還聲明瞭在 minc 便利函式庫中定義的函式,這些函式旨在使應用程式開發人員的生活更輕鬆。
已經提出了各種檔案格式的要求。其中一項要求清單如下:協議應該:1) 簡單,2) 自描述,3) 可維護,4) 可擴充套件,5) N 維,以及 6) 具有通用資料結構。NetCDF 格式滿足所有這些要求,表明它是一個良好的起點。但是,我會在清單中新增更多要求。上述清單中隱含的要求是,應該有一個訪問資料的標準(如何獲取患者姓名)——NetCDF 沒有提供。此外,一個有用的格式應該附帶一個軟體介面,使其易於使用,尤其是在開發環境中。最後,儲存許多關聯資訊的格式還應該提供一些資料組織方式。
MINC 格式嘗試在 NetCDF 格式中新增這些內容。
醫學影像通常會生成包含大量輔助資料的檔案(患者資訊、影像資訊、採集資訊等)。為了以一種有效的方式組織這些資訊,MINC 使用變數將相關的屬性分組在一起。變數本身可能包含或不包含有用的資料。例如,變數 MIimage 包含影像資料,並具有與該資料相關的屬性。變數 MIpatient 沒有相關的變數資料,但用於將所有描述患者的屬性(姓名、出生日期等)分組在一起。這種型別的變數被稱為組變數。
對應於維度的變數被稱為維度變數,它們描述與維度相對應的座標系。例如,MIxspace 是一個維度和變數,描述了其他變數的 x 座標。
NetCDF 規範允許這些維度變數指定每個點的座標,但沒有描述該點處樣本的寬度。MINC 提供了維度寬度變數的約定,例如 MIxspace_width,用於提供此資訊。
最後,可以擁有在變數的一些維度上變化的屬性。例如,如果我們有一個影像資料體,在 MIxspace、MIyspace 和 MIzspace 上變化,我們可能想要一個屬性,它給出每個影像的最大值,在 MIzspace 上變化。為了實現這一點,我們使用一個稱為變數屬性的變數,它由影像變數的一個屬性指向。
因此,MINC 引入了幾種型別的變數:組變數、維度變數、維度寬度變數和變數屬性。
MINC 嘗試透過組變數的層次結構提供一定程度的資料組織。如上所述,屬性根據型別在組變數中分組。每個組變數可以有一個 MIparent 和一個 MIchildren 屬性——前者指定另一個變數的名稱,該變數在層次結構中高於此變數,後者指定一個換行符分隔的變數列表,這些變數在層次結構中低於此變數。層次結構的根部是 MIrootvariable 變數,沒有父級。雖然沒有必要使用這種結構,但它可以提供一種機制來組織大量資訊。
NetCDF 格式沒有說明變數和維度命名約定,關於屬性名稱的說明也很少。它確實提供了一些標準,例如用於描述變數的屬性“long_name”,這些標準已被 MINC 標準採用。MINC 定義了一組用於常用實體的標準名稱,包含檔案定義了指定這些名稱的常量。這些在 MINC 參考手冊中有詳細描述。其中最有趣的是 MIimage,它是用於在檔案中儲存實際影像資料的變數的名稱。
MINC 標準賦予了影像概念一些特殊狀態。NetCDF 中沒有固有的內容表明特定維度有任何特殊狀態,但在成像環境中,對哪些內容可以在哪些維度上變化施加限制可能很方便。例如,要求用於指定如何重新縮放影像的變數(參見後面的畫素值部分)不隨影像維度變化,這意味著我們可以將影像視為一個簡單的單元。在最簡單的情況下,影像維度僅僅是 MIimage 變數的兩個變化最快的維度。
允許向量場——在每個點都有一個向量值的影像或影像體,也可能很有幫助。RGB 影像就是一個簡單的向量場示例。在空間中的每個點,都有三個值:紅色、綠色和藍色。維度 MIvector_dimension 用於向量的分量,它應該是 MIimage 變數中變化最快的維度。如果存在,則 MIimage 的三個變化最快的維度就是影像維度。
MINC 標準定義了空間座標相對於患者的方位。檔案可以自由地以所需的方向儲存資料,但在醫學影像環境中,正世界座標具有明確的含義。標準是正 x 軸從患者的左側指向右側,正 y 軸從後指向前,正 z 軸從下指向上。
元素索引到世界座標的轉換使用維度變數屬性 MIdirection_cosines、MIstep 和 MIstart 完成。如果方向餘弦是 c=(c_x, c_y, c_z),則沿著軸的相鄰元素之間的向量是 step x c。如果 start(i) 和 c(i) 是維度 i(MIxspace、MIyspace 和 MIzspace 之一)的 MIstart 和 MIdirection_cosines 屬性,則影像變數的第一個元素位於世界座標 \sum_i start(i) c(i) 處。
如果方向餘弦不存在,則假定 MIxspace 為 (1,0,0),MIyspace 為 (0,1,0),MIzspace 為 (0,0,1)。方向餘弦是單位向量,應該歸一化。此外,step 屬性應該包含關於軸翻轉(負或正)的資訊,而不是方向餘弦。
在醫學影像中,畫素值通常以位元組或短整型儲存,但通常也會與每個畫素關聯一個真實值。這個真實值是透過與每個影像或影像體相關的比例因子和偏移量獲得的。MINC 標準指示瞭如何解釋畫素值。
MIimage 變數中的影像資料可以儲存為位元組、短整型、整型(32 位)、浮點型或雙精度型。NetCDF 規範使用屬性 MIvalid_range 或 MIvalid_max 和 MIvalid_min 來指示變數中可以找到的值範圍。例如,對於短整型值,我們可能有一個 0 到 32000 的有效範圍。為了將這些整數轉換為真實值,我們可以使用比例因子和偏移量。但是,如果資料在 23 到 228 的範圍內轉換為位元組,那麼這些值將不得不改變。
如果我們指定一個影像最大值和最小值,MIvalid_max 和 MIvalid_min 應該透過適當的比例因子和偏移量對映到該值,那麼我們就可以轉換型別和有效範圍,而無需更改真實最大值和最小值。為了允許影像中的最大動態範圍,我們使用變數 MIimagemax 和 MIimagemin 來儲存真實最大值和最小值——這些值可以在 MIimage 的任何非影像維度上變化。
MINC 提供了許多便利函式,這些函式與醫學影像無關,但可以使使用 NetCDF 檔案變得更容易。NetCDF 格式的缺點之一是資料可以以任何形式(位元組、短整型、整型、浮點型、雙精度型)出現,呼叫程式必須處理一般情況。MINC 沒有限制這一點,而是提供了用於轉換型別的函式。
第一組便利函式用於型別轉換。
miattget- 讀取一個屬性向量,指定所需的數值型別和要讀取的最大值數。miattget1- 讀取指定型別的一個屬性值。miattgetstr- 讀取指定最大長度的字元屬性。miattputdbl- 寫入雙精度屬性。miattputstr- 寫入字串屬性。mivarget- 獲取指定型別的一組超立方體值。mivarget1- 獲取指定型別的一個值。mivarput- 放置指定型別的一組超立方體值。mivarput1- 放置指定型別的一個值。
接下來,我們有一些函式用於處理座標向量。
miset_coords- 將一組座標設定為一個值。mitranslate_coords- 將一個變數的座標轉換為另一個變數的索引向量。
最後,有一些函式用於將變數視為屬性組,這使得在保持輔助資訊的同時修改檔案變得更容易。
micopy_all_atts- 將一個變數的所有屬性複製到另一個變數(可能跨檔案)。micopy_var_def- 將一個變數的定義(包括屬性)從一個檔案複製到另一個檔案。micopy_var_vals- 將一個變數的值從一個變數複製到另一個變數(可能跨檔案)。micopy_all_var_defs- 將一個檔案的所有變數定義複製到另一個檔案,排除一個變數列表。micopy_all_var_vals- 將一個檔案的所有變數值複製到另一個檔案,排除一個變數列表。
提供了一些例程來處理一些 minc 結構。miattput_pointer 和 miattget_pointer 用於設定/獲取指向變數屬性的指標。miadd_child 透過處理兩個變數的 MIparent 和 MIchildren 屬性來幫助維護變數的層次結構。最後,micreate_std_variable 和 micreate_group_variable 建立一些標準變數並填充一些預設屬性。
前面提到的檔案格式要求之一是軟體介面,以使介面易於使用。使用靈活格式的最大困難在於應用程式必須處理許多可能性。在涉及影像的情況下,這意味著各種資料型別和比例因子,以及不同大小的影像。MINC 的影像轉換變數函式試圖為程式設計師消除這種複雜性。
影像轉換變數 (icv) 本質上是程式希望影像在型別、比例和維度上看起來像什麼。當 MINC 影像透過 icv 讀取時,它將被轉換為呼叫程式的標準格式,而不管資料如何在檔案中儲存。
轉換有兩類:型別和範圍轉換更改影像值的 資料型別(和符號),並選擇性地對其進行縮放以進行適當的規範化。維度轉換允許程式指定影像維度大小和影像軸方向(MIxspace 座標應該增加還是減少?患者的左側應該出現在影像的左側還是右側?)。
透過 icv 訪問檔案是一個簡單的過程。使用 miicv_create 建立 icv,使用 miicv_set 例程設定屬性(如所需資料型別),使用 miicv_attach 將 icv 附加到 NetCDF 變數,並使用 miicv_get 或 miicv_put 訪問資料。可以使用 miicv_detach 將 icv 與 NetCDF 變數分離,並可以使用 miicv_free 釋放 icv。
Icv 屬性是字串、整數、長整數或雙精度數。例如,MI_ICV_SIGN(變數值的符號)是一個字串,而 MI_ICV_IMAGE_MAX(影像最大值)是一個雙精度值。提供四個函式 - miicv_setint, miicv_setlong, miicv_setdbl 和 miicv_setstr - 以簡化屬性值的設定。程式可以使用 miicv_inqint, miicv_inqlong, miicv_inqdbl 和 miicv_inqstr 查詢屬性值。
畫素值透過指定 MI_ICV_TYPE 和 MI_ICV_SIGN 屬性的值(預設值分別為 NC_SHORT 和 MI_SIGNED)進行型別和符號轉換。值也可以轉換為有效範圍並進行規範化。這些轉換透過將 MI_ICV_DO_RANGE 設定為 TRUE(預設值)來啟用。
如果 MI_ICV_DO_NORM 為 FALSE(預設值),則僅進行有效範圍轉換。這意味著,如果輸入檔案在 0 到 4095 範圍內有短整型值,則可以將其轉換為 64 到 248 範圍內的位元組值(例如)。實際影像最大值和最小值(MIimagemax 和 MIimagemin)將被忽略。有效範圍由屬性 MI_ICV_VALID_MAX 和 MI_ICV_VALID_MIN 指定,它們預設值為型別和符號的合法範圍。
我們可能希望縮放值,以便將它們規範化為 MIimage 變數中的所有值或某個使用者定義的範圍。要進行規範化,請將 MI_ICV_DO_NORM 設定為 TRUE。將 MI_ICV_USER_NORM 設定為 FALSE(預設值)會導致規範化為變數的實際最大值和最小值(MIimagemax 的最大值和 MIimagemin 的最小值)。如果 MI_ICV_USER_NORM 為真,則使用 MI_ICV_IMAGE_MAX 和 MI_ICV_IMAGE_MIN 的值(預設值為 1.0 和 0.0)。
當 MI_ICV_TYPE 或檔案型別為浮點數時,總是使用實際影像最大值和最小值資訊進行向實值轉換和從實值轉換。如果內部型別為整數,並且 MI_ICV_DO_NORM 為 FALSE,則進行重新縮放以使切片最大值對映到內部值的有效範圍。
請注意,當轉換為整數型別時,值將四捨五入到最接近的整數,並限制在資料型別的合法範圍內。
上面的轉換很簡單,但是使用浮點數增加了複雜性,因為通常我們不想重新縮放這些值以獲得實際值。以下將更詳細地描述各種可能性。
考慮重新縮放最簡單的方法是透過四個範圍(最大值-最小值對)。在檔案變數中,值具有有效範圍 var_vrange,它們對應於實值 var_imgrange。使用者/應用程式希望將實值 usr_imgrange 轉換為有用的有效範圍 usr_vrange。根據 var_vrange、var_imgrange、usr_imgrange 和 usr_vrange,我們可以確定用於轉換畫素值的比例和偏移量:輸入值透過 var_vrange 到 var_imgrange 縮放為實值,然後再次透過 usr_imgrange 到 usr_vrange 縮放為使用者值。
如果任何一個 vrange 變數未指定,則它們將預設為整數型別的最大可能範圍。對於浮點型別,usr_vrange 設定為等於 usr_imgrange,因此不會進行實值轉換。
如果沒有進行規範化,則對於整數型別,var_imgrange 和 usr_imgrange 設定為 [0,1](縮放到 [0,1] 並再次縮放)。在規範化時,usr_imgrange 設定為變數的完整範圍(如果未找到則為 [0,1])或使用者請求的範圍。如果變數值為浮點數,則 var_imgrange 設定為 var_vrange(不縮放為實值),否則 var_imgrange 將針對每個影像讀取(如果未找到,則為 [0,1])。
下面討論這對於讀取和寫入影像意味著什麼。
當讀取到內部浮點值時,規範化不起作用。當不進行規範化時讀取整數時,每個影像都會縮放到完整範圍。在規範化時,它們將縮放到指定的範圍,並且可以比較切片。
當輸入檔案缺少 MIimagemax/MIimagemin(var_imgrange 資訊)或 MIvalid_range 時,例程會嘗試提供合理的預設值,但仍然可能發生奇怪的事情。最大的問題是,如果預設值不正確(整數值的完整範圍和浮點數的 [0,1]),則缺少 MIvalid_range。當將浮點值轉換為整數型別時,如果值超出 [0,1] 範圍,則會出現溢位。
轉換例程可用於寫入值。這對於資料壓縮很有用 - 例如,將內部浮點數轉換為檔案中的位元組值,或將內部短整型值轉換為位元組值。當使用規範化執行此操作時(例如,將位元組重新縮放為切片最大值),在寫入切片之前,在 MIimagemax 和 MIimagemin 中寫入切片最大值和最小值非常重要。
另一個問題是 MIvalid_range 或 MIvalid_max 和 MIvalid_min 應正確寫入(尤其是如果預設值不正確)。當寫入浮點值時,MIvalid_range 應設定為變數中值的完整範圍。在這種情況下,不必在寫入變數之前正確設定屬性,但如果它存在,則值應合理(最大值大於最小值,並且值不太可能導致溢位)。如果例程 micreate_std_variable 用於 NC_FILL 模式(預設值),則這些值將自動設定。
讀取不進行規範化的影像
/* Create the icv */
icv=miicv_create();
(void) miicv_setint(icv, MI_ICV_TYPE, NC_SHORT);
(void) miicv_setstr(icv, MI_ICV_SIGN, MI_UNSIGNED);
(void) miicv_setint(icv, MI_ICV_VALID_MAX, 32000);
(void) miicv_setint(icv, MI_ICV_VALID_MIN, 0);
/* Open the file, attach the image variable */
cdfid=ncopen(filename, NC_NOWRITE);
/* Attach image variable */
img=ncvarid(cdfid, MIimage);
(void) miicv_attach(icv, cdfid, img);
/* Get the data - we assume that coord and count are set properly */
(void) miicv_get(icv, coord, count, image);
/* Close the file and free the icv */
(void) ncclose(cdfid);
(void) miicv_free(icv);
讀取進行規範化的影像
/* Create the icv */
icv=miicv_create();
(void) miicv_setint(icv, MI_ICV_TYPE, NC_SHORT);
(void) miicv_setstr(icv, MI_ICV_SIGN, MI_UNSIGNED);
(void) miicv_setint(icv, MI_ICV_VALID_MAX, 32000);
(void) miicv_setint(icv, MI_ICV_VALID_MIN, 0);
(void) miicv_setint(icv, MI_ICV_DO_NORM, TRUE);
(void) miicv_setint(icv, MI_ICV_USER_NORM, TRUE);
(void) miicv_setdbl(icv, MI_ICV_IMAGE_MAX, 1.83);
(void) miicv_setdbl(icv, MI_ICV_IMAGE_MIN, -0.57);
...
讀取浮點影像
/* Create the icv. We don't have to set MI_ICV_USER_NORM to TRUE,
but doing so ensures that the conversion is done properly
without looking at file values (the defaults for
MI_ICV_IMAGE_MAX and MI_ICV_IMAGE_MIN are 1 and 0) */
icv=miicv_create();
(void) miicv_setint(icv, MI_ICV_TYPE, NC_FLOAT);
(void) miicv_setint(icv, MI_ICV_DO_NORM, TRUE);
(void) miicv_setint(icv, MI_ICV_USER_NORM, TRUE);
...
將浮點數寫入位元組值
/* Create the icv */
icv=miicv_create();
(void) miicv_setint(icv, MI_ICV_TYPE, NC_FLOAT);
(void) miicv_setint(icv, MI_ICV_DO_NORM, TRUE);
/* Create the file */
cdf=nccreate(filename, NC_CLOBBER);
/* Define the dimensions */
dim[0]=ncdimdef(cdf, MIyspace, ysize);
dim[1]=ncdimdef(cdf, MIxspace, xsize);
/* Define the variables */
img=micreate_std_variable(cdf, MIimage, NC_BYTE, 2, dim);
(void) miattputstr(cdf, img, MIsigntype, MI_UNSIGNED);
vrange[0]=0; vrange[1]=200;
(void) ncattput(cdf, img, MIvalid_range, NC_DOUBLE, 2, vrange);
max=micreate_std_variable(cdf, MIimagemax, NC_DOUBLE, 0, NULL);
min=micreate_std_variable(cdf, MIimagemin, NC_DOUBLE, 0, NULL);
/* End definition mode */
ncendef(cdf);
/* Attach image variable */
(void) miicv_attach(icv, cdf, img);
/* Write the image max and min */
ncvarput1(cdf, max, NULL, &image_maximum);
ncvarput1(cdf, min, NULL, &image_minimum);
/* Write the image */
start[0]=start[1]=0;
count[0]=ysize; count[1]=xsize;
miicv_put(icv, start, count, vals);
/* Close the file and free the icv */
(void) ncclose(cdf);
(void) miicv_free(icv);
如果我們要寫入浮點影像,唯一的區別(除了將NC_BYTE更改為NC_FLOAT)是我們將在檔案末尾使用浮點值的完整範圍重新寫入MIvalid_range。
任意維影像的問題之一是,軟體必須處理一般情況。如果提前知道所有影像都具有特定大小(例如 256 x 256)和特定方向(例如,第一個畫素位於患者的前部右側),則編寫應用程式軟體會更容易。
透過將 icv 屬性MI_ICV_DO_DIM_CONV設定為TRUE,可以自動執行這些轉換。空間軸的方向由屬性MI_ICV_XDIM_DIR、MI_ICV_YDIM_DIR和MI_ICV_ZDIM_DIR決定。這些會影響任何MI?space或MI?frequency的影像維度,其中?對應於x、y或z。這些屬性可以具有值MI_ICV_POSITIVE、MI_ICV_NEGATIVE或MI_ICV_ANYDIR。最後一個將防止維度翻轉。前兩個將根據需要翻轉維度,以便維度變數的屬性MIstep具有正確的符號。
兩個影像維度分別稱為維度 A 和 B。維度 A 是這兩個維度中變化最快的維度。設定屬性MI_ICV_ADIM_SIZE和MI_ICV_BDIM_SIZE指定影像維度的所需大小。調整維度大小,以便檔案影像完全適合呼叫程式的影像中,並在影像中居中。大小MI_ICV_ANYSIZE允許其中一個維度具有可變大小。如果屬性MI_ICV_KEEP_ASPECT設定為TRUE,則兩個維度按相同比例縮放。可以查詢與屬性MIstep和MIstart相對應的新的步長和起始位置(其中畫素位置 = ipixel*step+start,其中 ipixel 從零開始計數)。屬性MI_ICV_?DIM_STEP和MI_ICV_?DIM_START(? = A或B)是自動設定的,可以查詢,但不能設定。
雖然允許向量影像,但許多應用程式寧願只處理標量影像(每個點一個強度值)。將MI_ICV_DO_SCALAR設定為TRUE(預設值)將導致向量影像透過平均元件轉換為標量影像。(因此,RGB 影像以這種簡單的方式自動轉換為灰度影像)。
有時程式對三個(或更多)維度(而不僅僅是兩個標準影像維度)執行維度轉換可能很有用。要對超出通常兩個維度的維度執行維度翻轉和/或調整大小,可以將屬性MI_ICV_NUM_IMGDIMS設定為 1 到MI_MAX_IMGDIMS之間的整數值。要設定維度的尺寸,請設定屬性MI_ICV_DIM_SIZE(類似於MI_ICV_ADIM_SIZE)。要指定要設定的維度,請將維度新增到屬性(新增零對應於變化最快的維度 - 為``A維度新增零,為``B維度新增一,等等)。可以透過屬性MI_ICV_DIM_STEP和MI_ICV_DIM_START(類似於MI_ICV_ADIM_STEP和MI_ICV_ADIM_START)查詢體素間隔和位置,同樣將維度編號新增到屬性。
以 0 到 32000 之間的短整數值讀取 256 x 256 影像,第一個畫素位於患者的下部、後部和左側
/* Create the icv */
icv=miicv_create();
(void) miicv_setint(icv, MI_ICV_TYPE, NC_SHORT);
(void) miicv_setstr(icv, MI_ICV_SIGN, MI_UNSIGNED);
(void) miicv_setint(icv, MI_ICV_VALID_MAX, 32000);
(void) miicv_setint(icv, MI_ICV_VALID_MIN, 0);
(void) miicv_setint(icv, MI_ICV_DO_DIM_CONV, TRUE);
(void) miicv_setint(icv, MI_ICV_ADIM_SIZE, 256);
(void) miicv_setint(icv, MI_ICV_BDIM_SIZE, 256);
(void) miicv_setint(icv, MI_ICV_KEEP_ASPECT, TRUE);
(void) miicv_setint(icv, MI_ICV_XDIM_DIR, MI_POSITIVE);
(void) miicv_setint(icv, MI_ICV_YDIM_DIR, MI_POSITIVE);
(void) miicv_setint(icv, MI_ICV_ZDIM_DIR, MI_POSITIVE);
/* Open the file, attach the image variable */
cdfid=ncopen(filename, NC_NOWRITE);
/* Attach image variable */
img=ncvarid(cdfid, MIimage);
(void) miicv_attach(icv, cdfid, img);
/* Get the data - we assume that coord and count are set properly */
(void) miicv_get(icv, coord, count, image);
/* Close the file and free the icv */
(void) ncclose(cdfid);
(void) miicv_free(icv);