如何从数组中正确提取 PNG 格式的标记掩码?

How to extract labelled masks in PNG format correctly from an array?

我有以下 file 格式的 Nifti,其中包含遮罩,我编写了以下代码以将其中的图像提取为 PNG 图像,问题是:

这是一个用 [0. 1. 2. 3.],将掩码保存为 PNG 后,掩码图像中的值分布在 [0 --> 255] 范围内,而不是像以前那样只有 4 个标签!

请问我该如何解决这个问题?

唯一重要的是里面有4个独特的标签

提前致谢。

import nibabel as nib
import os
import glob
import numpy as np
from skimage.io import imread, imsave
#-------------------------------------------
# Multi Class Masks
path = 'Masks'
Dataset = glob.glob( os.path.join(path, '*.gz') )
ctr = 0
for image in Dataset:
    # Load masks voxel
    images = nib.load(image).get_fdata()
    print(np.unique(images))
    # Save it as PNG
    ctr+=1
    if(not os.path.exists('Dataset/masks/Case_'+str(ctr))):
        os.mkdir('Dataset/masks/Case_'+str(ctr))
    for _id in range(images.shape[2]):
        imsave(os.path.join('Dataset/masks','Case_'+
            str(ctr),str(ctr)+'_'+str(_id+1)+'.png'),
             resize(images[:,:,_id],(256,256)))
#-------------------------------------------
        imag = imread(os.path.join('Dataset/masks','Case_'+
             str(ctr),str(ctr)+'_'+str(_id+1)+'.png'))
        print(np.unique(imag))

只是警告你,我对 Nifti 数据一无所知,这里可能是完全错误的......但是,我认为问题在于当你这样做时:

fdata = nib.load(image).get_fdata()

你实际上得到了一个 float64 数据类型:

print(fdata.dtype)

并且 PNG 格式仅处理 uint8uint16,但不处理 float64

我假设,data 的形状是 (630, 630, 45),这意味着有 45 片东西,每片 630x630 - 但同样,我可能是错的。因此,我根据中间更可能有东西的基础采取了一个相当中心的切片,我 将其转换为 uint8 并将其保存为 PNG。

imsave('result.png', fdata[...,22].astype(np.uint8))

PNG 是低对比度的,因为在 0..255 的范围内所有值都小于 4,所以我用 ImageMagick 增加了对比度,这样你就可以看到它:

magick result.png -auto-level visible.png

您可以在终端中使用 ImageMagick 获取直方图并查看 4 个 class 标签中每个标签的出现频率:

magick result.png -format "%c" histogram:info

示例输出

335942: (0,0,0) #000000 gray(0)      <--- there are 335,942 pixels=0
 26367: (1,1,1) #010101 gray(1)      <--- there are  26,367 pixels=1
 29419: (2,2,2) #020202 gray(2)
  5172: (3,3,3) #030303 gray(3)