将灰色 pixel_array 从 DICOM 图像转换为 RGB 图像

Convert gray pixel_array from DICOM to RGB image

我正在读取 DICOM 灰度图像文件

gray = dicom.dcmread(file).pixel_array

我有 (x,y) 形状但我需要 RGB (x,y,3) 形状

我正在尝试使用 CV 进行转换

img = cv2.cvtColor(gray, cv2.COLOR_GRAY2RGB)

为了测试,我将其写入文件 cv2.imwrite('dcm.png', img)

我输出的图像非常暗,这是错误的,将 pydicom 图像转换为 RGB 的正确方法是什么?

阅读 DICOM 文件的完整教程在这里:https://www.kaggle.com/gzuidhof/full-preprocessing-tutorial

基本上,您必须从 DICOM 文件中提取参数 slopeinterception,并对每个像素进行数学计算:hu = pixel_value * slope + intercept——所有这些都在教程中进行了解释代码示例和图片。

要回答你的问题,你需要提供更多的信息,并且更清楚一些。

首先你想做什么?您是否只想在内存中获取 (x,y,3) 数组?还是您要将 dicom 文件转换为 .png 文件? ...它们是非常不同的东西。

其次,你的dicom图像是什么模态?

这很可能(除非是超声波或核医学)16 位灰度图像,这意味着数据是 16 位,这意味着您上面的 gray 数组是 16 位数据。

所以首先要了解的是window调平以及如何将16位的图像显示成8位。看看这里:http://www.upstate.edu/radiology/education/rsna/intro/display.php.

如果是16位的图片,如果你想看成rgb格式的灰度图,那么你需要知道你正在使用或需要什么window级别,并在之前适当调整节省。

第三,就像 lenik 提到的 ,您需要在使用前将 dicom slope/intercept 值应用到您的像素数据。


如果您的问题只是为 rgb 创建一个具有额外维度的新数组(因此大小 (r,c) 到 (r,c,3)),那么很容易

# orig is your read in dcmread 2D array:
r, c = orig.shape

new = np.empty((w, h, 3), dtype=orig.dtype)

new[:,:,2] = new[:,:,1] = new[:,:,0] = orig
# or with broadcasting
new[:,:,:] = orig[:,:, np.newaxis]

这会给你第三维度。但是如果您希望它是 RGB,这些值仍然都是 16 位,而不是需要的 8 位。 (假设您使用 dcmread 读取的图像是 CT、MR 或等效的 16 位 dicom - 那么 dtype 可能是 uint16)。

如果你想要它是RGB,那么你需要将值从16位转换为8位。为此,您需要决定 window/level 并将其应用于 select 来自完整 16 位数据范围的 8 位值。


可能你上面的问题 - I've got extremely dark image on output which is wrong - 实际上是正确的,但它是黑暗的,因为默认使用的 window/level cv 使它 'look' 黑暗,或者它是正确的但你没有'应用 slope/intercept.


如果您想将 dicom 转换为 png(或 jpg),那么您应该使用 PILmatplotlib 而不是 cv。这两个都提供了保存 16 位二维数组的简单方法(这就是上面代码中的 'gray'),它们都允许您在保存到 png 或时指定 window 和级别jpg。 CV 完全矫枉过正(意味着要加载很多 bigger/slower,并且学习曲线要​​高得多)。

一些使用 matplotlib 的伪代码。您需要调整的 vmin/vmax 值 - 此处的值对于 CT 图像来说大约没问题。


    import matplotlib.pyplot as plt

    df = dcmread(file)
    slope = float(df.RescaleSlope)
    intercept = float(df.RescaleIntercept)
    df_data = intercept + df.pixel_array * slope

    # tell matplotlib to 'plot' the image, with 'gray' colormap and set the
    # min/max values (ie 'black' and 'white') to correspond to 
    # values of -100 and 300 in your array
    plt.imshow(df_data, cmap='gray', vmin=-100, vmax=300)

    # save as a png file
    plt.savefig('png-copy.png')

这将保存 png 版本,但也会绘制坐标轴。要仅保存为图像,不带坐标轴和空白,请使用:

    inches = (3,3)
    dpi = 150
    fig, ax = plt.subplots(figsize=inches, dpi=dpi)
    fig.subplots_adjust(left=0, right=1, top=1, bottom=0, wspace=0, hspace=0)
    ax.imshow(df_data, cmap='gray', vmin=-100, vmax=300)

    fig.save('copy-without-whitespace.png')