The Method of Programming Medical Imaging
Ⅰ.ウィンドウレベル変換
モノクロで言えば、白と黒の階調表示を指定するタグを使って、グレースケールの濃淡を調整することです。
一般的な、パソコンのモニターは、8ビットのグレースケールに対応しています。
2^8 = 256 ですので、256階調の白黒の濃淡を表せるということになります。
10ビットマシンなど、高性能な輝度表示を行うことができるデバイスがありますが、
かなり高価です。
2^10 = 1024 ですので、1024階調の白黒の濃淡を表せるということになります。
グラフィックスボードも、10ビット対応のモノが必要です。
医用画像専用のモノになると、バルコというメーカーが有名です。
プロ仕様です。
Ⅱ.コード
///
/// Create Encoded Bitmap data from Dicom file.
///
/// '7FE0,0010' chunk pixcel image data
/// dicom definitioned width
/// dicom definitioned heigh
///
private Bitmap CreateBitmap(byte[] source, int width, int height, double window_center, double window_width)
{
Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format24bppRgb);
BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, width, height),
ImageLockMode.ReadWrite, bitmap.PixelFormat);
IntPtr ptr = bmpData.Scan0;
byte[] rgb = new byte[width * height * 3];
for (int i = 0; i < width * height; i++)
{
int value = source[2 * i] + source[2 * i + 1] * 256;
double val = value;
if (value >= window_width)
{
val = 255;
}
else if (value < 0)
{
val = 0;
}
else
{
val = val / window_width;
val = val * 255;
}
value = (int)val;
rgb[3 * i] = (byte)value;
rgb[3 * i + 1] = (byte)value;
rgb[3 * i + 2] = (byte)value;
}
System.Runtime.InteropServices.Marshal.Copy(rgb, 0, ptr, width * height * 3);
bitmap.UnlockBits(bmpData);
return bitmap;
}
上記は、Windows ビットマップファイルを作成する部分のコードです。
double val = value;
if (value >= window_width)
{
val = 255;
}
else if (value < 0)
{
val = 0;
}
else
{
val = val / window_width;
val = val * 255;
}
ウィンドウレベル変換に関するコードを抜粋しました。
ココでは、8ビットのグレースケールに変換するため、
デジタル信号が、ウィンドウ幅以上だった場合には、値255を、
デジタル信号が、0より低い値だった場合には、値0を、
それ以外の場合には、デジタル信号をウィンドウ幅で割った値に255を掛けた値を計算するものです。
そもそも、デジタル信号がマイナスである場合はないと思われますので、
else if(value < 0) のパスを通る場合はないと思われます。
ココで、ウィンドウレベルつまり、ウィンドウセンター値はどこに使うのかというお尋ねがあろうかと思われますが、
結論から言うと使いません。
いや、正確にいうのであれば、使うのだろうとおもいますが、
コード表現上の論理で考えた場合、使う余地がありません。
気を効かせて、忖度したコードが以下になります。
double val = value;
if (value >= window_width)
{
val = 255;
}
else if (value < 0)
{
val = 0;
}
else if (value < window_center)
{
val = val / window_center;
val = 127 * val;
}
else if (value >= window_center)
{
double tmp = (window_width - window_center) / window_width;
val = 127 + (val - window_center) * tmp;
}
Ex 1:
window_center(window_level) = 511
window_width = 1024
Ex 2:
window_center(window_level) = 4468.7402
window_width = 11062.5195
Ex 1 では、ウィンドウセンター値が、ウィンドウ幅のちょうど半分になっていることに気づきます。
つまり、デジタル信号の最小値から最大値までの変化率の傾きは一定です。
しかしながら、Ex 2 では、ウィンドウセンター値は、ウィンドウ幅の半分にはなっていませんね。
つまり、デジタル信号の最小値からウィンドウセンター値までの傾きと、
ウィンドウセンター値からデジタル信号の最大値までの傾きが異なるのです。
何がしらかの影響を加味したデータの交換がなされていたのであるならば、
細かい部分で、グレースケールにも影響を与えます。
つまりこういうことです。
下図を見てください。
しかしながら、このコードを実際ののモダリティで撮影された Dicom 画像に適用すると、
グレースケールにムラができ、正しく表示できません。
他のモダリティで撮影された画像も、失敗します。
正しく表示されるという意味では、
先に挙げた、ウィンドウセンター値を用いない方法での傾き一定で計算する方法が正しいようです。
前のページ <<< >>> 次のページ