之前一直以為自己對窗寬窗位的調節已經明了,但是隨著開發中的應用,發覺對這部分知識的理解實際上還是存在很多疑問的,尤其是在設計列印方面,曾經的自以為明了實際上只是自己把問題簡單化了而已。學無止境,看到自己的進步還是很開心的。
映像顯示和列印面臨的一個問題是:映像的亮度和對比能否充分突出關鍵區段。這裡所指的“關鍵區段”在 CT 裡的例子有軟組織、骨頭、腦組織、肺、腹部等等。
技術問題:
顯示器往往只有 8-bit, 而資料有 12- 至 16-bits。
如果將資料的 min 和 max 間 (dynamic range) 的之間轉換到 8-bit 0-255 去,過程是個有損轉換,而且出來的映像往往突出的是些噪音。
針對這些問題,研究人員先提出一些要求 (requirements),然後根據這些要求提出了一些演算法。這些演算法現在都很成熟。
要求一:充分利用 0-255 間的顯示有效範圍
要求二:盡量減少範圍壓縮帶來的損失
要求三:不能損失應該突出的組織部分
演算法分析:
A. 16-bit 到 8-bit 直接轉換:
computeMinMax(pixel_val, min, max); // 先算映像的最大和最小值
for (i = 0; i < nNumPixels; i++)
disp_pixel_val = (pixel_val - min)*255.0/(double)(max - min);
這個演算法必須有,對不少種類的映像是很有效:如 8-bit 映像,MRI, ECT, CR 等等。
B. Window-leveling 演算法:
W/L 是專門為 CT 設計的。原理很簡單:CT 映像裡不同組織的密度 (用 Hounsfield 單位) 是在固定的範圍, 與具體裝置和成像軟體沒有關係。因此,要看頭顱時, 我們只需將頭顱的範圍轉換到 0-255 就行了。
CT W/L 不講頭顱範圍的 min 和 max, 而說 max - min (即 window_width) 和 (max+min)/2 (即 window_center)。
我們還可以用原來的公式,只是 min 和 max 的演算法不一樣。
// 先算映像的最大和最小值
min = (2*window_center - window_width)/2.0 + 0.5;
max = (2*window_center + window_width)/2.0 + 0.5;
for (i = 0; i < nNumPixels; i++)
disp_pixel_val = (pixel_val - min)*255.0/(double)(max - min);
請注意,CT 映像必須先轉換成 Hounsfield 值再做 window-level。 這個轉換包括將多餘高位 bits 變成 0 (clipping), 和用 recale slope 和 rescale intercept 來做單位轉換。
HU = pixel_val*rescale_slope + rescale_intercept
C.非線性轉換
我剛剛說的是將 min 和 max 間的數值線性轉換到 0-255 之間。 如果 max - min 出來是個很大的數值,比如說 25500, 那就說每 100 原始密度會壓縮成一個顯示灰階。 這樣的損失可能會很大。
因為人眼對灰階地反應式是非線性,非線性轉換可以解決一些問題。 常用演算法有 log 和 gamma 兩種。gamma 比較好調 gamma 值,因此用得比較多。
for (i = 0; i < nNumPixels; i++)
disp_pixel_val = 255.0 * pow(pixel_value/(max-min), 1.0/gamma);
D. 有效範圍:CT 的 Window-level 有標準的定義,請參看 “Practical CT Techniques", by Wladyslaw Gedroyc and Sheila Rankin, Springer-Verlag。最常用到的有 WW = 400, WL = 40 (實用許多部位); WW = 100, WL = 36 (頭);WW = 3200, WL = 200 (骨頭),等等。
補充幾點:
最好先用 int 而非 unsigned char 來算,再轉入矩陣,以避免 overflow 和 underflow。
double dFactor = 255.0/(double)(max - min);
int nPixelVal;
for (i = 0; i < nNumPixels; i++)
{
nPixelVal = (int) ((pixel_val - min)*dFactor);
if (nPixelVal < 0)
disp_pixel_val = 0;
else if (nPixelVal > 255)
disp_pixel_val = 255;
else
disp_pixel_val = nPixelVal;
}
- 做 window-level 時要注意 min 和 max 之外未經處理資料的處理
double dFactor, min, max;
int nPixelVal;
min = (2*window_center - window_width)/2.0 + 0.5;
max = (2*window_center + window_width)/2.0 + 0.5;
dFactor = 255.0/(double)(max - min);
for (i = 0; i < nNumPixels; i++)
{
if (pixel_val < min)
{
disp_pixel_val = 0;
continue;
}
if (pixel_val > max)
{
disp_pixel_val = 255;
continue;
}
nPixelVal = (int)((pixel_val - min)*dFactor);
if (nPixelVal < 0)
disp_pixel_val = 0;
else if (nPixelVal > 255)
disp_pixel_val = 255;
else
disp_pixel_val = nPixelVal;
}
以下內容轉自“CT診斷學”一書,希望能協助大家更清楚地認識窗寬窗位。
窗寬與窗位
CT能識別人體內2000個不同灰階的密度差別。而人的眼睛卻只能分辨16 個灰階度。因此,人眼在CT映像上能分辨的CT值應為125 Hu ( 2000 / 16 )。換句話說,人體內不同組織CT 值只有相差125Hu 以上,才能為人眼所識別。人體軟組織CT值多變化在20 - 50 Hu之間,人眼就無法識別。為此,必須進行分段觀察,才能使CT 的優點反映出來。觀察的CT 值範圍,人們稱之為窗寬;觀察的中心CT值即為窗位或窗中心。
(一)窗寬指CT映像所顯示的CT 值範圍。在此CT值範圍內的組織圖按其密度高低從白到黑分為16 個灰階以供觀察對比。例如,窗寬選定為100 Hu ,則人眼可分辨的CT值為100 / 16 =6 . 25 Hu ,即2 種組織CT值相差在6 . 25Hu以上者即可為人眼所識別。因此,窗寬的寬窄直接影響映像的清晰度與對比。如果使用窄的窗寬,則顯示的CT 值範圍小,每一灰階代表的CT 值幅度小,對比強,適於觀察密度接近的組織圖(如腦組織)。反之,如果使用寬的窗寬,則顯示的CT值範圍大,每一灰階代表的CT 值幅度大,則映像對比差,但密度均勻,適於觀察密度差別大的結構(如骨與軟組織)。
(二)窗位(窗中心)指窗寬範圍內均值或中心值。比如一幅CT映像,窗寬為100Hu,窗位選在0Hu;則以窗位為中心(0Hu),向上包括+50Hu,向下包括-50Hu,凡是在這個100Hu 範圍內的組織均可顯示出來並為人眼所識別。凡是大於+50Hu 的組織均為白色;凡是小子-50Hu 的組織均為黑色,其密度差異無法顯示。人眼只能識別土50Hu 範圍內的CT 值,每一個灰階的CT 值範圍是100 / 16=6 . 25 Hu 。
原則上說窗位應該等於或接近需要觀察的CT 值;窗寬應能反映該組織或病變的CT 值變化範圍。