首页 > 解决方案 > 如何从数组中正确提取 PNG 格式的标记掩码?

问题描述

我有以下格式的文件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))

标签: pythonimage-processingmaskscikit-imagenifti

解决方案


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

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

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

print(fdata.dtype)

而 PNG 格式只处理uint8or uint16,而不处理float64.

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

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

PNG 的对比度很低,因为在 0..255 的范围内所有值都小于 4,所以我使用ImageMagick增加了对比度,以便您可以看到它:

magick result.png -auto-level visible.png

在此处输入图像描述

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

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)

推荐阅读