LiTS 数据集预处理(三) npy_to_png

前言

继续上次要完成的第二个目标:Numpy格式转换至PNG

在上次的工作LiTS 数据集预处理(一) 对数据切片LiTS 数据集预处理(二) 肝脏肿瘤分离 ,我们完成了对CT图像进行了切片处理,并生成了相应的切片后的标签(Label)。
需要注意的是,CT图像和标签之间是一一对应的,数量自然也是相同的,
所以我们转换成png是不是也应该是数目相同,我最开始也是这么认为的。

首先对肿瘤图像进行转换

我们已经使用上一次的博客代码将LiTS数据集处理好了,我下面要将处理好的npy文件转换成png,
转换期间我们可能会遇到以下几个问题,让我们依次解决:

  1. numpy是3维的,因为有0 1 2 三维分别放背景 肝脏 肿瘤 但是我们想要得到的图片得是2 维的灰度图像
  2. 对于没有肿瘤的病人图片的处理

完整代码如下:

'''
我们已经使用上一次的博客代码将LiTS数据集处理好了,我下面要将处理好的npy文件转换成png,
期间我们可能遇到的问题: numpy是3维的,因为有0 1 2 三维分别放背景 肝脏 肿瘤 但是我们想要得到的图片得是2维的灰度图像
'''
import numpy as np
import imageio
import os

from tqdm import tqdm

input_dir = r'F:\datesate\datasetnii\date-npy\tumor_image'
output_dir = r'F:\datesate\datasetnii\date-png\tumor_image'

# 创建输出文件夹(如果不存在)
os.makedirs(output_dir, exist_ok=True)

# 获取输入文件夹下所有.npy文件
npy_files = [os.path.join(input_dir, f) for f in os.listdir(input_dir) if f.endswith('.npy')]

for npy_file_path in tqdm(npy_files):
    # 加载.npy 文件
    npy_data = np.load(npy_file_path)

    # 检查数据范围
    min_value = np.min(npy_data)
    max_value = np.max(npy_data)
    #print(f"原始数据范围:{min_value} - {max_value}")

    # 归一化处理
    if min_value != max_value:
        npy_data = ((npy_data - min_value) / (max_value - min_value)) * 255
        npy_data = npy_data.astype(np.uint8)
    else:
        print("数据全相同,无法进行归一化。")


    # 检查数据维度
    if npy_data.ndim == 2:
        # 如果是二维数据,直接保存
        output_file = os.path.join(output_dir, f'{os.path.splitext(os.path.basename(npy_file_path))[0]}.png')
        imageio.imwrite(output_file, npy_data, format='png')
    elif npy_data.ndim == 3:
        # 如果是三维数据,遍历每个通道并保存
        for i in range(npy_data.shape[2]):  # 遍历第三个维度
            slice_data = npy_data[:, :, i]  # 获取第 i 个通道

            # 保存切片为 PNG,文件名中包含通道索引
            output_file = os.path.join(output_dir, f'{os.path.splitext(os.path.basename(npy_file_path))[0]}_channel{i}.png')
            imageio.imwrite(output_file, slice_data, format='png')

    else:
        print(f"不支持的维度:{npy_data.ndim},文件:{npy_file_path}")
        

print(f'{npy_file_path} 转换完成!')

首先对文件的读取,文件读取的相关知识我在之前博客也有简单讲解过,就不在这里啰嗦。
tqdm进度条显示,方便我们对整体有个感知

在对文件的归一化处理时候,如果图片是纯黑色,就可能会报错,但是也不能加入continue,(跳过当前文件),这样会导致label与Image 数目对不上。这是我第一次写代码的错误,当然也可以 npy_data.fill(255) 进行填充

    # 归一化处理
    if min_value != max_value:
        npy_data = ((npy_data - min_value) / (max_value - min_value)) * 255
        npy_data = npy_data.astype(np.uint8)
    else:
        print("数据全相同,无法进行归一化。")
        #npy_data.fill(255)
        #continue

对于维度的问题
我们可以先对处理好的npy 文件.shape一下,了解文件的结构与维度。

# 加载.npy 文件
npy_data = np.load(npy_file_path)
# 获取并打印数据的形状
data_shape = npy_data.shape
print(f"文件:{npy_file_path} 的形状为:{data_shape}")

对肿瘤文件的Mask文件,我们会得到(448,448)
对原CT图像 即Imgae 为(448,448,3)

所以我们对图像维度进行if判断

 # 检查数据维度
    if npy_data.ndim == 2:
        # 如果是二维数据,直接保存
        ···
       elif npy_data.ndim == 3:
       ····
       else:
        print(f"不支持的维度:{npy_data.ndim},文件:{npy_file_path}")

最终得到的肿瘤Mask图片如下:
在这里插入图片描述
最终得到的Image图如下:
这里发现有三个通道,是因为我们处理数据集时候,将拓展的三个切片整合为一个三通道数据的原因,更详细了解,可以去看看源代码。
在这里插入图片描述
经过对比,我们发现三个通道距离都比较近,差异比较小,但是我建议大家用channel0作为数据集Image。
在这里插入图片描述
下面的操作就比较简单了

方法一
  1. 删除文件名中包含 _channel1 和 _channel2 的 PNG 图片
    你可以使用 find 命令结合 -delete 选项来删除这些文件。假设你的文件夹路径是 /path/to/your/folder,你可以运行以下命令:
find /path/to/your/folder -type f $ -name '*_channel1.png' -o -name '*_channel2.png' $ -delete
  1. 重命名文件名中包含 _channel0 的 PNG 图片
    你可以使用 rename 命令(或 mv 命令)来重命名这些文件。以下是使用 rename 命令的示例:
# 重命名包含 _channel0 的 PNG 文件
for file in /path/to/your/folder/*_channel0.png; do
    mv "$file" "${file/_channel0/}"
done
或者or(方法二)

你可以用python实现

import os
import glob

# 设置目标文件夹路径
folder_path = '/path/to/your/folder'

# 删除包含 _channel1 和 _channel2 的 PNG 文件
for file_path in glob.glob(os.path.join(folder_path, '*_channel1.png')) + glob.glob(os.path.join(folder_path, '*_channel2.png')):
    try:
        os.remove(file_path)
        print(f"已删除文件: {file_path}")
    except Exception as e:
        print(f"删除文件 {file_path} 时出错: {e}")

# 重命名包含 _channel0 的 PNG 文件
for file_path in glob.glob(os.path.join(folder_path, '*_channel0.png')):
    new_file_path = file_path.replace('_channel0', '')
    try:
        os.rename(file_path, new_file_path)
        print(f"已重命名文件: {file_path} -> {new_file_path}")
    except Exception as e:
        print(f"重命名文件 {file_path} 时出错: {e}")
或者or(方法三)

当然最最简单的就是直接在源代码中不生成channel1和2的文件了。
防止大家出问题,直接把修改后代码贴上:

import numpy as np
import imageio
import os
from tqdm import tqdm

input_dir = r'F:\datesate\datasetnii\date-npy\tumor_image'
output_dir = r'F:\datesate\datasetnii\date-png\tumor_image'

# 创建输出文件夹(如果不存在)
os.makedirs(output_dir, exist_ok=True)

# 获取输入文件夹下所有.npy文件
npy_files = [os.path.join(input_dir, f) for f in os.listdir(input_dir) if f.endswith('.npy')]

for npy_file_path in tqdm(npy_files):
    # 加载.npy 文件
    npy_data = np.load(npy_file_path)

    # 检查数据范围
    min_value = np.min(npy_data)
    max_value = np.max(npy_data)

    # 归一化处理
    if min_value != max_value:
        npy_data = ((npy_data - min_value) / (max_value - min_value)) * 255
        npy_data = npy_data.astype(np.uint8)
    else:
        print("数据全相同,无法进行归一化。")
        continue  # 跳过当前文件

    # 检查数据维度
    if npy_data.ndim == 2:
        # 如果是二维数据,直接保存
        output_file = os.path.join(output_dir, f'{os.path.splitext(os.path.basename(npy_file_path))[0]}.png')
        imageio.imwrite(output_file, npy_data, format='png')
    elif npy_data.ndim == 3:
        # 如果是三维数据,只保存第一个通道
        slice_data = npy_data[:, :, 0]  # 获取第 0 个通道
        output_file = os.path.join(output_dir, f'{os.path.splitext(os.path.basename(npy_file_path))[0]}.png')
        imageio.imwrite(output_file, slice_data, format='png')
    else:
        print(f"不支持的维度:{npy_data.ndim},文件:{npy_file_path}")

print("所有文件转换完成!")

希望这些可以帮助到你!
如果可以给小陈学长点个赞,有问题欢迎评论区讨论。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值