前言
继续上次要完成的第二个目标:Numpy格式转换至PNG
在上次的工作LiTS 数据集预处理(一) 对数据切片 和LiTS 数据集预处理(二) 肝脏肿瘤分离 ,我们完成了对CT图像进行了切片处理,并生成了相应的切片后的标签(Label)。
需要注意的是,CT图像和标签之间是一一对应的,数量自然也是相同的,
所以我们转换成png是不是也应该是数目相同,我最开始也是这么认为的。
首先对肿瘤图像进行转换
我们已经使用上一次的博客代码将LiTS数据集处理好了,我下面要将处理好的npy文件转换成png,
转换期间我们可能会遇到以下几个问题,让我们依次解决:
- numpy是3维的,因为有0 1 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。
下面的操作就比较简单了
方法一
- 删除文件名中包含 _channel1 和 _channel2 的 PNG 图片
你可以使用 find 命令结合 -delete 选项来删除这些文件。假设你的文件夹路径是 /path/to/your/folder,你可以运行以下命令:
find /path/to/your/folder -type f $ -name '*_channel1.png' -o -name '*_channel2.png' $ -delete
- 重命名文件名中包含 _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("所有文件转换完成!")
希望这些可以帮助到你!
如果可以给小陈学长点个赞,有问题欢迎评论区讨论。