# 3.5 体积数据

你已经学习了如何加载和表示2D图像，比如使用相机拍摄的图像。在诸如涉及CT（Computed Tomography）扫描等医学成像应用程序的情况下，通常需要处理从头到脚方向堆叠的图像序列，每个序列对应于整个身体的横截面。在CT扫描中，强度代表身体不同部位的密度：肺、脂肪、水、肌肉、骨骼，以密度递增的顺序排列，当在临床工作站上显示CT扫描时，会从暗到亮映射。根据穿过人体后到达检测器的X射线量计算每个点的密度，并使用一些复杂的数学运算将原始传感器数据反卷积（deconvolve）为完整体积数据。

CT具有单个的强度通道，这类似于灰度图像。通常在本地数据格式中，通道维度被忽略了，因此原始数据通常会具有三个维度。通过将单个2D切片堆叠到3D张量中，你可以构建表示对象的3D解剖结构的体积数据。与图3.3不同，图3.4中的额外的维表示物理空间中的偏移量，而不是可见光谱的特定频带。

<div align=center>
  <img width="600" src="../img/chapter3/3.4.png" alt="1.4">
</div>
<div align=center>图3.4 从头顶到颌骨的CT扫描切片</div>

我们并不会在此处详细介绍医学成像数据格式。现在，足以说存储体积数据的张量和存储图像数据的张量之间不存在根本差异。在通道（`channel`）维之后，你有一个额外的维——深度（`depth`），形成5D张量为`N x C x D x H x W`。

使用`imageio`模块中的`volread`函数加载一个CT扫描样本，该函数以文件夹作为参数，将所有[DICOM](https://wiki.cancerimagingarchive.net/display/Public/CPTAC-LSCC#dd4a08a246524596add33b9f8f00f288)（Digital Imaging Communication and Storage，数字图像通信和存储）系列文件组合成一个NumPy 3D数组中，如下所示。

```python
import imageio
dir_path = "../../data/chapter3/volumetric-dicom/2-LUNG 3.0  B70f-04083" 
vol_arr = imageio.volread(dir_path, 'DICOM') 
vol_arr.shape
```

输出：

```python
Reading DICOM (examining files): 1/99 files (1.0%99/99 files (100.0%)   Found 1 correct series.
Reading DICOM (loading data): 87/99  (87.999/99  (100.0%)                                         
(99, 512, 512)
```

同样，由于缺少通道信息，此时的维度设置与PyTorch所期望的不同。你必须通过`unsqueeze`为新增通道（`channel`）维：

```python
vol = torch.from_numpy(vol_arr).float() 
vol = torch.transpose(vol, 0, 2) 
vol = torch.unsqueeze(vol, 0)
vol.shape
```

输出：

```python
torch.Size([1, 512, 512, 99])
```

此时，你可以像本章前面所述通过沿批处理（`batch`）方向堆叠多个体积数据来组装5D数据集。

## 小结

在本章中，你学到了很多基础知识。你学习了如何加载最常见的数据类型并对其进行重塑，以供神经网络使用。当然，实际要处理的数据格式可能比单个体积数据中描述的更多。有些内容，例如医学史，过于复杂而无法涵盖。但是，对于感兴趣的读者，我们在[代码仓库](https://github.com/deep-learning-with-pytorch/dlwpt-code/tree/master/p1ch4)中提供了在Jupyter notebooks中创建的处理音视频张量的简单样例。

## 练习

* 用手机或其他数码相机拍摄几张红色、蓝色和绿色的照片（或者从网上下载，如果你没有相机的话）。
  - 加载每张图像，并将其转换为张量。
  - 对于每个图像张量，请使用`.mean()`方法来获得图像的亮度。
  - 现在，取图像每个通道的均值。你能否仅从通道平均值中识别出红色、绿色或蓝色的图片吗？

* 选择一个包含Python源代码的相对较大的文件。
  - 建立源文件中所有单词的索引。（标记化可随意简单或复杂；我们建议你先将`r"[^a-zA-Z0-9_]+”`替换为空格。
  - 将你的索引与为《傲慢与偏见》制定的索引进行比较。哪个更大？
  - 为源代码文件创建独热编码。
  - 这种编码会丢失什么信息？该信息与《傲慢与偏见》编码中丢失的信息相比如何？

## 总结

* 神经网络要求将数据表示为多维数值张量，通常为32位浮点数。
* 多亏了PyTorch库可以与Python标准库和周围的生态系统进行交互，因此可以方便地加载最常见的数据类型并将其转换为PyTorch张量。
* 通常，PyTorch期望沿特定维度布局数据，这取决于模型架构（例如卷积与递归）。使用PyTorch张量API可以有效地实现数据重塑。
* 电子表格可以很容易地直接转换为张量。类别和序数值列的处理方式应与区间值列的处理方式有所不同。
* 通过使用字典，文本或分类数据可以使用独热编码表示。
* 图像可以具有一个或多个通道。最常见的是典型数码照片的红色、绿色和蓝色通道。
* 单通道数据格式有时会忽略显式的通道维。
* 体积数据类似于2D图像数据，但增加了第三维：深度。
* 尽管12位和16位图像并不罕见，但是大多数图像每像素依然还是8位。这些图像可以存储为32位浮点数，并不会降低精度。