函数 "im2uint8"(在 MATLAB 中)和 "bytescale"(在 Python 中)之间的区别

Difference between the functions "im2uint8" (in MATLAB) and "bytescale" (in Python)

我想将 DICOM 图像从 int16 转换为 uint8。我在 Python 中使用 Z_axis = bytescale(img) 完成了它,但这给出了与在 MATLAB 中使用 im2uint8 不同的结果。在 MATLAB 中,使用 im2uint8 转换为 uint8 后的 DICOM 图像的最小值和最大值分别为 (124, 136)。但是使用 bytescale 转换后 Python 中的这些值是 (0, 255).

Python代码:

for person in range(0, len(dirs1)):
if not os.path.exists(os.path.join(directory, dirs1[person])):
    Pathnew = os.path.join(directory, dirs1[person])
    os.makedirs(Pathnew)
    for root, dirs, files in os.walk(os.path.join(path, dirs1[person])):
        dcmfiles = [_ for _ in files if _.endswith('.dcm')]
        for dcmfile in dcmfiles:
            dcm_image = pydicom.read_file(os.path.join(root, dcmfile))
            img = dcm_image.pixel_array
            Z_axis = bytescale(img)  
            minVal = Z_axis.min()
            maxVal = Z_axis.max()

Matlab代码:

for j = 1 : length(Files2)
    img = dicomread([galleryPath Files2(j).name]);
    Z_axis = im2uint8(img);
    minVal = min(min(Z_axis));
    maxVal = max(max(Z_axis));

图像显示时看起来相等,但数值不同。那么,bytescaleim2uint8 函数是否相等?如果不是,我想要 Python 中的 im2uint8 这样的结果。我应该选择什么样的功能(尤其是DICOM图像)?

例如,在 MATLAB 中读取 DICOM 文件后:

img = dicomread([galleryPath Files2(j).name]);
img = [ -1024,   -1024,   16;
        -1024,       8,   11;
           17,       5,    8];

但是在Python中,读取后的相同图像是:

dcm_image = pydicom.read_file(os.path.join(root, dcmfile))
img = dcm_image.pixel_array
img = array([[ -1024,    -1024,   27],
             [ -1024,       27,   26],
             [    24,       26,   23]])

我不知道为什么它们在 MATLAB 和 Python 中不同。在 MATLAB 中应用 im2uint8 后,输出为:

Z_axis = im2uint8(img)
Z_axis =
 3×3 uint8 matrix
   124    124   128
   124    128   128
   128    128   128

并且在 Python 中应用 bytescale 之后,输出是:

bytescale(img)
Z_axis = 
    array([[0,    0,   83],
           [0,   83,   83],
           [83,  83,   83]], dtype=uint8)

首先,关于读取数据的问题,我建议在 MATLAB 中使用 dcmread in Python, as that gave me the same exact data as dicomread

其次,在 MATLAB 中,当 im2uint8 converts int16 values it will scale them assuming minimum and maximum values for the data equal to -32768 and 32767, respectively (i.e. the minimum and maximum values representable by an int16). For bytescale 表现相同时,我相信您需要相应地设置 cmincmax 参数(否则它们将默认为 data.min()data.max())。这应该在 Python:

中复制 im2uint8 的结果
Z_axis = bytescale(img.astype(float), cmin=-32768, cmax=32767)

注意:必须首先将数据转换为浮点数,以解决 bytescale 中无法正确处理整数运算的明显错误(由 Cris Luengo 提供)。

是的,不一样

bytescale 将矩阵转换为 uint8 通过最高和最低(最高 255 和最低 0)归一化所有值

img = array([[ 91.06794177,   3.39058326,  84.4221549 ],
                 [ 73.88003259,  80.91433048,   4.88878881],
                 [ 51.53875334,  34.45808177,  27.5873488 ]])

bytescale(img)

array([[255,   0, 236],
       [205, 225,   4],
       [140,  90,  70]], dtype=uint8)

在 Matlab 中 im2uint8 将双图像转换为 uint8 很有用。双图像的范围为 0 到 1。 要在 Matlab 拳头中做同样的事情,您需要在值 0-1(双)范围内转换图像,对数据进行归一化,然后应用 im2uint8。

I = [ 91.06794177,   3.39058326,  84.4221549;
    73.88003259,  80.91433048,   4.88878881;
    51.53875334,  34.45808177,  27.5873488];

Inorm = (I - min(I(:))) ./ ( max(I(:)) - min(I(:)) );

I2 = im2uint8(Inorm);

然后你得到相同的图像:

I2 =

  3×3 uint8 matrix

   255     0   236
   205   225     4
   140    90    70