CelebA数据集下载与预处理全指南:从官方渠道到高效加载

1次阅读
没有评论

共计 3415 个字符,预计需要花费 9 分钟才能阅读完成。

image.webp

背景痛点分析

CelebA 数据集作为人脸识别领域的基准数据集,包含超过 20 万张名人面部图像。但在实际使用中,开发者常遇到以下问题:

CelebA 数据集下载与预处理全指南:从官方渠道到高效加载

  • 下载速度慢:官方源位于香港中文大学服务器,国内直连速度常低于 100KB/s
  • 文件校验失败:10GB 的 img_align_celeba.zip 文件在传输中易出现损坏
  • 目录结构混乱:原始压缩包解压后包含 3 个子文件夹和 5 个标注文件,手动整理耗时
  • 内存瓶颈:直接加载全部图像会导致 32GB 内存机器 OOM(内存不足)

下载方案对比

官方源 vs 镜像源

  1. 官方源:
  2. URL:http://mmlab.ie.cuhk.edu.hk/projects/CelebA.html
  3. 优点:数据版本最新
  4. 缺点:单线程限速,无断点续传

  5. 国内镜像:

  6. 阿里云镜像:https://mirror.alibaba.com/celeba
  7. 百度网盘:提取码需关注公众号获取
  8. 优点:下载速度可达 10MB/s+
  9. 缺点:可能存在版本滞后问题

下载工具性能测试(1GB 测试文件)

工具 平均速度 断点续传 线程支持
wget 2.1MB/s 支持 单线程
aria2c 8.7MB/s 支持 16 线程
IDM 6.4MB/s 支持 8 线程

核心实现

带校验的下载脚本

import hashlib
import requests
from pathlib import Path
from tqdm import tqdm

def download_with_checksum(url: str, target_path: Path, md5: str = None):
    """
    带 MD5 校验的下载函数
    :param url: 下载链接
    :param target_path: 保存路径
    :param md5: 预期 MD5 值(可选)"""
    try:
        # 创建父目录
        target_path.parent.mkdir(parents=True, exist_ok=True)

        # 断点续传
        if target_path.exists():
            current_size = target_path.stat().st_size
            headers = {'Range': f'bytes={current_size}-'}
        else:
            current_size = 0
            headers = {}

        with requests.get(url, stream=True, headers=headers) as r, \
             open(target_path, 'ab') as f, \
             tqdm(unit='B', unit_scale=True, unit_divisor=1024, 
                  initial=current_size, total=int(r.headers.get('content-length', 0)) + current_size) as pbar:

            for chunk in r.iter_content(chunk_size=8192):
                if chunk:
                    f.write(chunk)
                    pbar.update(len(chunk))

        # MD5 校验
        if md5:
            file_md5 = hashlib.md5(open(target_path,'rb').read()).hexdigest()
            assert file_md5 == md5, f"MD5 校验失败: {file_md5} != {md5}"

    except Exception as e:
        if target_path.exists():
            target_path.unlink()
        raise RuntimeError(f"下载失败: {str(e)}")

人脸 ROI 裁剪示例

import cv2
import numpy as np

# CelebA 标注格式: [x1, y1, width, height]
def crop_face(image_path: str, bbox: list, margin: float = 0.2):
    """
    带边缘扩展的人脸裁剪
    :param image_path: 图像路径
    :param bbox: [x, y, w, h]格式的边界框
    :param margin: 扩展比例(0.2 表示扩展 20%):return: 裁剪后的 RGB 图像
    """
    img = cv2.imread(image_path)
    if img is None:
        raise ValueError(f"无法读取图像: {image_path}")

    h, w = img.shape[:2]
    x, y, bw, bh = bbox

    # 计算扩展后的区域
    new_x = max(0, x - margin * bw)
    new_y = max(0, y - margin * bh)
    new_w = min(w - new_x, bw * (1 + 2 * margin))
    new_h = min(h - new_y, bh * (1 + 2 * margin))

    cropped = img[int(new_y):int(new_y + new_h), 
                  int(new_x):int(new_x + new_w)]
    return cv2.cvtColor(cropped, cv2.COLOR_BGR2RGB)

性能优化

存储格式对比

格式 加载速度 磁盘占用 随机访问 适用场景
原始 JPEG 慢 小 差 初步实验
HDF5 快 中 优秀 中型数据集
TFRecord 最快 大 优秀 TensorFlow 训练
LMDB 快 小 优秀 超大规模数据集

多进程预处理模板

from multiprocessing import Pool
from functools import partial

def process_single_image(args, config):
    """单个图像的处理函数"""
    img_path, bbox = args
    try:
        img = crop_face(img_path, bbox)
        # 其他预处理...
        return img
    except Exception as e:
        print(f"处理失败 {img_path}: {str(e)}")
        return None

def batch_processing(image_list: list, workers: int = 8):
    """批量处理入口"""
    with Pool(workers) as p:
        # 使用 partial 固定配置参数
        processor = partial(process_single_image, config={"size": 256})
        results = list(tqdm(p.imap(processor, image_list), total=len(image_list)))
    return [r for r in results if r is not None]

避坑指南

标注文件编码问题

CelebA 的 list_attr_celeba.txt 使用 UTF- 8 编码,但部分操作系统可能误判为 ASCII。解决方案:

# 正确读取方式
with open('list_attr_celeba.txt', 'r', encoding='utf-8') as f:
    header = f.readline()  # 第一行是标题
    for line in f:
        parts = line.strip().split()
        filename = parts[0]
        attrs = list(map(int, parts[1:]))  # 属性值为 1 或 -1

内存优化技巧

  1. 生成器加载:

    def image_generator(file_list, batch_size=32):
        """分批生成图像数据"""
        for i in range(0, len(file_list), batch_size):
            batch = file_list[i:i + batch_size]
            yield [load_image(f) for f in batch]

  2. 内存映射文件:

    import numpy as np
    
    # 将预处理好的数据保存为内存映射格式
    arr = np.memmap('dataset.dat', dtype='float32', mode='w+', shape=(202599, 256, 256, 3))
    for i, img in enumerate(image_generator()):
        arr[i] = img

结语

通过本文介绍的方法,应该能帮助大家高效完成 CelebA 数据集的下载和预处理工作。在实际项目中,建议根据硬件条件和框架特性选择合适的存储格式。例如使用 PyTorch 时,可以优先考虑 LMDB 格式;而 TensorFlow 项目则更适合 TFRecord。

如果你有更好的预处理技巧或遇到文中未覆盖的问题,欢迎在评论区分享你的实践经验。对于大规模人脸识别项目,推荐进一步研究以下优化方向:

  • 使用 DALI 等 GPU 加速数据管道
  • 实现实时数据增强
  • 构建缓存机制避免重复预处理
正文完
 0
评论(没有评论)