人工智能与医学图像分析—作业1

作业1要求:加载数据,显示图像

MNIST

• Show MNIST images and ground truth

• Build dictionary or tuples
• Build an iterator
• Segment the data properly

• Read and show 3 plane medical images in dicom and nifti


作答过程:

解读:(1)MNIST(Modified National Institute of Standards and Technology database)是机器学习领域最经典的手写数字图像数据集,常被称为深度学习界的“Hello World”‌。它由美国国家标准与技术研究院(NIST)整理,包含60,000张训练图像和10,000张测试图像,每张图像为28×28像素的灰度图,对应0-9的手写数字标签‌。该数据集广泛用于算法验证和教学,是入门图像识别任务的标准化基准‌。

(2)NPZ文件是NumPy库用于存储多个数组的压缩文件格式。它通过键值对存储多个NumPy数组,类似字典结构,支持同时保存训练数据、标签等关联数组‌。文件内部采用压缩技术,相比多个NPY文件更节省空间‌。深度学习领域常用NPZ文件存储训练集、验证集等关联数据,通过numpy.load()加载后可直接按名称访问数组‌。

一、加载图像

1、检查实际键名

# 首先查看NPZ文件中包含哪些数组键名:

with np.load('/HW1-data/mnist.npz') as data:

# 显示所有可用的键名

print(data.files)
['data', 'label']

2、读取NPZ文件

# 使用with语句读取文件可以确保文件资源被正确管理,避免资源泄漏
# 使用allow_pickle=True参数可以加载序列化的数据‌

with np.load('/HW1-data/mnist.npz', allow_pickle=True) as data:
    data1 = data['data']
    label1 = data['label']
    print(data1)  # 输出: [1 2 3]
    print(label1)  # 输出: [4 5 6]
[[0 0 0 ... 0 0 0]
 [0 0 0 ... 0 0 0]
 [0 0 0 ... 0 0 0]
 ...
 [0 0 0 ... 0 0 0]
 [0 0 0 ... 0 0 0]
 [0 0 0 ... 0 0 0]]
[0. 0. 0. ... 9. 9. 9.]

3、打印图像和标签形状

print("图像形状:", data1.shape)
print("标签形状:", label1.shape)
图像形状: (70000, 784)   # 图像一共70000张,大小为784=28x28
标签形状: (70000,)

4、调整数据形状

MNIST数据集中的图像数据原本是28×28像素的二维数组,但在存储时被展平成了784个元素的一维向量。要正确显示图像,需要将这个一维数组重新调整为二维形状。

#批量处理‌:如果需要处理多个图像,可以使用向量化操作

data1_reshaped = data1.reshape(-1, 28, 28)
print(data1.shape)  # 输出: (784,)
print(data1_reshaped.shape)  # 输出: (28, 28)
(70000, 784)
(70000, 28, 28)

注:

reshape‌:仅返回新形状的视图,原数据保持不变‌。

resize‌:直接修改原数组的形状‌。若需永久改变形状,应使用此方法。

5、展示图像(单张)

plt.figure(figsize=(6, 6))
index = 0  # 可以改为0-69999之间的任意数字
plt.imshow(data1_reshaped[index], cmap='gray')
plt.title(f"Label: {label1[index]}")
plt.show()

6、展示图像(多张)

fig, axes = plt.subplots(8, 8, figsize=(12, 12))

for i, ax in enumerate(axes.flat):
    ax.imshow(data1_reshaped[i], cmap='gray')
    ax.set_title(f"Label: {label1[i]}")
    ax.axis('off')

plt.tight_layout()
plt.show()

二、构建字典或元组

1、构建元组

元组优势‌:结构简单,内存占用少,适合固定顺序的数据。

# 创建元组结构

mnist_tuple = (data1_reshaped, label1)

# 访问示例

images, labels = mnist_tuple
print(f"元组中的图像形状: {images.shape}")
print(f"元组中的标签形状: {labels.shape}")
元组中的图像形状: (70000, 28, 28)
元组中的标签形状: (70000,)

2、构建字典结构

字典优势‌:键名访问更直观,适合需要明确标识的场景。

(1)创建字典

# 创建字典结构
mnist_dict = {
    'images': data1_reshaped,  # 形状为(-1, 28, 28)
    'labels': label1,           # 形状为(70000,)
    'metadata': {
        'num_samples': data1_reshaped.shape[0],
        'image_height': 28,
        'image_width': 28
    }
}

# 访问示例
print(f"图像数量: {mnist_dict['metadata']['num_samples']}")
print(f"单张图像形状: ({mnist_dict['metadata']['image_height']}, {mnist_dict['metadata']['image_width']})")
图像数量: 70000
单张图像形状: (28, 28)

(2)创建扩展的字典结构

# 确保标签为整数类型
label1_int = label1.astype(np.int64)
# 创建详细字典结构
detailed_mnist_dict = {
    'dataset': 'MNIST',
    'features': {
        'image_data': data1_reshaped,
        'ground_truth': label1
    },
    'statistics': {
        'total_images': data1_reshaped.shape[0],
        'unique_labels': np.unique(label1),
        'label_distribution': np.bincount(label1_int)
    }
}
print(f"数据集名称: {detailed_mnist_dict['dataset']}")
print(f"图像数量: {detailed_mnist_dict['statistics']['total_images']}")
print(f"单张图像形状: {data1_reshaped[0].shape}")
print(f"标签类别: {detailed_mnist_dict['statistics']['unique_labels']}")
print(f"标签分布: {detailed_mnist_dict['statistics']['label_distribution']}")
print(f"图像数据类型: {data1_reshaped.dtype}")
print(f"标签数据类型: {label1.dtype}")
数据集名称: MNIST
图像数量: 70000
单张图像形状: (28, 28)
标签类别: [0. 1. 2. 3. 4. 5. 6. 7. 8. 9.]
标签分布: [6903 7877 6990 7141 6824 6313 6876 7293 6825 6958]
图像数据类型: uint8
标签数据类型: float64

三、构建迭代器

解读:迭代器是软件设计模式中的一种对象遍历接口,它允许开发者遍历容器(如链表、数组等)中的元素,而无需了解容器的底层内存分配细节。在编程中,迭代器作为一个数据流对象,能够依次返回序列中的每个元素,直至数据被取完且不会被重复使用。

在具体实现上,迭代器需要遵循特定的协议。例如在Python中,迭代器协议要求对象实现__iter__和__next__两个方法。__iter__方法返回迭代器对象本身,这是for循环使用迭代器的前提;而__next__方法负责返回容器中的下一个元素,当没有更多元素时则抛出StopIteration异常。

特点:

  • 支持批量数据加载
  • 实现标准迭代器协议
  • 自动处理数据遍历结束

(1)构建迭代器:

class SimpleMNISTIterator:
    def __init__(self, mnist_dict, batch_size=32):
        self.images = mnist_dict['features']['image_data']
        self.labels = mnist_dict['features']['ground_truth']
        self.batch_size = batch_size
        self.num_samples = mnist_dict['statistics']['total_images']
        self.current_index = 0
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.current_index >= self.num_samples:
            self.current_index = 0
            raise StopIteration
        
        end_index = self.current_index + self.batch_size
        batch_images = self.images[self.current_index:end_index]
        batch_labels = self.labels[self.current_index:end_index]
        self.current_index = end_index
        return batch_images, batch_labels

(2)使用迭代器

# 创建并使用迭代器
iterator = SimpleMNISTIterator(detailed_mnist_dict, batch_size=16)
    
print("MNIST数据迭代器演示:")
for i, (imgs, lbls) in enumerate(iterator):
    print(f"批次 {i+1}: 图像 {imgs.shape}, 标签 {lbls.shape}")

四、分割数据

(1)分割数据集:训练集和测试集为8:2。

def split_mnist_data(detailed_mnist_dict, test_size=0.2, random_state=42):
    """
    将MNIST数据集按比例随机分割为训练集和测试集
    
    参数:
        detailed_mnist_dict: 包含图像和标签数据的字典
        test_size: 测试集比例,默认为0.2(20%)
        random_state: 随机种子,保证结果可复现
    """
    # 从字典中获取数据
    images = detailed_mnist_dict['features']['image_data']
    labels = detailed_mnist_dict['features']['ground_truth']
    
    # 将数据集按8:2比例随机分割
    X_train, X_test, y_train, y_test = train_test_split(
        images, labels, test_size=test_size, random_state=random_state
    )
    
    return X_train, X_test, y_train, y_test

(2)测试分割结果

np.random.seed(42)

# 分割数据集
X_train, X_test, y_train, y_test = split_mnist_data(detailed_mnist_dict)

print("MNIST数据集分割结果:")
print(f"训练集图像: {X_train.shape}")
print(f"训练集标签: {y_train.shape}")
print(f"测试集图像: {X_test.shape}")
print(f"测试集标签: {y_test.shape}")
print(f"分割比例: 训练集 {len(X_train)/70000*100:.1f}%, 测试集 {len(X_test)/70000*100:.1f}%")
MNIST数据集分割结果:
训练集图像: (56000, 28, 28)
训练集标签: (56000,)
测试集图像: (14000, 28, 28)
测试集标签: (14000,)
分割比例: 训练集 80.0%, 测试集 20.0%

五、读取医学影像数据

要求:Read and show 3 plane medical images in dicom and nifti

作业:

(1)dicom展示 2 维图片

# 读取DICOM文件
dcm_file_path = '/HW1-data/T1/00001.dcm'
dataset = pydicom.dcmread(dcm_file_path)
pixel_array = dataset.pixel_array  # 三维体数据?

# 输出基本信息
print(f"Patient's Name: {dataset.PatientName}")
print(f"Modality: {dataset.Modality}") 
print(f"Study Date: {dataset.StudyDate}")

# 来吧,展示~
plt.imshow(dataset.pixel_array, cmap=plt.cm.bone)
plt.show()

(2)nifti格式展示

# 加载NIfTI文件
img = nib.load('/Users/pangyu/Desktop/冬季课程/人工智能与医学图像分析/HW1-data/T1w.nii')  # 替换为实际文件路径
data = img.get_fdata()  # 获取三维数据(numpy数组)
print(f"数据形状: {data.shape}")  # 输出维度信息(如:512, 512, 161)
数据形状: (256, 256, 192)
# 计算中间切片位置
depth, height, width = data.shape
            
# 计算中间切片位置
z_slice = depth // 2    # 轴状面切片
y_slice = height // 2  # 冠状面切片
x_slice = width // 2    # 矢状面切片

# 提取切片
axial = data[z_slice, :, :]  # 轴状面
coronal = data[:, y_slice, :]  # 冠状面
sagittal = data[:, :, x_slice]  # 矢状面


# 可视化三个平面
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(15, 5))

# 显示轴状面
ax1.imshow(axial, cmap='gray')
ax1.set_title("Axial Plane")
ax1.axis('off')

# 显示冠状面
ax2.imshow(coronal, cmap='gray')
ax2.set_title("Coronal Plane")
ax2.axis('off')

# 显示矢状面
ax3.imshow(sagittal, cmap='gray')
ax3.set_title("Sagittal Plane")
ax3.axis('off')

plt.tight_layout()
plt.show()

完结撒花~

全部代码和结果在这儿:https://download.csdn.net/download/qq_28480795/92344905?spm=1011.2124.3001.6210

所用数据集在这儿:https://download.csdn.net/download/qq_28480795/92407692

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值