如何从数组中正确提取 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 格式仅处理 uint8
或 uint16
,但不处理 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)
我有以下 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 格式仅处理 uint8
或 uint16
,但不处理 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)