# 加载图像数据

图像数据集包含 [Image](/docs/datasets/v5.2.0/zh/package_reference/main_classes#datasets.Image) 类型的列，其中包含 PIL 对象。

> [!TIP]
> 要处理图像数据集，您需要安装 `vision` 依赖项。请参阅 [安装](./installation#vision) 指南了解如何安装。

加载图像数据集并调用图像列时，图像会被解码为 PIL Images：

```py
>>> from datasets import load_dataset, Image

>>> dataset = load_dataset("AI-Lab-Makerere/beans", split="train")
>>> dataset[0]["image"]
```

> [!WARNING]
> 首先使用行索引，然后使用 `image` 列来索引图像数据集 - `dataset[0]["image"]` - 以避免解码和重新采样数据集中的所有图像对象。否则，如果数据集很大，这可能是一个缓慢且耗时的过程。

如需了解如何加载任意类型的数据集，请参阅通用加载指南。

## 本地文件

您可以从图像路径加载数据集。使用 [cast_column()](/docs/datasets/v5.2.0/zh/package_reference/main_classes#datasets.Dataset.cast_column) 函数接受一列图像文件路径，并使用 [Image](/docs/datasets/v5.2.0/zh/package_reference/main_classes#datasets.Image) 特征将其解码为 PIL 图像：
```py
>>> from datasets import Dataset, Image

>>> dataset = Dataset.from_dict({"image": ["path/to/image_1", "path/to/image_2", ..., "path/to/image_n"]}).cast_column("image", Image())
>>> dataset[0]["image"]
<PIL.PngImagePlugin.PngImageFile image mode=RGBA size=1200x215 at 0x15E6D7160>]
```

如果只想加载图像数据集的底层路径而不解码图像对象，请在 [Image](/docs/datasets/v5.2.0/zh/package_reference/main_classes#datasets.Image) 特征中设置 `decode=False`：

```py
>>> dataset = load_dataset("AI-Lab-Makerere/beans", split="train").cast_column("image", Image(decode=False))
>>> dataset[0]["image"]
{'bytes': None,
 'path': '/root/.cache/huggingface/datasets/downloads/extracted/b0a21163f78769a2cf11f58dfc767fb458fc7cea5c05dccc0144a2c0f0bc1292/train/bean_rust/bean_rust_train.29.jpg'}
```

## ImageFolder

你还可以通过 `ImageFolder` 数据集构建器加载数据集，这无需编写自定义的数据加载器。这使得 `ImageFolder` 非常适合快速创建和加载包含数千张图片的数据集，以用于不同的视觉任务。你的图像数据集结构应如下所示：

```
folder/train/dog/golden_retriever.png
folder/train/dog/german_shepherd.png
folder/train/dog/chihuahua.png

folder/train/cat/maine_coon.png
folder/train/cat/bengal.png
folder/train/cat/birman.png
```

或者它应该包含元数据，例如：

```
folder/train/metadata.csv
folder/train/0001.png
folder/train/0002.png
folder/train/0003.png
```

如果数据集遵循 `ImageFolder` 结构，则可以直接使用 [load_dataset()](/docs/datasets/v5.2.0/zh/package_reference/loading_methods#datasets.load_dataset) 加载：

```py
>>> from datasets import load_dataset

>>> dataset = load_dataset("username/dataset_name")
>>> # OR locally:
>>> dataset = load_dataset("/path/to/folder")
```

对于本地数据集，这相当于在 [load_dataset()](/docs/datasets/v5.2.0/zh/package_reference/loading_methods#datasets.load_dataset) 中手动传入 `imagefolder` 以及 `data_dir` 中的目录：

```py
>>> dataset = load_dataset("imagefolder", data_dir="/path/to/folder")
```

然后你可以将视频作为`PIL.Image`对象进行访问：

```
>>> dataset["train"][0]
{"image": <PIL.PngImagePlugin.PngImageFile image mode=RGBA size=1200x215 at 0x15E6D7160>, "label": 0}

>>> dataset["train"][-1]
{"image": <PIL.PngImagePlugin.PngImageFile image mode=RGBA size=1200x215 at 0x15E8DAD30>, "label": 1}
```

若要忽略元数据文件中的信息，请在 [load_dataset()](/docs/datasets/v5.2.0/zh/package_reference/loading_methods#datasets.load_dataset) 中设置 `drop_metadata=True`：

```py
>>> from datasets import load_dataset

>>> dataset = load_dataset("username/dataset_with_metadata", drop_metadata=True)
```

如果没有元数据文件，`ImageFolder` 会自动从目录名推断标签名称。如果要丢弃自动创建的标签，请设置 `drop_labels=True`。在这种情况下，您的数据集将只包含一个图像列：

```py
>>> from datasets import load_dataset

>>> dataset = load_dataset("username/dataset_without_metadata", drop_labels=True)
```

最后，`filters` 参数允许你基于标签或元数据中的条件，仅加载数据集的一个子集。如果元数据采用 Parquet 格式，这一点尤其有用，因为该格式支持快速过滤。同时，建议将此参数与 `streaming=True` 一起使用，因为默认情况下，数据集会在过滤之前被完整下载。

```python
>>> filters = [("label", "=", 0)]
>>> dataset = load_dataset("username/dataset_name", streaming=True, filters=filters)
```

> [!TIP]
> 有关创建自己的 `ImageFolder` 数据集的更多信息，请参阅 [创建图像数据集](./image_dataset) 指南。

## WebDataset

[WebDataset](https://github.com/webdataset/webdataset) 格式基于一个包含 TAR 归档文件的文件夹，适用于大型图像数据集。由于其体积庞大，WebDataset 通常以流式模式加载（使用 `streaming=True`）。

您可以按以下方式加载 WebDataset：

```python
>>> from datasets import load_dataset

>>> dataset = load_dataset("webdataset", data_dir="/path/to/folder", streaming=True)
```

## Lance

[Lance](https://lance.org) 是一种开放的多模态数据湖仓表格式。Lance 表不仅可以原生存储文本和标量值，还可以与您的表格数据一起存储图像、音频和视频等大型二进制对象（blobs）。

Lance 将元数据和图像 blob 集中存储在同一位置，同时仍允许你高效地仅扫描所需的元数据列，而无需加载图像字节。当你准备好时，可以获取一小部分行（包括图像 blob），并将它们直接写入本地文件系统上的文件。

```python
from datasets import load_dataset

# Return as a Hugging Face dataset
ds = load_dataset(
    "lance-format/laion-1m",
    split="train",
    streaming=True
)

dir_name = "laion_samples"
Path(dir_name).mkdir(exist_ok=True)

for idx, row in enumerate(ds.take(3)):
    with open(f"{dir_name}/{idx}.jpg", "wb") as f:
        f.write(row["image"])
```

在此示例中，`image` 列包含编码后的图像字节，因此您可以直接将其写入 `.jpg` 文件。

> [!NOTE] `datasets` API 目前不会将操作下推到 Lance 表，因此对于较大的数据集，速度可能较慢。目前，直接使用 `lance` Python 包可以获得更好的性能。有关使用示例，请参阅 [Hub](https://huggingface.co/docs/datasets-lance) 上的文档。

## 图像解码

默认情况下，在迭代数据集时，图像会按顺序解码为 `PIL.Images`。不过，使用多线程解码可以显著加快数据集的处理速度：

```python
>>> import os
>>> num_threads = num_threads = min(32, (os.cpu_count() or 1) + 4)
>>> dataset = dataset.decode(num_threads=num_threads)
>>> for example in dataset:  # up to 20 times faster !
...     ...
```

您可以使用 `num_threads` 来启用多线程。这对于加速远程数据流式传输特别有用。不过，对于位于高速磁盘上的本地数据，它可能比 `num_threads=0` 更慢。

如果您对解码为`PIL.Images`的图像不感兴趣，而是希望访问路径/字节，则可以禁用解码：

```python
>>> dataset = dataset.decode(False)
```

注意：[IterableDataset.decode()](/docs/datasets/v5.2.0/zh/package_reference/main_classes#datasets.IterableDataset.decode) 目前仅适用于流式数据集。

