对CT数据进行最小最大值归一化(Min-Max Normalization)和消除过暗过亮值处理


我们在处理CT图像时(以dcm格式为例),在数据预处理方面(主要和PIL.Image相关)会出现图像失真的问题。
我们可以使用最小最大值归一化(Min-Max Normalization)和消除过暗过亮值,来解决相关问题。下面详述。

本文需要用到处理dcm文件的库:pydicom。

本文代码:my GitHub

PIL库的图像失真问题

我们从dcm数据中获取数据矩阵时,直接用 Image.fromarray() 读取时会出现图像失真。

例:

我们先用plt.imshow显示图像没有问题。
在这里插入图片描述

用Image读入图像矩阵后,convert过后就出现了问题:
在这里插入图片描述

由于图像矩阵传入PIL库后,模式(mode)一般是F(浮点型)或I(整形),无法进一步处理(比如另存为jpg图像格式、在notebook中显示等)。
所以我们一般会使用 convert 方法转换mode,灰度图我们一般转成 “L” 模式。
但是这样会导致图像失真,效果如上图所示。

模式 说明
1 1位像素,黑和白,存成8位的像素
L 8位像素,黑白
P 8位像素,使用调色板映射到任何其他模式
RGB 3×8位像素,真彩
RGBA 4×8位像素,真彩+透明通道
CMYK 4×8位像素,颜色隔离
YCbCr 3×8位像素,彩色视频格式
I 32位整型像素
F 32位浮点型像素

我们可以将矩阵求和来验证一下是否失真:
在这里插入图片描述

以上可以看到 convert(‘L’) 后,图像矩阵的数值已经产生了变化,这也解释了为什么显示出来的图像和plt.imshow()显示的有很大的差别

使用最小最大值归一化(Min-Max Normalization)预处理

我们发现使用convert方法对数值范围的要求在 0~255 之间。而这张图像的矩阵的数值最高达到了2242,所以convert时出现了问题。
最小最大值归一化(Min-Max Normalization)可将矩阵全体数值线性映射到[0, 1]之间。
最后再全体乘以255即可。


我们在传入Image之前对矩阵进行归一化:

max_value = img_array.max()
min_value = img_array.min()
img_array = (img_array - min_value) / (max_value - min_value)
img_array = img_array * 255

具体实现:
在这里插入图片描述

在这里插入图片描述

以上经过最小最大值归一化,并乘以255后,图像基本就不失真了!

消除过暗过亮值

在实际情况中,不少CT图像的矩阵存在背景数值(CT值)为-2000,并且还会有带极高亮斑的情况。
这种光光做Min-Max Normalization是不够的。


举个例子(观察最大值和最小值):
在这里插入图片描述

以上我们发现经过Min-Max Normalization后,图像变得非常暗淡。
我们计算了数据最大值: 9435.0 ,数据最小值: -2000.0
我们查看一下图像矩阵的一行。

在这里插入图片描述

可以发现背景的数值是 -2000,并且普通组织区域的数值大约在0~3000左右。
最大值9435应该对应的是图像中的某个亮斑,属于干扰值。
我们可以将图像进行进一步处理,将-2000的部分改成0,大于3000的值改成3000

在这里插入图片描述

以上就正常多啦~

pytorch中对tensor使用最小最大值归一化处理(torchvision.transforms)

torchvision.transforms中没有对应最小最大值归一化的方法。
想要在pytorch数据处理中使用最小最大值归一化,可以自己写一个方法放入transoms.Compose中。

消除过暗过亮值 和 最小最大值归一化 处理后的CT图像数据在训练时有助于收敛并提高模型准确率指标。


代码实例:
我们编写一个NormalizeTensor函数即可

from torchvision import transforms
import torch

def NormalizeTensor(data):
    minimal = torch.min(data)
    return (data - minimal) / (torch.max(data) - minimal)

transform = transforms.Compose([
    transforms.Resize((224,224)),
    transforms.ToTensor(),
    NormalizeTensor,
])

img_open=pydicom.read_file(dcm2)
img_array = img_open.pixel_array
img_array = np.array(img_array, dtype=np.float32)

# 消除过暗过亮值
img_array = np.maximum(img_array, 0)  # 消除-2000 CT值
img_array = np.minimum(img_array, 3000)  # 消除极亮值

img_array_pil = Image.fromarray(img_array)
img = img_array_pil.convert('L')

img_tensor = transform(img)

参考:
https://androidkt.com/normalize-pytorch-batch-of-tensors-between-0-and-1-using-scikit-learn-minmaxscaler/

猜你喜欢

转载自blog.csdn.net/takedachia/article/details/131034498