CT图像的窗宽窗位(VTK及3Dslicer中的使用)

1. 窗宽/窗位概念

窗技术(Window Technique)是医生用 以观察不同密度正常组织或病变的一种显示技术,其包括窗宽(window width)和窗位(window level)。由于各种不同组织结构或病变具有不同的像素值,因些欲显示某一组织结构细节时,应选择适合观察组织结构的窗宽窗位,以获得显示最佳效果。
CT能识别人体内2000个不同灰阶的密度差别。而人的眼睛却只能分辨16 个灰阶度。因此,人眼在CT图像上能分辨的CT值应为125 Hu ( 2000 / 16 )。
CT图像的窗宽窗位(VTK及3Dslicer中的使用)_第1张图片

换句话说,人体内不同组织CT 值只有相差125Hu 以上,才能为人眼所识别。人体软组织CT值多变化在20 - 50 Hu之间,人眼就无法识别。为此,必须进行分段观察,才能使CT 的优点反映出来。观察的CT 值范围,人们称之为窗宽 ;观察的中心CT值即为窗位或窗中心。
常见人体组织的CT值(HU)
CT图像的窗宽窗位(VTK及3Dslicer中的使用)_第2张图片

窗宽

窗宽指CT图像所显示的CT 值范围。在此CT值范围内的组织结构按其密度高低从白到黑分为16 个灰阶以供观察对比。
例如,窗宽选定为100 Hu ,则人眼可分辨的CT值为100 / 16 =6 . 25 Hu ,即2 种组织CT值相差在6 . 25Hu以上者即可为人眼所识别。因此,窗宽的宽窄直接影响图像的清晰度与对比度。

  1. 如果使用窄的窗宽,则显示的CT 值范围小,每一灰阶代表的CT 值幅度小,对比度强,适于观察密度接近的组织结构(如脑组织)。
  2. 反之,如果使用宽的窗宽,则显示的CT值范围大,每一灰阶代表的CT 值幅度大,则图像对比度差,但密度均匀,适于观察密度差别大的结构(如骨与软组织)。

窗位

窗位(窗中心)指窗宽范围内均值或中心值。
比如一幅CT图像,窗宽为100Hu,窗位选在0Hu;则以窗位为中心(0Hu),向上包括+50Hu,向下包括-50Hu,凡是在这个100Hu 范围内的组织均可显示出来并为人眼所识别。凡是大于+50Hu 的组织均为白色;凡是小子-50Hu 的组织均为黑色,其密度差异无法显示。人眼只能识别土50Hu 范围内的CT 值,每一个灰阶的CT 值范围是100 / 16=6 . 25 Hu 。

参考链接:https://www.zhihu.com/question/33587197/answer/89502692

2. W/L (Window-leveling)算法分析

  1. 16-bit 到 8-bit 直接转换
    在显示器往往只有 8位(0~255), 而数据有 12~16位。如果将数据的 min 和 max 间 (dynamic range) 的之间转换到 8位的0~255,在这个过程是有损转换,而且出来的图像往往突出的是些噪音。
    针对这些问题,研究人员先提出一些要求 (requirements),然后根据这些要求提出了一些算法。这些算法现在都很成熟。
    要求(1):充分利用 0-255 间的显示有效值域;
    要求(2):尽量减少值域压缩带来的损失;
    要求(3):不能损失应该突出的组织部分。
ComputeMinValMaxVal(pixel_val, min, max); // 先算图像的最大和最小值  
for (i = 0; i < nNumPixels; i++){  
    disp_pixel_val = (pixel_val - min)*255.0/(double)(max - min);  
}
  1. Window-leveling 算法
    原理:CT/DR 图像里不同组织的密度 (用 Hounsfield 单位) 是在固定的值域, 与具体设备和成像软件没有关系。
    因此,要看头颅时, 我们只需将头颅的值域转换到 0-255 就行了。CT/DR 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);  
}

非线性转换
刚刚说的是将 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);  
    }  

3D Slicer中的窗宽/窗位调节

CT图像的窗宽窗位(VTK及3Dslicer中的使用)_第3张图片## VTK中的窗宽/窗位调节

  1. 第一种:
    imageViewer->SetColorLevel(-600);//窗位
    imageViewer->SetColorWindow(1200);//窗宽

	dim[0] = dcmViewer->GetColorLevel();//显示窗位1000   
	dim[1] = dcmViewer->GetColorWindow();//显示窗宽2000
  1. 第二种:
double range[2];
v16->GetOutput()->GetScalarRange(range);//灰度的最大值 最小值
vtkImageShiftScale* shifter = vtkImageShiftScale::New();  
shifter->SetShift(-1.0*range[0]);//减去最小值
shifter->SetScale(255.0/(range[1]-range[0])); //调节比例 //灰度换算公式:255*X/(range[1]-range[0])
shifter->SetOutputScalarTypeToUnsignedChar();
shifter->SetInputConnection(v16->GetOutputPort());

//计算公式: double val = ((double)(*inSI) + shift) * scale;

  1. 第三种:
   vtkNew imageSlice;
    vtkNew mapper;
    vtkNew interactorStyle;    // 用于响应鼠标事件以调节窗宽窗位
    //鼠标左键按住不放,上下移动调整窗位,左右移动调整窗宽
    //鼠标右键按住不放,上下移动放大缩小,或者使用鼠标滚轮
    reader->SetFileName(dcmFileName);
    reader->Update();
    vtkImageData* imageData = reader->GetOutput();
 
    mapper->SetInputData(imageData);
    imageSlice->SetMapper(mapper);
    renderer->AddViewProp(imageSlice);
    renderWindow->AddRenderer(renderer);
    w.SetRenderWindow(renderWindow);
    w.GetInteractor()->SetInteractorStyle(interactorStyle);
 
    renderer->ResetCamera();
    imageSlice->GetProperty()->SetColorLevel(/*double*/val);   // 窗位
	imageSlice->GetProperty()->SetColorWindow(/*double*/val);  // 窗宽

你可能感兴趣的:(VTK,干货,vtk)