🚧 开发中 / Under Development
PallasAthena 是一套面向 FPS 游戏的玩家行为分析工具链,通过采集鼠标点击数据并与游戏录像对齐,实现开火行为的自动提取、分类、校准与可视化。
PallasAthena is a behavioral analysis toolkit for FPS games. It captures mouse click data, aligns it with gameplay recordings, and provides automated extraction, classification, calibration, and interactive visualization of firing behavior.
mouse_click 用于在游戏侧实时记录鼠标左键按下/释放行为,并按回合落盘为日志文件,作为后续 mouse_extract 的原始输入。
脚本位置:scripts/mouse_logger/mouse_click.py
- 建议将该脚本打包为 exe,并部署到游戏电脑端运行
- 游戏过程中按回合记录鼠标点击行为,再将生成的 session 目录拷回分析环境
N:开始/停止当前回合记录(toggle)P:停止并退出程序
程序启动后会在终端打印 session 输出目录。
脚本会在运行目录下创建:
session_YYYYMMDD_HHMMSS/round_001.log、round_001.jsonl(每轮递增)session_info.log
其中 round_*.jsonl 是后续 mouse_extract 的优先输入格式。
mouse_extract 用于把鼠标日志(round_*.jsonl / round_*.log)与同 session 内的视频(*.mp4)对齐,输出可用于后续可视化分析的 CSV。
脚本位置:scripts/mouse_extract/mouse_extract.py
默认情况下,脚本会自动向上查找项目根目录(包含 scripts/ 和 data/ 的目录),并使用:
- 输入目录:
<project_root>/data - 输出目录:
<project_root>/output
在输入目录下,当前只扫描 session_* 文件夹(已弃用其它命名)。
每个 session 目录内建议包含:
round_001.jsonl(优先读取)或round_001.loground_002.jsonl/round_002.log...- 对应回合视频
*.mp4
在项目根目录执行:
python scripts/mouse_extract/mouse_extract.pypython scripts/mouse_extract/mouse_extract.py --data-dir D:/path/to/data --output-dir D:/path/to/output支持参数:
--data-dir:日志和视频 session 根目录--output-dir:分析结果输出根目录
也支持环境变量:
PALLAS_DATA_DIRPALLAS_OUTPUT_DIR
优先级:命令行参数 > 环境变量 > 自动推断默认目录
输出会按原始 session 文件夹名落盘到 output/ 下:
output/
session_20260220_224249/
round_001_events.csv
round_001_bursts.csv
round_002_events.csv
round_002_bursts.csv
其中:
*_events.csv:逐事件(pressed/released)*_bursts.csv:按按下-释放配对后的持续段
- round 与视频按排序后一一对应(
round_1 -> 第1个mp4) - 视频开始时间从视频文件名解析(格式示例:
YYYY.MM.DD - HH.MM.SS[.NN].mp4) - 文件名末尾
NN是序号,不是秒的小数位;时间解析只取到HH.MM.SS
如果 mp4 数量与 round 数量不一致,脚本会给出 warning/note,并按较小数量处理。
mouse_extract 已修复文件名尾段语义(从“秒小数”改为“序号”)。
如果你之前基于旧逻辑生成过 CSV,建议:
- 重新运行
mouse_extract生成*_events.csv/*_bursts.csv - 重新运行
frame_offset_calibrator估计 offset - 使用新 offset 运行
burst_frame_viewer
burst_classifier 用于基于 *_bursts.csv 中的 n_frames 对 burst 进行三分类,并输出新增标签列后的 CSV。
脚本位置:scripts/burst_classifier/burst_classifier.py
--input指向的 CSV 必须包含列:n_frames- 输入与输出路径不能相同(脚本会报错,防止覆盖原始数据)
在项目根目录执行:
python scripts/burst_classifier/burst_classifier.py \
--input output/<session_id>/round_<round_id>_bursts.csv可选参数完整示例:
python scripts/burst_classifier/burst_classifier.py \
--input output/<session_id>/round_<round_id>_bursts.csv \
--output output/<session_id>/round_<round_id>_bursts_labeled.csv \
--threshN 20 \
--threshY 30占位符说明:
<session_id>:如session_20260324_203756<round_id>:如010
脚本会将 n_frames 转成数值后,按阈值写入新列 burst_label:
non_primary:n_frames < threshNprimary:n_frames >= threshYuncertain:threshN <= n_frames < threshY或n_frames无法解析为数值
--input(必填):输入 CSV 路径--output(选填):输出 CSV 路径;默认<输入文件名>_labeled.csv(与输入同目录)--threshN(选填,默认20):非主武器阈值--threshY(选填,默认30):主武器阈值
约束:threshN 不能大于 threshY,否则脚本报错。
- 在原有列基础上新增列:
burst_label - 若未传
--output,默认输出为<输入文件名>_labeled.csv - 运行结束会打印三类计数与输出文件路径
⚠️ 已弃用:推荐使用 Dashboard 的 Offset Calibrator 标签页(python scripts/visualization/app.py)进行交互式校准。CLI 版不会写入offsets.json,后续工具无法自动读取其结果。若仍需使用,请手动创建offsets.json。
frame_offset_calibrator 用于做“半自动帧偏移校准”:
- 自动读取 burst 参考帧并提取候选偏移帧
- 自动生成带标注的 contact sheet 拼图
- 人工根据拼图记录最合适的偏移值
脚本位置:scripts/frame_offset_calibrator/frame_offset_calibrator.py
推荐流程:
mouse_extract生成*_bursts.csvburst_classifier生成*_bursts_labeled.csvframe_offset_calibrator校准偏移并记录最终 offsetburst_frame_viewer使用校准后的 offset 批量截图
即:本模块放在 burst_classifier 与 burst_frame_viewer 之间。
--csv:输入 burst CSV(可用原始*_bursts.csv或带标签的*_bursts_labeled.csv)--video:对应 round 的视频文件- CSV 至少包含
frame0列(若使用--use-frame1,还需包含frame1)
说明:若 CSV 含 burst_label 列且存在 primary,脚本会先在 primary 集合中选参考 burst;否则在全体 burst 中选。
参考 burst 选择策略:
--hold-number -1(默认):随机选一个候选 burst--hold-number >= 0:按候选集合序号固定选取(0-based)--seed:仅在随机模式下生效;不传表示每次随机不同
最小示例:
python scripts/frame_offset_calibrator/frame_offset_calibrator.py \
--csv output/<session_id>/round_<round_id>_bursts_labeled.csv \
--video data/<session_id>/<video_file>.mp4完整示例:
python scripts/frame_offset_calibrator/frame_offset_calibrator.py \
--csv output/<session_id>/round_<round_id>_bursts_labeled.csv \
--video data/<session_id>/<video_file>.mp4 \
--offsetMIN 50 \
--offsetMAX 89 \
--hold-number -1 \
--out output/<session_id>/offset_sheets/round_<round_id>_sheet.png \
--cols 8 \
--gap 8 \
--tileW 960 \
--tileH 540固定候选序号示例:
python scripts/frame_offset_calibrator/frame_offset_calibrator.py \
--csv output/<session_id>/round_<round_id>_bursts_labeled.csv \
--video data/<session_id>/<video_file>.mp4 \
--hold-number 2可复现实验示例(随机 + 指定 seed):
python scripts/frame_offset_calibrator/frame_offset_calibrator.py \
--csv output/<session_id>/round_<round_id>_bursts_labeled.csv \
--video data/<session_id>/<video_file>.mp4 \
--hold-number -1 \
--seed 42--csv(必填):burst CSV 路径--video(必填):视频路径--offsetMIN(选填,默认50):最小偏移--offsetMAX(选填,默认89):最大偏移--hold-number(选填,默认-1):参考 burst 选择序号(-1随机,>=0固定序号)--seed(选填,默认不固定):随机种子(仅随机模式生效)--out(选填):拼图输出路径(默认<csv_stem>_offset_sheet.png)--cols(选填,默认8):每行子图数--gap(选填,默认8):子图间距像素--tileW(选填,默认960):子图宽度--tileH(选填,默认540):子图高度--use-frame1(选填):改用frame1作为参考帧(默认使用frame0)
- 输出一张带角标的 contact sheet(标注候选
offset与对应帧号) - 终端会打印参考帧、有效候选数与输出路径
- 人工从拼图中选择最终偏移值,用于后续
burst_frame_viewer --offset
burst_frame_viewer 用于从 *_bursts.csv 中读取开火帧的起始和终止帧号(frame0、frame1),结合给定视频提取截图,便于快速人工检查点击段对应画面。
脚本位置:scripts/burst_frame_viewer/burst_frame_viewer.py
--csv指向的 CSV 必须包含列:frame0、frame1- 可选列:
round(用于输出文件名;缺失时使用默认值) - 可选列:
burst_label(若存在,脚本会按标签自动分目录保存截图) --video指向可由 OpenCV 打开的mp4等视频文件
在项目根目录执行:
python scripts/burst_frame_viewer/burst_frame_viewer.py \
--csv output/<session_id>/round_<round_id>_bursts.csv \
--video data/<session_id>/<video_file>.mp4 \
--offset <offset_frames> \
--out output/<session_id>/burst_frames/round_<round_id>占位符说明:
<session_id>:如session_20260324_203756<round_id>:如010<video_file>:对应 round 的视频文件名(不含扩展名)<offset_frames>:整数帧偏移(如68)
--csv(必填):*_bursts.csv路径--video(必填):视频路径--offset(选填,整数):帧偏移量,脚本实际计算为adjusted = raw_frame - offset。若省略,脚本会自动从 CSV 同级目录的offsets.json中按 round 号读取对应 offset;若offsets.json不存在或无对应 round,脚本会报错并提示手动指定--out(选填):输出目录,默认output/<session_dir>/burst_frames/round_<number>
脚本会遍历 CSV 每一行,对 frame0 和 frame1 各尝试导出一张图。
输出文件名格式:
row{行号}_rnd{round}_{frame0|frame1}_r{原始帧}_a{偏移后帧}.png
例如:
row0001_rnd10_frame0_r12345_a12245.png
当 CSV 中包含 burst_label 列时,输出会自动分到标签子目录,例如:
<out>/primary/
<out>/non_primary/
<out>/uncertain/
若不存在 burst_label 列,则截图直接输出到 --out 目录。
以下情况会被跳过并打印提示:
- 偏移后帧号越界(
< 0或>= total_frames) - OpenCV 在指定帧读取失败
最终会打印统计:保存数量与跳过数量。
burst_label_annotater 用于对 burst_classifier 输出的 *_bursts_labeled.csv 进行两阶段人工标注:
- 第一阶段:复核标签(默认只复核
burst_label=uncertain) - 第二阶段:仅对
label_reviewed=primary的条目标注kills/deaths
脚本位置:scripts/burst_classifier/burst_label_annotater.py
推荐流程:
mouse_extract生成*_bursts.csvburst_classifier生成*_bursts_labeled.csvframe_offset_calibrator校准帧偏移burst_frame_viewer使用校准后的 offset 批量截图burst_label_annotater人工复核标注
即:本模块位于 burst_frame_viewer 之后,利用其生成的截图进行人工判读。
--csv:输入 CSV 必须包含burst_label列,且标签值仅限primary、non_primary、uncertain--frames-dir:burst_frame_viewer输出的截图目录(round 级别),例如output/session_xxx/burst_frames/round_001(可不传,自动推导)- CSV 还须包含列:
frame0、frame1、round - 使用
--stage2-only时,输入 CSV 还必须已有label_reviewed列
截图文件查找依据 burst_frame_viewer 的命名约定(row{行号}_rnd{round}_frame{0|1}_r{原始帧}_a{偏移帧}.png)。
基本用法(仅复核 uncertain,frames-dir 自动推导):
python scripts/burst_classifier/burst_label_annotater.py \
--csv output/<session_id>/round_<round_id>_bursts_labeled.csv手动指定截图目录:
python scripts/burst_classifier/burst_label_annotater.py \
--csv output/<session_id>/round_<round_id>_bursts_labeled.csv \
--frames-dir output/<session_id>/burst_frames/round_<round_id>全量复核模式(复核所有条目):
python scripts/burst_classifier/burst_label_annotater.py \
--csv output/<session_id>/round_<round_id>_bursts_labeled.csv \
-f仅运行第二阶段(跳过第一阶段):
python scripts/burst_classifier/burst_label_annotater.py \
--csv output/<session_id>/round_<round_id>_bursts_reviewed.csv \
--stage2-only指定输出路径:
python scripts/burst_classifier/burst_label_annotater.py \
--csv output/<session_id>/round_<round_id>_bursts_labeled.csv \
--out output/<session_id>/round_<round_id>_bursts_reviewed.csv--csv(必填):输入 labeled CSV 路径--frames-dir(选填):截图目录(round 级别);若不指定,脚本会从 CSV 路径自动推导,格式为<output_dir>/burst_frames/round_<round_id>--out(选填):输出 CSV 路径;默认在输入文件旁生成*_reviewed.csv(若输入为*_labeled.csv则输出为*_reviewed.csv)-f/--full-review(选填):启用全量复核模式,对所有条目标注(含primary和non_primary)--stage2-only(选填):跳过第一阶段,直接进入第二阶段(要求输入 CSV 已含label_reviewed)
P:标记为primaryN:标记为non_primaryU:保持uncertainB:返回上一条Q:结束第一阶段并进入第二阶段
每次按键判定后,终端会同步打印判定结果(例如:第xx行 -> primary)。
0-9:设置killsD:切换deaths(0 <-> 1)Enter:确认当前条目并跳到下一条B:返回上一条Q:保存并退出
- 在原有列基础上新增/维护列:
label_reviewed、kills、deaths - 第一阶段会写入
label_reviewed(原burst_label列不修改) - 第二阶段仅对
label_reviewed=primary的行标注kills/deaths - 非
primary行的kills/deaths保持空值
- 第一阶段默认只复核 uncertain;启用
-f后第一阶段复核全部条目 - 第二阶段始终从整个
frames-dir递归查找截图,并只筛选label_reviewed=primary条目 - 若某行缺少 frame0 或 frame1 截图,该行会被跳过并打印提示
burst_raster 用于把单个 round 的 *_bursts.csv、*_bursts_labeled.csv 或 *_bursts_reviewed.csv 画成中点栅格图:
三排主轨道(上→下):
primary(红)uncertain(黄)non_primary(灰)
可选两条事件轨道(仅当 CSV 含 kills/deaths 列时出现):
- 最上方:
kill近似时间点(绿色上三角) - 最下方:
death近似时间点(黑色下三角) - 两类事件点同时绘制竖向辅助线连接上下轨道
每个 burst 只保留时间中点,用于快速观察时间分布。
脚本位置:scripts/visualization/burst_raster.py
--input指向单个 round 的 bursts CSV- CSV 至少包含时间列之一:
t0_rel_sec+t1_rel_sec(优先)t0_unix+t1_unix
- 标签列优先级:
label_reviewed>burst_label> 全部归入non_primary label_reviewed中无有效标签值的行不绘制(直接丢弃)kills/deaths列(选填):来自burst_label_annotater第二阶段输出;有值时自动绘制事件轨道
python scripts/visualization/burst_raster.py \
--input output/<session_id>/round_<round_id>_bursts_reviewed.csv可选参数示例:
python scripts/visualization/burst_raster.py \
--input output/<session_id>/round_<round_id>_bursts_reviewed.csv \
--output output/<session_id>/round_<round_id>_bursts_raster.png \
--title "Round <round_id> Burst Raster"- x 轴虚线按固定 60 秒主刻度绘制
- y 轴三排标签固定;有事件轨道时图高自动增大(4.2 → 5.8)
- kill 近似时间点在 burst 持续段的 30%~80% 区间内随机分布;death 在 80%~95% 区间取一点(种子固定,可复现)
- 颜色主次:
primary最突出,uncertain次之,non_primary最淡
burst_scatter 用于按 session 批量可视化所有 round 的 burst:
- x 轴:burst 时间中点
- y 轴:round 编号(每个 round 一行)
- 点大小:与 burst 持续时长挂钩
- 点颜色:按
burst_label分类 - 支持 y 向微小 jitter,减少点重叠
脚本位置:scripts/visualization/burst_scatter.py
--session-dir指向一个 session 输出目录(例如output/session_20260220_224249)- 目录内可包含:
round_*_bursts_reviewed.csvround_*_bursts_labeled.csvround_*_bursts.csv
脚本会按 round 自动选源(三级优先):
*_bursts_reviewed.csv(最高优先)*_bursts_labeled.csv*_bursts.csv(无标签,全轮点用蓝色unlabeled绘制并打印提示)
若目录中没有可用 bursts CSV,则跳过绘图并提示。
标签列优先级:label_reviewed > burst_label > unlabeled;label_reviewed 中无有效值的行直接丢弃不绘制。
python scripts/visualization/burst_scatter.py \
--session-dir output/<session_id>带 jitter 参数示例:
python scripts/visualization/burst_scatter.py \
--session-dir output/<session_id> \
--jitter 0.08 \
--title "Burst Session Scatter"--session-dir(必填):session 目录路径--output(选填):输出 PNG 路径;默认<session_dir>/<session_name>_burst_session_scatter.png--title(选填):图标题--jitter(选填,默认0.08):每个 round 的 y 方向抖动幅度
app 是基于 Dash 的交互式可视化面板,包含两个标签页:
- Dashboard:Burst Raster + Session Scatter + 统计卡片
- Offset Calibrator:交互式帧偏移校准,替代静态 contact sheet 工作流
脚本位置:scripts/visualization/app.py
Dashboard 标签页是 burst_raster + burst_scatter 的交互版,是最终可视化入口。
Offset Calibrator 标签页可替代 frame_offset_calibrator 的全部功能(后者目前仍可独立使用,但是可能在将来弃用),在管线中位于 burst_classifier 与 burst_frame_viewer 之间。
在项目根目录执行:
python scripts/visualization/app.py带参数示例:
python scripts/visualization/app.py \
--data-dir output/ \
--port 8050 \
--debug启动后访问 http://localhost:8050。
--data-dir(选填):输出目录路径;默认自动推断(从 cwd / 脚本目录向上查找含session_*的output/)--port(选填,默认8050):监听端口--debug(选填):启用 Dash 调试模式(热重载 + 详细错误)
也支持环境变量 PALLAS_OUTPUT_DIR。
选择 session 和 round 后自动渲染:
- 统计卡片:total bursts、primary 数、kills、deaths、round 时长、平均 burst 持续
- Burst Raster:三轨道栅格 + kill/death 事件标记(与
burst_raster.py同构) - Session Scatter:全 session 散点(与
burst_scatter.py同构),点大小映射 duration
数据源优先级与 burst_scatter 一致:*_reviewed.csv > *_labeled.csv > *_bursts.csv。
Header 右侧提供 ↻ Refresh 按钮。点击后:
- 重新扫描
output/目录,发现新增的 session / round / CSV - 立即刷新当前 Dashboard 图表和 Calibrator 下拉选项
- 无需重启 Dashboard 服务器
用于交互式确定每个 round 的帧偏移量。
- 在 Calibrator 标签页选择 session 和 round
- 脚本自动加载该 round 的 burst 列表和对应视频(视频映射规则与
mouse_extract相同:排序后一一对应) - 使用 ◀ / ▶ 按钮浏览各 burst
- 使用 ±1 / ±10 按钮或直接输入数字调整 offset
- 画面实时显示
frame0 - offset和frame1 - offset对应的视频帧 - 确认满意后点击 💾 Save Offset 保存
每次保存会写入 output/<session_id>/offsets.json,格式如下:
{
"002": {"offset": 68, "source": "manual"},
"010": {"offset": 72, "source": "manual"}
}切换到已校准的 round 时,会自动加载已保存的 offset 值。
frame_offset_calibrator.py(CLI 版)已弃用,仍可独立运行但会提示迁移到 Dashboard- CLI 版不会写入
offsets.json,如需后续工具自动读取 offset,请手动创建 - 建议统一使用 Dashboard 进行 offset 校准
脚本会自动检测以下目录结构:
output/:从 cwd 和脚本目录向上逐级查找,优先选含session_*子目录的候选data/:取output/的同级data/目录,用于定位视频文件
- Dashboard 标注整合:将
burst_label_annotater的两阶段标注流程整合进 Dash Dashboard(scripts/visualization/app.py),利用 Web UI 提供更高效的鼠标点击交互,替代当前 cv2 弹窗方式。可参考已有的 offset 校准 Tab 实现。 - 枪击落点可视化:整合目标检测模型(如 YOLO),识别游戏画面中的命中反馈,实现枪击落点的自动标注与可视化。
无需手动指定路径即可在项目根目录直接运行。
run_pipeline 是 PallasAthena 的统一命令行入口,将提取、分类、截图、标注等步骤串联为一条命令。
脚本位置:scripts/run_pipeline.py
# Step 1: 提取 + 分类
python scripts/run_pipeline.py
# Step 2: 在 Dashboard 校准每个 round 的帧偏移
python scripts/visualization/app.py
# Step 3: 截图 + 人工标注
python scripts/run_pipeline.py --review
# Step 4: 在 Dashboard 查看最终结果;刷新或重启app.py即可默认:提取 + 分类
python scripts/run_pipeline.py从 data/session_* 读取日志和视频,产出 output/session_*/round_*_bursts_labeled.csv。
截图 + 标注(跳过提取分类)
python scripts/run_pipeline.py --review等价于 --skip-extract --skip-classify --run-frame-viewer --run-annotater。offset 自动从 offsets.json 读取;标注遍历所有 session/round,跳过已有 *_reviewed.csv 的。
只标注指定 session
python scripts/run_pipeline.py --run-annotater --annotate-session session_20260324_203756只标注指定 round
python scripts/run_pipeline.py --run-annotater --annotate-session session_20260324_203756 --annotate-round 5清理中间 CSV
python scripts/run_pipeline.py --cleanup-intermediate-csv保留最终可用 CSV(reviewed > labeled > raw),删除中间产物。
| 参数 | 说明 |
|---|---|
--data-dir |
输入 data 根目录(默认自动解析) |
--output-dir |
输出 output 根目录(默认自动解析) |
--review |
快捷模式:跳过提取分类,直接截图+标注 |
--skip-extract |
跳过 mouse_extract 阶段 |
--skip-classify |
跳过 burst_classifier 阶段 |
--overwrite-labeled |
覆盖已有 labeled CSV |
--threshN / --threshY |
burst_classifier 阈值(默认 20 / 30) |
--run-frame-viewer |
执行批量截图 |
--offset |
截图偏移值(省略则从 offsets.json 读取) |
--run-annotater |
执行人工标注(默认遍历全部) |
--annotate-session |
限定标注的 session |
--annotate-round |
限定标注的 round(需配合 --annotate-session) |
--overwrite-reviewed |
覆盖已有 reviewed CSV |
--full-review |
标注全量复核模式 |
--stage2-only |
标注仅第二阶段 |
--run-calibrator |
[已弃用] CLI offset 校准,请改用 Dashboard |
--cleanup-intermediate-csv |
清理中间 CSV |
--dry-run |
只打印命令,不实际执行 |