用Python自动化统计活体检测数据集信息的完整指南
面对CASIA、Replay等活体检测数据集时,手动统计视频文件数量、真假样本比例等信息既耗时又容易出错。本文将教你如何用Python编写自动化脚本,快速生成精确的数据集统计报告。
1. 准备工作与环境配置
在开始编写统计脚本前,我们需要确保开发环境配置正确。推荐使用Python 3.8+版本,这是目前大多数深度学习框架兼容性最好的版本。
首先安装必要的依赖库:
pip install pandas tqdmpandas:用于数据分析和生成结构化统计报告tqdm:为循环操作添加进度条,提升用户体验
建议创建一个专门的Python虚拟环境来管理这些依赖:
python -m venv dataset_stats source dataset_stats/bin/activate # Linux/Mac # 或 dataset_stats\Scripts\activate # Windows2. 理解数据集目录结构与命名规则
不同活体检测数据集的组织方式各不相同,准确理解其目录结构和命名规则是编写统计脚本的前提。
2.1 CASIA数据集结构分析
CASIA数据集通常按以下方式组织:
CASIA/ ├── train/ │ ├── subject_01/ │ │ ├── 1.avi │ │ ├── 2.avi │ │ ├── HR_1.avi │ │ ├── attack_01.avi │ │ └── ... │ └── ... └── test/ ├── subject_31/ │ ├── 1.avi │ ├── 2.avi │ ├── HR_1.avi │ ├── attack_01.avi │ └── ... └── ...关键特征:
- 每个subject包含12个视频
- 真实样本视频前缀为
1、2或HR_1 - 其余均为攻击样本
2.2 Replay数据集结构分析
Replay数据集的组织更为复杂:
Replay/ ├── train/ │ ├── real/ │ │ ├── client001_session01_controlled.avi │ │ └── ... │ └── attack/ │ ├── print_client001_session01_controlled.avi │ └── ... ├── devel/ # 同train结构 └── test/ # 同train结构特征:
- 明确分为real和attack子目录
- 文件名中包含client和session信息
3. 编写核心统计脚本
基于上述分析,我们可以编写一个通用脚本框架,然后针对不同数据集进行适配。
3.1 基础统计函数
import os from collections import defaultdict import pandas as pd from tqdm import tqdm def count_videos(dataset_path): """基础统计函数""" stats = { 'total': 0, 'real': 0, 'attack': 0, 'subjects': defaultdict(int) } for root, _, files in os.walk(dataset_path): for file in files: if file.endswith('.avi') or file.endswith('.mp4'): stats['total'] += 1 subject_id = os.path.basename(root) stats['subjects'][subject_id] += 1 # 根据文件名判断真实/攻击样本 if is_real_sample(file): stats['real'] += 1 else: stats['attack'] += 1 return stats3.2 数据集特定适配器
针对CASIA数据集:
def is_real_sample(filename): """CASIA数据集真实样本判断""" return filename.startswith(('1', '2', 'HR_1')) def analyze_casia(dataset_path): stats = count_videos(dataset_path) # 计算训练集/测试集划分 train_subjects = [f"subject_{i:02d}" for i in range(1, 21)] test_subjects = [f"subject_{i:02d}" for i in range(21, 51)] train_stats = { 'videos': sum(stats['subjects'][s] for s in train_subjects), 'real': 0, 'attack': 0 } # 更精确的统计实现... return { 'total': stats['total'], 'train': train_stats, 'test': test_stats }针对Replay数据集:
def analyze_replay(dataset_path): """Replay数据集专用分析函数""" stats = { 'train': {'real': 0, 'attack': 0}, 'devel': {'real': 0, 'attack': 0}, 'test': {'real': 0, 'attack': 0} } for split in ['train', 'devel', 'test']: split_path = os.path.join(dataset_path, split) real_path = os.path.join(split_path, 'real') attack_path = os.path.join(split_path, 'attack') # 统计真实样本 for root, _, files in os.walk(real_path): stats[split]['real'] += len([f for f in files if f.endswith('.avi')]) # 统计攻击样本 for root, _, files in os.walk(attack_path): stats[split]['attack'] += len([f for f in files if f.endswith('.avi')]) return stats4. 生成可视化统计报告
收集到原始统计数据后,我们可以使用pandas生成更专业的报告。
4.1 创建DataFrame
def create_stats_dataframe(stats, dataset_name): """将统计结果转换为DataFrame""" data = [] if dataset_name == 'CASIA': data.append({ 'Dataset': dataset_name, 'Split': 'Train', 'Real Videos': stats['train']['real'], 'Attack Videos': stats['train']['attack'], 'Total': stats['train']['videos'] }) # 添加测试集数据... elif dataset_name == 'Replay': for split in ['train', 'devel', 'test']: data.append({ 'Dataset': dataset_name, 'Split': split.capitalize(), 'Real Videos': stats[split]['real'], 'Attack Videos': stats[split]['attack'], 'Total': stats[split]['real'] + stats[split]['attack'] }) return pd.DataFrame(data)4.2 输出格式化报告
def generate_report(stats_df): """生成格式化的统计报告""" report = [] # 总体统计 total_real = stats_df['Real Videos'].sum() total_attack = stats_df['Attack Videos'].sum() report.append(f"## 数据集总体统计\n") report.append(f"- 总视频数: {total_real + total_attack}") report.append(f"- 真实样本比例: {total_real/(total_real+total_attack):.1%}") report.append(f"- 攻击样本比例: {total_attack/(total_real+total_attack):.1%}\n") # 按划分统计 report.append("## 按数据集划分统计") for _, row in stats_df.iterrows(): report.append( f"### {row['Split']}集\n" f"- 视频总数: {row['Total']}\n" f"- 真实样本: {row['Real Videos']} ({row['Real Videos']/row['Total']:.1%})\n" f"- 攻击样本: {row['Attack Videos']} ({row['Attack Videos']/row['Total']:.1%})" ) return "\n".join(report)5. 完整工作流集成
将上述组件整合成一个完整的脚本:
def main(): import argparse parser = argparse.ArgumentParser() parser.add_argument('dataset_path', help='Path to dataset directory') parser.add_argument('--dataset-type', choices=['casia', 'replay', 'oulu', 'msu'], required=True, help='Type of dataset to analyze') args = parser.parse_args() if args.dataset_type == 'casia': stats = analyze_casia(args.dataset_path) df = create_stats_dataframe(stats, 'CASIA') elif args.dataset_type == 'replay': stats = analyze_replay(args.dataset_path) df = create_stats_dataframe(stats, 'Replay') # 其他数据集适配... report = generate_report(df) print(report) # 可选:保存���文件 with open('dataset_report.md', 'w') as f: f.write(report) if __name__ == '__main__': main()使用方式:
python dataset_stats.py /path/to/casia --dataset-type casia6. 高级功能扩展
6.1 支持多数据集批量处理
def batch_analyze(datasets): """批量分析多个数据集""" all_stats = [] for name, path, dtype in tqdm(datasets, desc="Processing datasets"): try: if dtype == 'casia': stats = analyze_casia(path) df = create_stats_dataframe(stats, name) elif dtype == 'replay': stats = analyze_replay(path) df = create_stats_dataframe(stats, name) # 其他类型... all_stats.append(df) except Exception as e: print(f"Error processing {name}: {str(e)}") return pd.concat(all_stats)6.2 生成可视化图表
虽然本文不使用mermaid图表,但我们可以用文本表格增强可读性:
| 数据集 | 划分 | 真实样本 | 攻击样本 | 总计 | |---------|-------|---------|---------|-------| | CASIA | Train | 60 | 180 | 240 | | CASIA | Test | 90 | 270 | 360 | | Replay | Train | 60 | 300 | 360 | | Replay | Devel | 60 | 300 | 360 | | Replay | Test | 80 | 400 | 480 |6.3 异常检测与数据校验
def validate_dataset(stats, expected_counts): """验证数据集完整性""" errors = [] for split in expected_counts: if stats[split]['real'] != expected_counts[split]['real']: errors.append( f"{split}集真实样本数量异常: " f"期望{expected_counts[split]['real']}, 实际{stats[split]['real']}" ) # 其他验证... if errors: raise ValueError("数据集验证失败:\n" + "\n".join(errors))在实际项目中,我发现这种自动化统计脚本不仅能节省大量时间,还能避免人工统计中的疏漏。特别是在处理像OULU-NPU这样包含近5000个视频的大规模数据集时,手动统计几乎是不可能的任务。