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

浪尽此生 提交于 2021-01-27 05:38:30

问题


I want to convert a DICOM image from int16 to uint8. I have done it in Python using Z_axis = bytescale(img), but this gives different results than using im2uint8 in MATLAB. In MATLAB, The minimum and maximum values of a DICOM image after converting to uint8 using im2uint8 are (124, 136), respectively. But these values in Python after converting using bytescale are (0, 255).

Python code:

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 code:

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));

The images look equal when displayed, but the numeric values are not. So, are the bytescale and im2uint8 functions equal or not? If not, I want results like im2uint8 in Python. What kind of function should I choose (especially for DICOM images)?

For example, in MATLAB after reading a DICOM file:

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

But in Python, the same image after reading is:

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]])

I don't know why they are different in MATLAB and Python. After applying im2uint8 in MATLAB, the output is:

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

And after applying bytescale in Python, the output is:

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

回答1:


Firstly, regarding the issue with reading the data, I would suggest using dcmread in Python, as that gave me the same exact data as dicomread in MATLAB.

Secondly, in MATLAB when 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 to behave equivalently, I believe you need to set the cmin and cmax arguments accordingly (since they will otherwise default to data.min() and data.max(), respectively). This should replicate the results of im2uint8 in Python:

Z_axis = bytescale(img.astype(float), cmin=-32768, cmax=32767)

Note: conversion of the data to float first is necessary to account for an apparent bug in bytescale that doesn't handle the integer arithmetic properly (found courtesy of Cris Luengo).




回答2:


Yes it's different

bytescale convert matrix to uint8 normalizing all values by the the highest and the lowest (highest 255 and lowest 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)

In Matlab im2uint8 it's useful to convert double images to uint8. Double images has range 0 to 1. To do the same in Matlab fist you need to convert image in range of value 0-1 (double) normalizing the data, then apply 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);

Then you obtain the same image:

I2 =

  3×3 uint8 matrix

   255     0   236
   205   225     4
   140    90    70


来源:https://stackoverflow.com/questions/52725553/difference-between-the-functions-im2uint8-in-matlab-and-bytescale-in-pyth

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!