Python自动化统计活体检测数据集视频数量的实战指南

在计算机视觉领域,活体检测算法的开发离不开高质量的数据集支持。CASIA、MSU-MFSD、Replay和Oulu等公开数据集因其标准化采集流程和丰富样本类型,成为研究者验证算法性能的首选基准库。然而这些数据集往往采用复杂的目录结构存储视频文件,手动统计各类样本数量不仅耗时费力,还容易出错。本文将分享一套基于Python的自动化统计方案,帮助开发者快速掌握数据集全貌。

1. 数据集结构解析与统计需求

活体检测数据集通常包含真实人脸样本和各类攻击样本(如打印照片、视频回放等),并按训练集、验证集和测试集划分。以CASIA数据集为例:

  • 目录结构: /dataset_root/subject_id/video_files
  • 命名规则:
    • 真实样本: HR_1.mp4 1.mp4 2.mp4
    • 攻击样本:其他命名模式的视频文件
  • 统计维度需求:
    • 各subject的视频数量
    • 真实/攻击样本分类统计
    • 训练集/测试集划分统计
# 典型数据集目录结构示例
CASIA/
├── train/
│   ├── subject_01/
│   │   ├── HR_1.avi
│   │   ├── 1.avi
│   │   ├── 2.avi
│   │   ├── attack_01.avi
│   │   └── ...
│   └── subject_02/
│       └── ...
└── test/
    ├── subject_31/
    └── ...

提示:不同数据集的文件命名规则可能有所差异,建议先检查官方文档或随机抽样验证命名模式

2. 核心Python库与工具链配置

实现自动化统计需要以下Python生态工具的支持:

工具库 用途 安装命令
os 文件系统操作 Python内置
glob 文件路径模式匹配 Python内置
pandas 数据统计与CSV导出 pip install pandas
tqdm 进度条显示 pip install tqdm
pathlib 面向对象的路径操作 Python内置
# 推荐创建conda环境进行依赖管理
conda create -n liveness_stats python=3.8
conda activate liveness_stats
pip install pandas tqdm

3. 通用统计脚本开发

下面是一个可扩展的统计脚本框架,支持处理多种活体检测数据集:

import os
from glob import glob
from collections import defaultdict
import pandas as pd
from tqdm import tqdm

class DatasetStats:
    def __init__(self, dataset_path):
        self.dataset_path = dataset_path
        self.stats = {
            'total': defaultdict(int),
            'train': defaultdict(int),
            'test': defaultdict(int),
            'devel': defaultdict(int)  # 部分数据集有开发集
        }
    
    def is_real_video(self, filename):
        """判断是否为真实样本的规则方法,需根据具体数据集重写"""
        return any(kw in filename.lower() for kw in ['hr_1', 'real', 'live'])

    def scan_dataset(self):
        for split in ['train', 'test', 'devel']:
            split_path = os.path.join(self.dataset_path, split)
            if not os.path.exists(split_path):
                continue
                
            subjects = os.listdir(split_path)
            for subject in tqdm(subjects, desc=f"Processing {split}"):
                subject_path = os.path.join(split_path, subject)
                videos = glob(os.path.join(subject_path, '*.*'))
                
                for video in videos:
                    video_name = os.path.basename(video)
                    if self.is_real_video(video_name):
                        self.stats[split]['real'] += 1
                        self.stats['total']['real'] += 1
                    else:
                        self.stats[split]['attack'] += 1
                        self.stats['total']['attack'] += 1
                    self.stats[split]['total'] += 1
                    self.stats['total']['total'] += 1

    def generate_report(self):
        report = pd.DataFrame.from_dict(self.stats, orient='index')
        report.fillna(0, inplace=True)
        return report

4. 数据集特定适配实现

针对不同数据集的特点,我们需要继承基类并实现特定规则:

4.1 CASIA数据集适配

class CASIAStats(DatasetStats):
    def is_real_video(self, filename):
        name = os.path.splitext(filename)[0].lower()
        return name in {'hr_1', '1', '2'}

# 使用示例
casia_stats = CASIAStats('/path/to/CASIA')
casia_stats.scan_dataset()
print(casia_stats.generate_report())

4.2 Replay数据集适配

class ReplayStats(DatasetStats):
    def scan_dataset(self):
        # Replay数据集有特殊的enroll子集
        super().scan_dataset()
        enroll_path = os.path.join(self.dataset_path, 'enroll')
        if os.path.exists(enroll_path):
            videos = glob(os.path.join(enroll_path, '*.*'))
            self.stats['enroll'] = {
                'real': len(videos),
                'attack': 0,
                'total': len(videos)
            }

    def is_real_video(self, filename):
        return 'real' in filename.lower()

4.3 统计结果可视化

将统计结果导出为结构化表格并生成可视化图表:

def save_statistics(report, output_dir):
    os.makedirs(output_dir, exist_ok=True)
    
    # 保存为CSV
    csv_path = os.path.join(output_dir, 'dataset_stats.csv')
    report.to_csv(csv_path)
    
    # 生成可视化图表
    import matplotlib.pyplot as plt
    report[['real', 'attack']].plot(kind='bar', stacked=True)
    plt.title('Dataset Composition')
    plt.ylabel('Video Count')
    plt.savefig(os.path.join(output_dir, 'stats.png'))
    plt.close()

5. 高级功能扩展

基础统计之外,还可以扩展以下实用功能:

  • 视频元数据提取 :使用OpenCV获取视频时长、分辨率等信息
  • 数据完整性校验 :检查每个subject是否包含规定数量的视频
  • 自动生成DataLoader配置 :直接输出PyTorch/TensorFlow可用的数据划分文件
def generate_dataloader_config(stats, output_path):
    """生成训练框架可用的数据划分配置文件"""
    config = {
        'train': {
            'real': [],
            'attack': []
        },
        'val': {
            'real': [],
            'attack': []
        }
    }
    
    for split in ['train', 'test', 'devel']:
        split_path = os.path.join(stats.dataset_path, split)
        for subject in os.listdir(split_path):
            subject_path = os.path.join(split_path, subject)
            for video in os.listdir(subject_path):
                video_path = os.path.join(split_path, subject, video)
                key = 'real' if stats.is_real_video(video) else 'attack'
                if split == 'devel':
                    config['val'][key].append(video_path)
                elif split == 'train':
                    config['train'][key].append(video_path)
    
    import json
    with open(output_path, 'w') as f:
        json.dump(config, f, indent=2)

在实际项目中,这套自动化统计方案可将原本需要数小时的手动检查工作缩短到几分钟内完成。我曾在一个跨数据集训练项目中,通过扩展脚本的校验功能,发现了下载过程中损坏的17个视频文件,避免了后续训练阶段的潜在问题。

更多推荐