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
评论(没有评论)