image-flash-detector 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- image_flash_detector-0.1.0/PKG-INFO +214 -0
- image_flash_detector-0.1.0/README.md +201 -0
- image_flash_detector-0.1.0/pyproject.toml +27 -0
- image_flash_detector-0.1.0/setup.cfg +4 -0
- image_flash_detector-0.1.0/src/flash_detector_cpu/__init__.py +3 -0
- image_flash_detector-0.1.0/src/flash_detector_cpu/_launch.py +31 -0
- image_flash_detector-0.1.0/src/flash_detector_cpu/bin/image-flash-detector.exe +0 -0
- image_flash_detector-0.1.0/src/image_flash_detector.egg-info/PKG-INFO +214 -0
- image_flash_detector-0.1.0/src/image_flash_detector.egg-info/SOURCES.txt +10 -0
- image_flash_detector-0.1.0/src/image_flash_detector.egg-info/dependency_links.txt +1 -0
- image_flash_detector-0.1.0/src/image_flash_detector.egg-info/entry_points.txt +2 -0
- image_flash_detector-0.1.0/src/image_flash_detector.egg-info/top_level.txt +2 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: image-flash-detector
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Screen flash detection CLI for ordered screenshots or video frames; bundles image-flash-detector.exe on Windows.
|
|
5
|
+
Author: internal
|
|
6
|
+
Classifier: Programming Language :: Python :: 3
|
|
7
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
8
|
+
Classifier: Environment :: Console
|
|
9
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
10
|
+
Classifier: Topic :: Multimedia :: Video
|
|
11
|
+
Requires-Python: >=3.10
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
# flicker-detector-cpu-version
|
|
15
|
+
|
|
16
|
+
本仓库提供原生 **image-flash-detector** 命令行工具(C++/OpenCV),面向**有序截图或视频帧**的闪屏与异常画面检测,输出 JSON 结果。
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 1. 功能作用
|
|
21
|
+
|
|
22
|
+
- **做什么**:对**有序图像序列**或**视频逐帧**做闪屏/异常画面检测,输出结构化 **JSON**,便于自动化与外部工具集成。
|
|
23
|
+
- **典型输入**:目录下的连续截图(文件名含时间戳更佳)、视频文件、两张相邻图快速验证、或文本列表中的图片路径。
|
|
24
|
+
- **检测思路概要**:
|
|
25
|
+
- 计算相邻帧**模板相似度**;
|
|
26
|
+
- 用滑窗与统计将时间轴切分为 **稳定 / 动效 / 特殊** 场景;
|
|
27
|
+
- 在各场景下分别执行稳定区(含纯色块/视频低相似分支)、滑动动效、跟手特殊等分析;
|
|
28
|
+
- **合并**时间段并过滤花屏时刻等,得到最终的 `findings` 列表。
|
|
29
|
+
- **平台**:当前以 **Windows x64** 下编译得到的 **`image-flash-detector.exe`** 为主;也可从源码构建 wheel(内嵌该 exe),通过 PyPI 包名 **`image-flash-detector`** 分发(见 `publish.bat`)。
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 2. 使用方法
|
|
34
|
+
|
|
35
|
+
### 2.1 编译(Windows + vcpkg)
|
|
36
|
+
|
|
37
|
+
```bat
|
|
38
|
+
build.bat
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
或手动(需已安装 CMake、VS、vcpkg):
|
|
42
|
+
|
|
43
|
+
```powershell
|
|
44
|
+
cd <仓库根目录>
|
|
45
|
+
$env:VCPKG_ROOT = "<你的 vcpkg 路径>"
|
|
46
|
+
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_ROOT\scripts\buildsystems\vcpkg.cmake" -DVCPKG_TARGET_TRIPLET=x64-windows-static-md
|
|
47
|
+
cmake --build build --config Release
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
生成可执行文件:**`build\Release\image-flash-detector.exe`**(具体路径随生成器可能略有不同)。
|
|
51
|
+
|
|
52
|
+
如需更多视频封装格式,可在 `vcpkg.json` 中为 `opencv4` 增加 **`ffmpeg`** feature(编译更久、体积更大)。
|
|
53
|
+
|
|
54
|
+
### 2.2 命令行调用
|
|
55
|
+
|
|
56
|
+
```text
|
|
57
|
+
image-flash-detector.exe --type <dir|video|image|list> --input <路径> [--input <路径>...] --output <输出.json>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**必选参数**
|
|
61
|
+
|
|
62
|
+
| 参数 | 说明 |
|
|
63
|
+
|------|------|
|
|
64
|
+
| `--type` | 输入形态,见下表。 |
|
|
65
|
+
| `--input` | 输入路径;`image` 模式需写**两次** `--input`(前一帧、后一帧)。 |
|
|
66
|
+
| `--output` | 结果 JSON 文件路径。 |
|
|
67
|
+
|
|
68
|
+
**`--type` 与 `--input` 含义**
|
|
69
|
+
|
|
70
|
+
| `--type` | `--input` 含义 | 说明 |
|
|
71
|
+
|----------|----------------|------|
|
|
72
|
+
| `dir` | 单一路径:图片目录 | **不递归**子目录;仅常见扩展名(如 png/jpg/webp 等)。图片按**无扩展名的 stem** 做「下划线分段自然序」:用 `_` 切成多段,**段内全是数字则按数值比**(故 `0_…` 在 `1_…` 前),**否则按字典序**(故 `…_A` 在 `…_B` 前)。stem 相同时再按完整文件名字典序。 |
|
|
73
|
+
| `video` | 单一路径:视频文件 | 逐帧解码;默认按容器 FPS 推算每帧时间戳;帧会落到系统临时目录下的 PNG。 |
|
|
74
|
+
| `image` | 两个路径:`--input A --input B` | 仅两帧,用于快速验证管线。 |
|
|
75
|
+
| `list` | 单一路径:文本文件 | 每行一张图片路径,`#` 开头行为注释;顺序即时间序。 |
|
|
76
|
+
|
|
77
|
+
**可选参数**
|
|
78
|
+
|
|
79
|
+
| 参数 | 默认值 | 说明 |
|
|
80
|
+
|------|--------|------|
|
|
81
|
+
| `--fps` | `0` | 视频:覆盖 FPS;为 `0` 时用 OpenCV 从容器读取,失败时可手动指定。 |
|
|
82
|
+
| `--frame-interval-ms` | `0` | 为 `0` 时,`dir`/`list` 的时间戳来自文件名数字;**非 0** 时用 `帧序号 × 该值` 作为毫秒时间轴。 |
|
|
83
|
+
| `--config` | 无 | JSON 配置文件:业务字段 + **门限调参**(与 CLI 门限同名 snake_case 键),见下表。 |
|
|
84
|
+
|
|
85
|
+
**检测门限(可选)**
|
|
86
|
+
|
|
87
|
+
- 命令行:`image-flash-detector.exe --help` 查看 **`Thresholds (optional)`** 分组(如 `--stable-ratio`、`--video-low-similarity`、`--motional-sharp-delta` 等)。未指定时保持内置默认,与改参前行为一致。
|
|
88
|
+
- **优先级**:先读 `--config` 中的数值,再应用命令行中显式传入的门限(CLI 覆盖 JSON)。
|
|
89
|
+
- **仅 JSON**:稳定段细查的 `sf_*` 字段(如 `sf_scene_edge_sim`、`sf_rect_templ_min`)、以及 `video_sim_ratio_stages`(数组,元素为 `[帧数阈值, 相似度比例上限]`)只能在配置 JSON 里写,不设独立 CLI。键名与 [flash_params.hpp](src/flash/flash_params.hpp) 中成员一致。
|
|
90
|
+
|
|
91
|
+
**`--config` JSON 常用字段(可选)**
|
|
92
|
+
|
|
93
|
+
| 字段 | 类型 | 说明 |
|
|
94
|
+
|------|------|------|
|
|
95
|
+
| `step_name` | 字符串 | 含特定子串时会跳过整段场景解析(如部分拍照相关步骤)。 |
|
|
96
|
+
| `operation_type` | 字符串 | 如 `normal_swipe`:在动效段启用滑动闪屏分析。 |
|
|
97
|
+
| `swipe_type` | 字符串 | 如 `swipe_photo_scroll_bar`:整段按特殊场景处理。 |
|
|
98
|
+
| `action_type` | 字符串 | 如 `side_swipe`:与 `operation_type` 组合影响动效分析器挂载。 |
|
|
99
|
+
| `scene_type` | 字符串 | 如 `PLAY_VIDEO`:与 `normal_swipe` 等组合影响是否走「视频黑花闪」分支。 |
|
|
100
|
+
| `is_lock_special` | 布尔 | 解锁专项:按相似度切分后再解析等。 |
|
|
101
|
+
| `video_start_timestamp` | 整数 | 相对时间原点(毫秒);默认多为首帧时间。 |
|
|
102
|
+
| `blurred_image_time_list` | 整数数组 | 采集卡花屏时刻;落在此区间内的 finding 会被过滤。 |
|
|
103
|
+
|
|
104
|
+
查看全部开关:
|
|
105
|
+
|
|
106
|
+
```bat
|
|
107
|
+
image-flash-detector.exe --help
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 2.3 打包与发布(PyPI)
|
|
111
|
+
|
|
112
|
+
在仓库根目录执行 **`publish.bat`**(需已安装 [uv](https://docs.astral.sh/uv/)):会先编译原生程序、将 **`image-flash-detector.exe`** 拷入包内、再执行 **`uv build`** 生成 **`dist\`** 下的 wheel 与 sdist。
|
|
113
|
+
|
|
114
|
+
上传到 PyPI 前请在环境中设置 **`PYPI_TOKEN`**(API token);脚本在校验通过后会执行 **`uv publish --token %PYPI_TOKEN%`**。本地仅安装 wheel 时可用例如 **`uv pip install dist\*.whl`**(文件名随版本变化, setuptools 会将包名规范为下划线形式,如 `image_flash_detector-*.whl`)。
|
|
115
|
+
|
|
116
|
+
安装后可在控制台运行 **`image-flash-detector`**(与 `image-flash-detector.exe` 等价,由 Python 入口转发到捆绑的 exe)。
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## 3. 结果说明
|
|
121
|
+
|
|
122
|
+
输出为 **JSON**,根对象包含 **`version`**、**`input_type`**、**`findings`**。未检出时 **`findings` 为空数组 `[]`**(不代表画面绝对无问题,与阈值、场景划分、配置有关)。
|
|
123
|
+
|
|
124
|
+
### 3.1 根级字段
|
|
125
|
+
|
|
126
|
+
| 字段 | 类型 | 含义 |
|
|
127
|
+
|------|------|------|
|
|
128
|
+
| `version` | 整数 | 结果格式版本,当前为 `1`。 |
|
|
129
|
+
| `input_type` | 字符串 | 与本次 `--type` 一致:`dir` / `video` / `image` / `list`。 |
|
|
130
|
+
| `findings` | 数组 | 每条表示一段检出的**闪屏/异常时间区间**及元数据。 |
|
|
131
|
+
|
|
132
|
+
### 3.2 `findings[]` 每条记录:字段说明与 `scene` / `flash_type`
|
|
133
|
+
|
|
134
|
+
#### 字段列表
|
|
135
|
+
|
|
136
|
+
| 字段 | 类型 | 含义 |
|
|
137
|
+
|------|------|------|
|
|
138
|
+
| `flash_type` | 字符串 | **检出问题类型**(算法分支),取值与含义见本节 **「`flash_type` 常见取值」**。 |
|
|
139
|
+
| `scene` | 字符串 | 该 finding 所在时间段的场景切分类型,取值见本节 **「`scene` 取值」**。 |
|
|
140
|
+
| `start_time_ms` | 整数 | 区间起点**绝对时间戳**(毫秒)。 |
|
|
141
|
+
| `end_time_ms` | 整数 | 区间终点**绝对时间戳**(毫秒)。 |
|
|
142
|
+
| `during_time_ms` | 整数 | 持续时间,`end_time_ms - start_time_ms`。 |
|
|
143
|
+
| `video_start_time_ms` | 整数 | 相对**序列/视频时间原点**的起点:`start_time_ms - video_start_timestamp`。 |
|
|
144
|
+
| `video_end_time_ms` | 整数 | 相对原点的终点:`end_time_ms - video_start_timestamp`。 |
|
|
145
|
+
| `start_frame` | 整数 | 起点在输入序列中的**帧序号**(从 0 起,与加载顺序一致)。 |
|
|
146
|
+
| `end_frame` | 整数 | 终点帧序号。 |
|
|
147
|
+
| `path_start` | 字符串 | 起点帧对应的文件路径或展示用标签(视频临时帧可能为临时 PNG 路径或 `video:frame=N` 形式)。 |
|
|
148
|
+
| `path_end` | 字符串 | 终点帧对应路径或标签,含义同 `path_start`。 |
|
|
149
|
+
|
|
150
|
+
**时间戳与帧号**:目录/列表模式优先用**文件名 stem 前缀数字**作为毫秒时间;若使用 `--frame-interval-ms` 则用序号乘以间隔。视频模式按 FPS 将帧序号映射为毫秒。
|
|
151
|
+
|
|
152
|
+
#### `scene` 取值
|
|
153
|
+
|
|
154
|
+
| `scene` | 含义 |
|
|
155
|
+
|---------|------|
|
|
156
|
+
| `STABLE` | 算法将该区段判为**相对稳定**的界面停留段。 |
|
|
157
|
+
| `ANIMATOR` | 判为**动效/过渡**段(如列表滑动动画区域)。 |
|
|
158
|
+
| `SPECIAL` | 判为**特殊交互**段(如跟手滑动、相册滚动条等配置触发)。 |
|
|
159
|
+
|
|
160
|
+
#### `flash_type` 常见取值(场景向 + 算法向 + 阈值)
|
|
161
|
+
|
|
162
|
+
**稳定场景**指时间轴上被切分为 **`scene` = `STABLE`** 的一段:界面**整体相对静止**,多数相邻帧彼此很像(观感上页面停住,没有明显整列表滑动或全屏跟手拖拽),与动效段、特殊交互段区分;**上表**已列出三类 `scene` 的简要含义。
|
|
163
|
+
|
|
164
|
+
`stable_scene_change`、`stable_white_trans`、`stable_content` 在上述**稳定段**内、基于相邻帧差分区域做三帧细查;若整段被识别为**类视频播放**(如配置 `normal_swipe` + `PLAY_VIDEO`,或按帧率与相似度统计命中视频模式),则走 **`stable_video`** 分支:在序列上寻找**低模板相似度**帧并配对上报,而**不再**走上述差分矩形 + 三帧稳定细查路径(实现见 `src/flash/stable_analyzer.cpp` 中 `is_video_scene` / `analyze_video_scene_images`)。
|
|
165
|
+
|
|
166
|
+
`motional_swipe_pure` 仅在 **`scene` = `ANIMATOR`** 且配置为滑动动效时触发;`special_*` 在 **`scene` = `SPECIAL`** 的跟手等特殊段触发。
|
|
167
|
+
|
|
168
|
+
下列阈值均可通过 **`--config` JSON**(键名为 **snake_case**,与 [`flash_params.hpp`](src/flash/flash_params.hpp) 一致)或 **`--help` → Thresholds (optional)** 中部分 CLI 选项调整;未列出者多为仅 JSON 可调(如 `sf_*`)。**CLI 选项名**为同一键的 **kebab-case**(如 `stable_ratio` ↔ `--stable-ratio`)。
|
|
169
|
+
|
|
170
|
+
| `flash_type` | 场景角度说明(用户可见现象) | 算法角度说明(判定摘要) | 主要阈值参数(键名 · 默认 · 作用) |
|
|
171
|
+
|--------------|------------------------------|--------------------------|-------------------------------------|
|
|
172
|
+
| `stable_scene_change` | 整体仍像「停住」,但**某一局部**在极短时间内**内容跳变**:像闪了一小块错误图层、弹层错位,或整屏短暂和前后对不上。<br>有时表现为:前后两帧整体还能对齐,**中间一帧在变化区域里很突兀**。 | 在相邻帧差分得到的**变化矩形**上,取前/中/后三帧的局部与全局模板相似度、**相位相关**等;满足「中间帧在变化区内相似度偏低,但**首尾全图仍较像**」等组合条件,且异常持续时间落在阈值内(`check_scene_change`)。 | **`stable_ratio`** · `0.95` · 判定「稳定帧」的模板相似度下限。<br>**`stable_max_rect_area_ratio`** · `0.01` · 稳定帧允许的差分矩形最大面积占比。<br>**`rect_min_width_ratio`** / **`rect_min_height_ratio`** / **`rect_min_area_ratio`** · `0.1` / `0.05` / `0.01` · 过滤过小的差分轮廓。<br>**`sf_rect_templ_min`** · `0.9` · 候选「非闪光」矩形模板相似度下限(跳过)。<br>**`sf_rect_diff_max`** · `0.9` · 与上配合的矩形差分比上限。<br>**`sf_scene_edge_sim`** · `0.9` · 首尾全图相似度高于此且中间区低于 **`sf_scene_mid_sim`**(`0.8`)时快速判场景切换。<br>**`sf_pure_mid_high`** · `0.8`、**`sf_min_rect_ratio`** · `0.05` · 中间纯色过高或变化区过小时排除。<br>**`sf_rect_pure_high`** · `0.9`、**`sf_phase_corr_max`** · `0.5`、**`sf_prev_global_pure_high`** · `0.8` · 排除高纯色/高相关假阳性。<br>**`sf_template_mid_low`** · `0.5`、**`sf_pure_drop_max`** · `0.4` · 中间帧模板与主色跌落约束。<br>**`sf_rect_pure_hi_alt`** · `0.85`、**`sf_flash_ms_short`** · `100`、**`sf_flash_ms_long`** · `200` · 持续时间窗(ms)。<br>**`sf_max_lookback_frames`** · `10` · 向前追溯帧数上限。<br>**`sf_error_iou`** · `0.5` · 历史误差矩形与当前矩形 IOU 关联门槛。 |
|
|
173
|
+
| `stable_white_trans` | 稳定段里出现**偏亮/偏白的单色或近单色过渡**:像**闪白、蒙层突然变亮、灰阶被「洗」成一片**;通常**不是**长时间均匀渐隐(会尝试排除渐隐)。 | 在变化矩形内统计**主色占比与主色灰阶**沿三帧的变化;结合矩形模板相似度、三帧相似度方差等过滤正常过渡(`check_white_trans`)。 | 除上表 **`stable_*` / `rect_*` / `sf_rect_templ_min` / `sf_rect_diff_max` / `sf_max_lookback_frames`** 等公共前置外:<br>**`sf_white_mrt`** · `0.9` · 矩形模板相似度上限,高于则视为正常。<br>**`sf_white_mts`** · `0.95`、**`sf_white_std_ts`** · `0.01` · 三帧整体相似度与方差联合过滤「无波动」序列。<br>**`sf_white_pure_mid`** · `0.9`、**`sf_white_min_rd`** · `0.4` · 中间帧主色与相邻帧差分幅度。<br>**`sf_white_pure_max_group`** · `0.8` · 进入强白过渡分支的主色占比条件。<br>**`sf_white_pd_same_dir`** · `40`、**`sf_white_pd_opposite`** · `20` · 主色灰阶变化幅度(同向/反向)。<br>**`sf_white_mx01_max`** · `0.85`、**`sf_white_pure_pair_max`** · `0.85` · 首尾主色与中间配对约束。 |
|
|
174
|
+
| `stable_content` | 前后在变化区域**几乎像「空/纯色底」**,**中间一帧却像「有内容」或更花**:观感接近**中间多出一帧杂讯或错误内容**,前后又「回到」简单背景。 | 三帧在矩形内**主色占比**与**模板相似度**联合判定(`check_content_flash`)。 | 公共前置同 **`stable_scene_change`**(`stable_ratio`、`sf_rect_templ_min`、`sf_rect_diff_max` 等)。<br>**`sf_content_pure_end`** · `0.9` · 首尾帧矩形内主色占比须高于此。<br>**`sf_content_pure_mid`** · `0.8` · 中间帧主色占比须低于此。<br>**`sf_content_template_min`** · `0.9` · 三帧模板相似度最小值须低于此才上报。 |
|
|
175
|
+
| `stable_video` | 在**像在看视频**的那段里,**连续几帧对不上**(卡顿、花帧、黑场闪),或**相邻低相似帧成对**;也可能从**高纯色帧**切入下一帧异常。 | 段被 **`is_video_scene`** 标为类视频后,收集低模板相似帧并成对筛选(`analyze_video_scene_images`);另可由配置 **`operation_type`=`normal_swipe` 且 `scene_type`=`PLAY_VIDEO`** 强制走视频分支(非数值阈值)。 | **`video_high_similarity`** · `0.99` · 统计「高相似」帧的阈值。<br>**`video_scene_similarity_ratio_max`** · `0.3` · 高相似帧占比低于此则直接判为视频场景。<br>**`video_avg_fps_min`** · `20`、**`video_avg_fps_max`** · `60` · 平均运动帧率窗口。<br>**`video_sim_ratio_stages`** · `[[10,0.5],…,[100,0.1]]` · 按帧数分段的相似度比例表(仅 JSON)。<br>**`video_low_similarity`** · `0.5` · 低相似帧判定。<br>**`video_pair_near_ms`** · `200` · 两低相似帧间隔小于此(ms)易上报。<br>**`video_neighbor_pure_ratio`** · `0.7` · 邻帧高纯色时的上报条件。<br>**`video_pair_far_ms`** · `500` · 与前帧组合的时间上限(ms)。 |
|
|
176
|
+
| `motional_swipe_pure` | **滑动列表/页面**时中间**夹高纯色帧**,且**相似度陡变**;后续帧同色占比**剧烈跳变**。 | 需 **`operation_type`/`action_type`** 命中滑动动效;两次**陡变**间隔、中间纯色与后续**色占比跳变**(`motional_analyzer.cpp`)。 | **`motional_sharp_sim_delta`** · `0.5` · 相邻帧模板相似度差超过此记为陡变。<br>**`motional_sharp_max_span_ms`** · `200` · 两次陡变最大间隔(ms)。<br>**`motional_mid_pure_min`** · `0.2` · 中间帧纯色占比下限。<br>**`motional_color_jump_min`** · `0.1` · 后续帧同色占比相邻差最大值下限。<br>**`motional_sim_high_keep`** · `0.95` · 高于此相似度则重置「上一帧」参考。<br>**`motional_next_sim_threshold`** · `0.98` · 向前扫描时低于此相似度才采样纯色比例。 |
|
|
177
|
+
| `special_follow_hand_pure` | **跟手滑动**时**整图或大片突然高纯色**,常伴**左半屏仍稳定**。 | 纯色占比**升→降**包络;峰值帧**左半屏**主色约束;时间与阶跃幅度(`build_pure_flash`)。 | **`special_pure_spike`** · `0.3` · 相邻帧纯色占比上升/下降超过此触发峰谷检测。<br>**`special_pure_step_min`** · `0.2` · 峰值到前后相邻步长的最小变化(`build_pure_flash` 内)。<br>**`special_left_pure_min`** · `0.5` · 峰值帧左半屏主色占比下限。<br>**`special_pure_span_max_ms`** · `300` · 首末帧时间跨度上限(ms)。<br>**`special_template_break`** · `0.5` · 模板相似度低于此会打断峰跟踪。 |
|
|
178
|
+
| `special_follow_hand_low_similarity` | **多数帧连贯**,**中间一两帧**与前后明显不一致(孤立坏帧)。 | 当前与前一帧相似度双低,且**两侧窗口**内相似度均高(`special_analyzer.cpp`)。 | **`special_isolated_low_sim`** · `0.6` · 当前帧与前一帧模板相似度须**均不高于**此(代码中为 `>` 跳过)。<br>**`special_surround_sim_min`** · `0.9` · 左右各 **`special_surround_window`** 帧内相似度最小值须 ≥ 此值。<br>**`special_surround_window`** · `3` · 单侧参与统计的帧数。 |
|
|
179
|
+
|
|
180
|
+
实际运行中是否出现某一类,仍取决于场景切分、**`--config`** 与输入数据;调参后判定结果可能变化。
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## 4. 各异常类型检测流程图
|
|
185
|
+
|
|
186
|
+
流程图源文件在 **`./docs/flowcharts/*.mmd`**(Mermaid);下方插图路径均为**相对仓库根目录 `README.md`** 的 `./docs/flowcharts/*.png`(与 `src/` 同级下的 `docs/` 目录)。若修改 `.mmd`,可在 `docs/flowcharts` 目录执行:
|
|
187
|
+
|
|
188
|
+
`npx @mermaid-js/mermaid-cli -i <name>.mmd -o <name>.png -b white -w 1800 -H 1400`
|
|
189
|
+
|
|
190
|
+
对应实现:`src/flash/image_flash_analyzer.cpp`、`video_scene_parser.cpp`、`stable_analyzer.cpp`、`motional_analyzer.cpp`、`special_analyzer.cpp`。
|
|
191
|
+
|
|
192
|
+
### 4.1 总览:从输入到 `findings`
|
|
193
|
+
|
|
194
|
+

|
|
195
|
+
|
|
196
|
+
### 4.2 `STABLE` 段:视频类分支 vs 纯稳定分支
|
|
197
|
+
|
|
198
|
+

|
|
199
|
+
|
|
200
|
+
### 4.3 纯稳定三帧细查:`stable_scene_change` / `stable_white_trans` / `stable_content`
|
|
201
|
+
|
|
202
|
+

|
|
203
|
+
|
|
204
|
+
### 4.4 `stable_video`:低相似帧收集与成对上报
|
|
205
|
+
|
|
206
|
+

|
|
207
|
+
|
|
208
|
+
### 4.5 `motional_swipe_pure`(动效段 + 滑动配置)
|
|
209
|
+
|
|
210
|
+

|
|
211
|
+
|
|
212
|
+
### 4.6 `special_follow_hand_pure` 与 `special_follow_hand_low_similarity`
|
|
213
|
+
|
|
214
|
+

|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# flicker-detector-cpu-version
|
|
2
|
+
|
|
3
|
+
本仓库提供原生 **image-flash-detector** 命令行工具(C++/OpenCV),面向**有序截图或视频帧**的闪屏与异常画面检测,输出 JSON 结果。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. 功能作用
|
|
8
|
+
|
|
9
|
+
- **做什么**:对**有序图像序列**或**视频逐帧**做闪屏/异常画面检测,输出结构化 **JSON**,便于自动化与外部工具集成。
|
|
10
|
+
- **典型输入**:目录下的连续截图(文件名含时间戳更佳)、视频文件、两张相邻图快速验证、或文本列表中的图片路径。
|
|
11
|
+
- **检测思路概要**:
|
|
12
|
+
- 计算相邻帧**模板相似度**;
|
|
13
|
+
- 用滑窗与统计将时间轴切分为 **稳定 / 动效 / 特殊** 场景;
|
|
14
|
+
- 在各场景下分别执行稳定区(含纯色块/视频低相似分支)、滑动动效、跟手特殊等分析;
|
|
15
|
+
- **合并**时间段并过滤花屏时刻等,得到最终的 `findings` 列表。
|
|
16
|
+
- **平台**:当前以 **Windows x64** 下编译得到的 **`image-flash-detector.exe`** 为主;也可从源码构建 wheel(内嵌该 exe),通过 PyPI 包名 **`image-flash-detector`** 分发(见 `publish.bat`)。
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 2. 使用方法
|
|
21
|
+
|
|
22
|
+
### 2.1 编译(Windows + vcpkg)
|
|
23
|
+
|
|
24
|
+
```bat
|
|
25
|
+
build.bat
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
或手动(需已安装 CMake、VS、vcpkg):
|
|
29
|
+
|
|
30
|
+
```powershell
|
|
31
|
+
cd <仓库根目录>
|
|
32
|
+
$env:VCPKG_ROOT = "<你的 vcpkg 路径>"
|
|
33
|
+
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_ROOT\scripts\buildsystems\vcpkg.cmake" -DVCPKG_TARGET_TRIPLET=x64-windows-static-md
|
|
34
|
+
cmake --build build --config Release
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
生成可执行文件:**`build\Release\image-flash-detector.exe`**(具体路径随生成器可能略有不同)。
|
|
38
|
+
|
|
39
|
+
如需更多视频封装格式,可在 `vcpkg.json` 中为 `opencv4` 增加 **`ffmpeg`** feature(编译更久、体积更大)。
|
|
40
|
+
|
|
41
|
+
### 2.2 命令行调用
|
|
42
|
+
|
|
43
|
+
```text
|
|
44
|
+
image-flash-detector.exe --type <dir|video|image|list> --input <路径> [--input <路径>...] --output <输出.json>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**必选参数**
|
|
48
|
+
|
|
49
|
+
| 参数 | 说明 |
|
|
50
|
+
|------|------|
|
|
51
|
+
| `--type` | 输入形态,见下表。 |
|
|
52
|
+
| `--input` | 输入路径;`image` 模式需写**两次** `--input`(前一帧、后一帧)。 |
|
|
53
|
+
| `--output` | 结果 JSON 文件路径。 |
|
|
54
|
+
|
|
55
|
+
**`--type` 与 `--input` 含义**
|
|
56
|
+
|
|
57
|
+
| `--type` | `--input` 含义 | 说明 |
|
|
58
|
+
|----------|----------------|------|
|
|
59
|
+
| `dir` | 单一路径:图片目录 | **不递归**子目录;仅常见扩展名(如 png/jpg/webp 等)。图片按**无扩展名的 stem** 做「下划线分段自然序」:用 `_` 切成多段,**段内全是数字则按数值比**(故 `0_…` 在 `1_…` 前),**否则按字典序**(故 `…_A` 在 `…_B` 前)。stem 相同时再按完整文件名字典序。 |
|
|
60
|
+
| `video` | 单一路径:视频文件 | 逐帧解码;默认按容器 FPS 推算每帧时间戳;帧会落到系统临时目录下的 PNG。 |
|
|
61
|
+
| `image` | 两个路径:`--input A --input B` | 仅两帧,用于快速验证管线。 |
|
|
62
|
+
| `list` | 单一路径:文本文件 | 每行一张图片路径,`#` 开头行为注释;顺序即时间序。 |
|
|
63
|
+
|
|
64
|
+
**可选参数**
|
|
65
|
+
|
|
66
|
+
| 参数 | 默认值 | 说明 |
|
|
67
|
+
|------|--------|------|
|
|
68
|
+
| `--fps` | `0` | 视频:覆盖 FPS;为 `0` 时用 OpenCV 从容器读取,失败时可手动指定。 |
|
|
69
|
+
| `--frame-interval-ms` | `0` | 为 `0` 时,`dir`/`list` 的时间戳来自文件名数字;**非 0** 时用 `帧序号 × 该值` 作为毫秒时间轴。 |
|
|
70
|
+
| `--config` | 无 | JSON 配置文件:业务字段 + **门限调参**(与 CLI 门限同名 snake_case 键),见下表。 |
|
|
71
|
+
|
|
72
|
+
**检测门限(可选)**
|
|
73
|
+
|
|
74
|
+
- 命令行:`image-flash-detector.exe --help` 查看 **`Thresholds (optional)`** 分组(如 `--stable-ratio`、`--video-low-similarity`、`--motional-sharp-delta` 等)。未指定时保持内置默认,与改参前行为一致。
|
|
75
|
+
- **优先级**:先读 `--config` 中的数值,再应用命令行中显式传入的门限(CLI 覆盖 JSON)。
|
|
76
|
+
- **仅 JSON**:稳定段细查的 `sf_*` 字段(如 `sf_scene_edge_sim`、`sf_rect_templ_min`)、以及 `video_sim_ratio_stages`(数组,元素为 `[帧数阈值, 相似度比例上限]`)只能在配置 JSON 里写,不设独立 CLI。键名与 [flash_params.hpp](src/flash/flash_params.hpp) 中成员一致。
|
|
77
|
+
|
|
78
|
+
**`--config` JSON 常用字段(可选)**
|
|
79
|
+
|
|
80
|
+
| 字段 | 类型 | 说明 |
|
|
81
|
+
|------|------|------|
|
|
82
|
+
| `step_name` | 字符串 | 含特定子串时会跳过整段场景解析(如部分拍照相关步骤)。 |
|
|
83
|
+
| `operation_type` | 字符串 | 如 `normal_swipe`:在动效段启用滑动闪屏分析。 |
|
|
84
|
+
| `swipe_type` | 字符串 | 如 `swipe_photo_scroll_bar`:整段按特殊场景处理。 |
|
|
85
|
+
| `action_type` | 字符串 | 如 `side_swipe`:与 `operation_type` 组合影响动效分析器挂载。 |
|
|
86
|
+
| `scene_type` | 字符串 | 如 `PLAY_VIDEO`:与 `normal_swipe` 等组合影响是否走「视频黑花闪」分支。 |
|
|
87
|
+
| `is_lock_special` | 布尔 | 解锁专项:按相似度切分后再解析等。 |
|
|
88
|
+
| `video_start_timestamp` | 整数 | 相对时间原点(毫秒);默认多为首帧时间。 |
|
|
89
|
+
| `blurred_image_time_list` | 整数数组 | 采集卡花屏时刻;落在此区间内的 finding 会被过滤。 |
|
|
90
|
+
|
|
91
|
+
查看全部开关:
|
|
92
|
+
|
|
93
|
+
```bat
|
|
94
|
+
image-flash-detector.exe --help
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### 2.3 打包与发布(PyPI)
|
|
98
|
+
|
|
99
|
+
在仓库根目录执行 **`publish.bat`**(需已安装 [uv](https://docs.astral.sh/uv/)):会先编译原生程序、将 **`image-flash-detector.exe`** 拷入包内、再执行 **`uv build`** 生成 **`dist\`** 下的 wheel 与 sdist。
|
|
100
|
+
|
|
101
|
+
上传到 PyPI 前请在环境中设置 **`PYPI_TOKEN`**(API token);脚本在校验通过后会执行 **`uv publish --token %PYPI_TOKEN%`**。本地仅安装 wheel 时可用例如 **`uv pip install dist\*.whl`**(文件名随版本变化, setuptools 会将包名规范为下划线形式,如 `image_flash_detector-*.whl`)。
|
|
102
|
+
|
|
103
|
+
安装后可在控制台运行 **`image-flash-detector`**(与 `image-flash-detector.exe` 等价,由 Python 入口转发到捆绑的 exe)。
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## 3. 结果说明
|
|
108
|
+
|
|
109
|
+
输出为 **JSON**,根对象包含 **`version`**、**`input_type`**、**`findings`**。未检出时 **`findings` 为空数组 `[]`**(不代表画面绝对无问题,与阈值、场景划分、配置有关)。
|
|
110
|
+
|
|
111
|
+
### 3.1 根级字段
|
|
112
|
+
|
|
113
|
+
| 字段 | 类型 | 含义 |
|
|
114
|
+
|------|------|------|
|
|
115
|
+
| `version` | 整数 | 结果格式版本,当前为 `1`。 |
|
|
116
|
+
| `input_type` | 字符串 | 与本次 `--type` 一致:`dir` / `video` / `image` / `list`。 |
|
|
117
|
+
| `findings` | 数组 | 每条表示一段检出的**闪屏/异常时间区间**及元数据。 |
|
|
118
|
+
|
|
119
|
+
### 3.2 `findings[]` 每条记录:字段说明与 `scene` / `flash_type`
|
|
120
|
+
|
|
121
|
+
#### 字段列表
|
|
122
|
+
|
|
123
|
+
| 字段 | 类型 | 含义 |
|
|
124
|
+
|------|------|------|
|
|
125
|
+
| `flash_type` | 字符串 | **检出问题类型**(算法分支),取值与含义见本节 **「`flash_type` 常见取值」**。 |
|
|
126
|
+
| `scene` | 字符串 | 该 finding 所在时间段的场景切分类型,取值见本节 **「`scene` 取值」**。 |
|
|
127
|
+
| `start_time_ms` | 整数 | 区间起点**绝对时间戳**(毫秒)。 |
|
|
128
|
+
| `end_time_ms` | 整数 | 区间终点**绝对时间戳**(毫秒)。 |
|
|
129
|
+
| `during_time_ms` | 整数 | 持续时间,`end_time_ms - start_time_ms`。 |
|
|
130
|
+
| `video_start_time_ms` | 整数 | 相对**序列/视频时间原点**的起点:`start_time_ms - video_start_timestamp`。 |
|
|
131
|
+
| `video_end_time_ms` | 整数 | 相对原点的终点:`end_time_ms - video_start_timestamp`。 |
|
|
132
|
+
| `start_frame` | 整数 | 起点在输入序列中的**帧序号**(从 0 起,与加载顺序一致)。 |
|
|
133
|
+
| `end_frame` | 整数 | 终点帧序号。 |
|
|
134
|
+
| `path_start` | 字符串 | 起点帧对应的文件路径或展示用标签(视频临时帧可能为临时 PNG 路径或 `video:frame=N` 形式)。 |
|
|
135
|
+
| `path_end` | 字符串 | 终点帧对应路径或标签,含义同 `path_start`。 |
|
|
136
|
+
|
|
137
|
+
**时间戳与帧号**:目录/列表模式优先用**文件名 stem 前缀数字**作为毫秒时间;若使用 `--frame-interval-ms` 则用序号乘以间隔。视频模式按 FPS 将帧序号映射为毫秒。
|
|
138
|
+
|
|
139
|
+
#### `scene` 取值
|
|
140
|
+
|
|
141
|
+
| `scene` | 含义 |
|
|
142
|
+
|---------|------|
|
|
143
|
+
| `STABLE` | 算法将该区段判为**相对稳定**的界面停留段。 |
|
|
144
|
+
| `ANIMATOR` | 判为**动效/过渡**段(如列表滑动动画区域)。 |
|
|
145
|
+
| `SPECIAL` | 判为**特殊交互**段(如跟手滑动、相册滚动条等配置触发)。 |
|
|
146
|
+
|
|
147
|
+
#### `flash_type` 常见取值(场景向 + 算法向 + 阈值)
|
|
148
|
+
|
|
149
|
+
**稳定场景**指时间轴上被切分为 **`scene` = `STABLE`** 的一段:界面**整体相对静止**,多数相邻帧彼此很像(观感上页面停住,没有明显整列表滑动或全屏跟手拖拽),与动效段、特殊交互段区分;**上表**已列出三类 `scene` 的简要含义。
|
|
150
|
+
|
|
151
|
+
`stable_scene_change`、`stable_white_trans`、`stable_content` 在上述**稳定段**内、基于相邻帧差分区域做三帧细查;若整段被识别为**类视频播放**(如配置 `normal_swipe` + `PLAY_VIDEO`,或按帧率与相似度统计命中视频模式),则走 **`stable_video`** 分支:在序列上寻找**低模板相似度**帧并配对上报,而**不再**走上述差分矩形 + 三帧稳定细查路径(实现见 `src/flash/stable_analyzer.cpp` 中 `is_video_scene` / `analyze_video_scene_images`)。
|
|
152
|
+
|
|
153
|
+
`motional_swipe_pure` 仅在 **`scene` = `ANIMATOR`** 且配置为滑动动效时触发;`special_*` 在 **`scene` = `SPECIAL`** 的跟手等特殊段触发。
|
|
154
|
+
|
|
155
|
+
下列阈值均可通过 **`--config` JSON**(键名为 **snake_case**,与 [`flash_params.hpp`](src/flash/flash_params.hpp) 一致)或 **`--help` → Thresholds (optional)** 中部分 CLI 选项调整;未列出者多为仅 JSON 可调(如 `sf_*`)。**CLI 选项名**为同一键的 **kebab-case**(如 `stable_ratio` ↔ `--stable-ratio`)。
|
|
156
|
+
|
|
157
|
+
| `flash_type` | 场景角度说明(用户可见现象) | 算法角度说明(判定摘要) | 主要阈值参数(键名 · 默认 · 作用) |
|
|
158
|
+
|--------------|------------------------------|--------------------------|-------------------------------------|
|
|
159
|
+
| `stable_scene_change` | 整体仍像「停住」,但**某一局部**在极短时间内**内容跳变**:像闪了一小块错误图层、弹层错位,或整屏短暂和前后对不上。<br>有时表现为:前后两帧整体还能对齐,**中间一帧在变化区域里很突兀**。 | 在相邻帧差分得到的**变化矩形**上,取前/中/后三帧的局部与全局模板相似度、**相位相关**等;满足「中间帧在变化区内相似度偏低,但**首尾全图仍较像**」等组合条件,且异常持续时间落在阈值内(`check_scene_change`)。 | **`stable_ratio`** · `0.95` · 判定「稳定帧」的模板相似度下限。<br>**`stable_max_rect_area_ratio`** · `0.01` · 稳定帧允许的差分矩形最大面积占比。<br>**`rect_min_width_ratio`** / **`rect_min_height_ratio`** / **`rect_min_area_ratio`** · `0.1` / `0.05` / `0.01` · 过滤过小的差分轮廓。<br>**`sf_rect_templ_min`** · `0.9` · 候选「非闪光」矩形模板相似度下限(跳过)。<br>**`sf_rect_diff_max`** · `0.9` · 与上配合的矩形差分比上限。<br>**`sf_scene_edge_sim`** · `0.9` · 首尾全图相似度高于此且中间区低于 **`sf_scene_mid_sim`**(`0.8`)时快速判场景切换。<br>**`sf_pure_mid_high`** · `0.8`、**`sf_min_rect_ratio`** · `0.05` · 中间纯色过高或变化区过小时排除。<br>**`sf_rect_pure_high`** · `0.9`、**`sf_phase_corr_max`** · `0.5`、**`sf_prev_global_pure_high`** · `0.8` · 排除高纯色/高相关假阳性。<br>**`sf_template_mid_low`** · `0.5`、**`sf_pure_drop_max`** · `0.4` · 中间帧模板与主色跌落约束。<br>**`sf_rect_pure_hi_alt`** · `0.85`、**`sf_flash_ms_short`** · `100`、**`sf_flash_ms_long`** · `200` · 持续时间窗(ms)。<br>**`sf_max_lookback_frames`** · `10` · 向前追溯帧数上限。<br>**`sf_error_iou`** · `0.5` · 历史误差矩形与当前矩形 IOU 关联门槛。 |
|
|
160
|
+
| `stable_white_trans` | 稳定段里出现**偏亮/偏白的单色或近单色过渡**:像**闪白、蒙层突然变亮、灰阶被「洗」成一片**;通常**不是**长时间均匀渐隐(会尝试排除渐隐)。 | 在变化矩形内统计**主色占比与主色灰阶**沿三帧的变化;结合矩形模板相似度、三帧相似度方差等过滤正常过渡(`check_white_trans`)。 | 除上表 **`stable_*` / `rect_*` / `sf_rect_templ_min` / `sf_rect_diff_max` / `sf_max_lookback_frames`** 等公共前置外:<br>**`sf_white_mrt`** · `0.9` · 矩形模板相似度上限,高于则视为正常。<br>**`sf_white_mts`** · `0.95`、**`sf_white_std_ts`** · `0.01` · 三帧整体相似度与方差联合过滤「无波动」序列。<br>**`sf_white_pure_mid`** · `0.9`、**`sf_white_min_rd`** · `0.4` · 中间帧主色与相邻帧差分幅度。<br>**`sf_white_pure_max_group`** · `0.8` · 进入强白过渡分支的主色占比条件。<br>**`sf_white_pd_same_dir`** · `40`、**`sf_white_pd_opposite`** · `20` · 主色灰阶变化幅度(同向/反向)。<br>**`sf_white_mx01_max`** · `0.85`、**`sf_white_pure_pair_max`** · `0.85` · 首尾主色与中间配对约束。 |
|
|
161
|
+
| `stable_content` | 前后在变化区域**几乎像「空/纯色底」**,**中间一帧却像「有内容」或更花**:观感接近**中间多出一帧杂讯或错误内容**,前后又「回到」简单背景。 | 三帧在矩形内**主色占比**与**模板相似度**联合判定(`check_content_flash`)。 | 公共前置同 **`stable_scene_change`**(`stable_ratio`、`sf_rect_templ_min`、`sf_rect_diff_max` 等)。<br>**`sf_content_pure_end`** · `0.9` · 首尾帧矩形内主色占比须高于此。<br>**`sf_content_pure_mid`** · `0.8` · 中间帧主色占比须低于此。<br>**`sf_content_template_min`** · `0.9` · 三帧模板相似度最小值须低于此才上报。 |
|
|
162
|
+
| `stable_video` | 在**像在看视频**的那段里,**连续几帧对不上**(卡顿、花帧、黑场闪),或**相邻低相似帧成对**;也可能从**高纯色帧**切入下一帧异常。 | 段被 **`is_video_scene`** 标为类视频后,收集低模板相似帧并成对筛选(`analyze_video_scene_images`);另可由配置 **`operation_type`=`normal_swipe` 且 `scene_type`=`PLAY_VIDEO`** 强制走视频分支(非数值阈值)。 | **`video_high_similarity`** · `0.99` · 统计「高相似」帧的阈值。<br>**`video_scene_similarity_ratio_max`** · `0.3` · 高相似帧占比低于此则直接判为视频场景。<br>**`video_avg_fps_min`** · `20`、**`video_avg_fps_max`** · `60` · 平均运动帧率窗口。<br>**`video_sim_ratio_stages`** · `[[10,0.5],…,[100,0.1]]` · 按帧数分段的相似度比例表(仅 JSON)。<br>**`video_low_similarity`** · `0.5` · 低相似帧判定。<br>**`video_pair_near_ms`** · `200` · 两低相似帧间隔小于此(ms)易上报。<br>**`video_neighbor_pure_ratio`** · `0.7` · 邻帧高纯色时的上报条件。<br>**`video_pair_far_ms`** · `500` · 与前帧组合的时间上限(ms)。 |
|
|
163
|
+
| `motional_swipe_pure` | **滑动列表/页面**时中间**夹高纯色帧**,且**相似度陡变**;后续帧同色占比**剧烈跳变**。 | 需 **`operation_type`/`action_type`** 命中滑动动效;两次**陡变**间隔、中间纯色与后续**色占比跳变**(`motional_analyzer.cpp`)。 | **`motional_sharp_sim_delta`** · `0.5` · 相邻帧模板相似度差超过此记为陡变。<br>**`motional_sharp_max_span_ms`** · `200` · 两次陡变最大间隔(ms)。<br>**`motional_mid_pure_min`** · `0.2` · 中间帧纯色占比下限。<br>**`motional_color_jump_min`** · `0.1` · 后续帧同色占比相邻差最大值下限。<br>**`motional_sim_high_keep`** · `0.95` · 高于此相似度则重置「上一帧」参考。<br>**`motional_next_sim_threshold`** · `0.98` · 向前扫描时低于此相似度才采样纯色比例。 |
|
|
164
|
+
| `special_follow_hand_pure` | **跟手滑动**时**整图或大片突然高纯色**,常伴**左半屏仍稳定**。 | 纯色占比**升→降**包络;峰值帧**左半屏**主色约束;时间与阶跃幅度(`build_pure_flash`)。 | **`special_pure_spike`** · `0.3` · 相邻帧纯色占比上升/下降超过此触发峰谷检测。<br>**`special_pure_step_min`** · `0.2` · 峰值到前后相邻步长的最小变化(`build_pure_flash` 内)。<br>**`special_left_pure_min`** · `0.5` · 峰值帧左半屏主色占比下限。<br>**`special_pure_span_max_ms`** · `300` · 首末帧时间跨度上限(ms)。<br>**`special_template_break`** · `0.5` · 模板相似度低于此会打断峰跟踪。 |
|
|
165
|
+
| `special_follow_hand_low_similarity` | **多数帧连贯**,**中间一两帧**与前后明显不一致(孤立坏帧)。 | 当前与前一帧相似度双低,且**两侧窗口**内相似度均高(`special_analyzer.cpp`)。 | **`special_isolated_low_sim`** · `0.6` · 当前帧与前一帧模板相似度须**均不高于**此(代码中为 `>` 跳过)。<br>**`special_surround_sim_min`** · `0.9` · 左右各 **`special_surround_window`** 帧内相似度最小值须 ≥ 此值。<br>**`special_surround_window`** · `3` · 单侧参与统计的帧数。 |
|
|
166
|
+
|
|
167
|
+
实际运行中是否出现某一类,仍取决于场景切分、**`--config`** 与输入数据;调参后判定结果可能变化。
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## 4. 各异常类型检测流程图
|
|
172
|
+
|
|
173
|
+
流程图源文件在 **`./docs/flowcharts/*.mmd`**(Mermaid);下方插图路径均为**相对仓库根目录 `README.md`** 的 `./docs/flowcharts/*.png`(与 `src/` 同级下的 `docs/` 目录)。若修改 `.mmd`,可在 `docs/flowcharts` 目录执行:
|
|
174
|
+
|
|
175
|
+
`npx @mermaid-js/mermaid-cli -i <name>.mmd -o <name>.png -b white -w 1800 -H 1400`
|
|
176
|
+
|
|
177
|
+
对应实现:`src/flash/image_flash_analyzer.cpp`、`video_scene_parser.cpp`、`stable_analyzer.cpp`、`motional_analyzer.cpp`、`special_analyzer.cpp`。
|
|
178
|
+
|
|
179
|
+
### 4.1 总览:从输入到 `findings`
|
|
180
|
+
|
|
181
|
+

|
|
182
|
+
|
|
183
|
+
### 4.2 `STABLE` 段:视频类分支 vs 纯稳定分支
|
|
184
|
+
|
|
185
|
+

|
|
186
|
+
|
|
187
|
+
### 4.3 纯稳定三帧细查:`stable_scene_change` / `stable_white_trans` / `stable_content`
|
|
188
|
+
|
|
189
|
+

|
|
190
|
+
|
|
191
|
+
### 4.4 `stable_video`:低相似帧收集与成对上报
|
|
192
|
+
|
|
193
|
+

|
|
194
|
+
|
|
195
|
+
### 4.5 `motional_swipe_pure`(动效段 + 滑动配置)
|
|
196
|
+
|
|
197
|
+

|
|
198
|
+
|
|
199
|
+
### 4.6 `special_follow_hand_pure` 与 `special_follow_hand_low_similarity`
|
|
200
|
+
|
|
201
|
+

|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=69", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "image-flash-detector"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Screen flash detection CLI for ordered screenshots or video frames; bundles image-flash-detector.exe on Windows."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
authors = [{ name = "internal" }]
|
|
12
|
+
classifiers = [
|
|
13
|
+
"Programming Language :: Python :: 3",
|
|
14
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
15
|
+
"Environment :: Console",
|
|
16
|
+
"Operating System :: Microsoft :: Windows",
|
|
17
|
+
"Topic :: Multimedia :: Video",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
[project.scripts]
|
|
21
|
+
image-flash-detector = "flash_detector_cpu._launch:main"
|
|
22
|
+
|
|
23
|
+
[tool.setuptools.packages.find]
|
|
24
|
+
where = ["src"]
|
|
25
|
+
|
|
26
|
+
[tool.setuptools.package-data]
|
|
27
|
+
flash_detector_cpu = ["bin/image-flash-detector.exe"]
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Run the bundled native executable with the same argv (Windows)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import sys
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def main() -> None:
|
|
11
|
+
if sys.platform != "win32":
|
|
12
|
+
print("launcher: bundled binary is Windows-only (image-flash-detector.exe).", file=sys.stderr)
|
|
13
|
+
sys.exit(2)
|
|
14
|
+
|
|
15
|
+
here = Path(__file__).resolve().parent
|
|
16
|
+
exe = here / "bin" / "image-flash-detector.exe"
|
|
17
|
+
if not exe.is_file():
|
|
18
|
+
print(f"launcher: missing bundled executable: {exe}", file=sys.stderr)
|
|
19
|
+
print("Install from a wheel built with publish.bat, or rebuild the C++ target.", file=sys.stderr)
|
|
20
|
+
sys.exit(2)
|
|
21
|
+
|
|
22
|
+
argv = [str(exe)] + sys.argv[1:]
|
|
23
|
+
try:
|
|
24
|
+
os.execv(str(exe), argv)
|
|
25
|
+
except OSError as e:
|
|
26
|
+
print(f"launcher: failed to start {exe}: {e}", file=sys.stderr)
|
|
27
|
+
sys.exit(1)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
if __name__ == "__main__":
|
|
31
|
+
main()
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: image-flash-detector
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Screen flash detection CLI for ordered screenshots or video frames; bundles image-flash-detector.exe on Windows.
|
|
5
|
+
Author: internal
|
|
6
|
+
Classifier: Programming Language :: Python :: 3
|
|
7
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
8
|
+
Classifier: Environment :: Console
|
|
9
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
10
|
+
Classifier: Topic :: Multimedia :: Video
|
|
11
|
+
Requires-Python: >=3.10
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
# flicker-detector-cpu-version
|
|
15
|
+
|
|
16
|
+
本仓库提供原生 **image-flash-detector** 命令行工具(C++/OpenCV),面向**有序截图或视频帧**的闪屏与异常画面检测,输出 JSON 结果。
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 1. 功能作用
|
|
21
|
+
|
|
22
|
+
- **做什么**:对**有序图像序列**或**视频逐帧**做闪屏/异常画面检测,输出结构化 **JSON**,便于自动化与外部工具集成。
|
|
23
|
+
- **典型输入**:目录下的连续截图(文件名含时间戳更佳)、视频文件、两张相邻图快速验证、或文本列表中的图片路径。
|
|
24
|
+
- **检测思路概要**:
|
|
25
|
+
- 计算相邻帧**模板相似度**;
|
|
26
|
+
- 用滑窗与统计将时间轴切分为 **稳定 / 动效 / 特殊** 场景;
|
|
27
|
+
- 在各场景下分别执行稳定区(含纯色块/视频低相似分支)、滑动动效、跟手特殊等分析;
|
|
28
|
+
- **合并**时间段并过滤花屏时刻等,得到最终的 `findings` 列表。
|
|
29
|
+
- **平台**:当前以 **Windows x64** 下编译得到的 **`image-flash-detector.exe`** 为主;也可从源码构建 wheel(内嵌该 exe),通过 PyPI 包名 **`image-flash-detector`** 分发(见 `publish.bat`)。
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 2. 使用方法
|
|
34
|
+
|
|
35
|
+
### 2.1 编译(Windows + vcpkg)
|
|
36
|
+
|
|
37
|
+
```bat
|
|
38
|
+
build.bat
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
或手动(需已安装 CMake、VS、vcpkg):
|
|
42
|
+
|
|
43
|
+
```powershell
|
|
44
|
+
cd <仓库根目录>
|
|
45
|
+
$env:VCPKG_ROOT = "<你的 vcpkg 路径>"
|
|
46
|
+
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_ROOT\scripts\buildsystems\vcpkg.cmake" -DVCPKG_TARGET_TRIPLET=x64-windows-static-md
|
|
47
|
+
cmake --build build --config Release
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
生成可执行文件:**`build\Release\image-flash-detector.exe`**(具体路径随生成器可能略有不同)。
|
|
51
|
+
|
|
52
|
+
如需更多视频封装格式,可在 `vcpkg.json` 中为 `opencv4` 增加 **`ffmpeg`** feature(编译更久、体积更大)。
|
|
53
|
+
|
|
54
|
+
### 2.2 命令行调用
|
|
55
|
+
|
|
56
|
+
```text
|
|
57
|
+
image-flash-detector.exe --type <dir|video|image|list> --input <路径> [--input <路径>...] --output <输出.json>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**必选参数**
|
|
61
|
+
|
|
62
|
+
| 参数 | 说明 |
|
|
63
|
+
|------|------|
|
|
64
|
+
| `--type` | 输入形态,见下表。 |
|
|
65
|
+
| `--input` | 输入路径;`image` 模式需写**两次** `--input`(前一帧、后一帧)。 |
|
|
66
|
+
| `--output` | 结果 JSON 文件路径。 |
|
|
67
|
+
|
|
68
|
+
**`--type` 与 `--input` 含义**
|
|
69
|
+
|
|
70
|
+
| `--type` | `--input` 含义 | 说明 |
|
|
71
|
+
|----------|----------------|------|
|
|
72
|
+
| `dir` | 单一路径:图片目录 | **不递归**子目录;仅常见扩展名(如 png/jpg/webp 等)。图片按**无扩展名的 stem** 做「下划线分段自然序」:用 `_` 切成多段,**段内全是数字则按数值比**(故 `0_…` 在 `1_…` 前),**否则按字典序**(故 `…_A` 在 `…_B` 前)。stem 相同时再按完整文件名字典序。 |
|
|
73
|
+
| `video` | 单一路径:视频文件 | 逐帧解码;默认按容器 FPS 推算每帧时间戳;帧会落到系统临时目录下的 PNG。 |
|
|
74
|
+
| `image` | 两个路径:`--input A --input B` | 仅两帧,用于快速验证管线。 |
|
|
75
|
+
| `list` | 单一路径:文本文件 | 每行一张图片路径,`#` 开头行为注释;顺序即时间序。 |
|
|
76
|
+
|
|
77
|
+
**可选参数**
|
|
78
|
+
|
|
79
|
+
| 参数 | 默认值 | 说明 |
|
|
80
|
+
|------|--------|------|
|
|
81
|
+
| `--fps` | `0` | 视频:覆盖 FPS;为 `0` 时用 OpenCV 从容器读取,失败时可手动指定。 |
|
|
82
|
+
| `--frame-interval-ms` | `0` | 为 `0` 时,`dir`/`list` 的时间戳来自文件名数字;**非 0** 时用 `帧序号 × 该值` 作为毫秒时间轴。 |
|
|
83
|
+
| `--config` | 无 | JSON 配置文件:业务字段 + **门限调参**(与 CLI 门限同名 snake_case 键),见下表。 |
|
|
84
|
+
|
|
85
|
+
**检测门限(可选)**
|
|
86
|
+
|
|
87
|
+
- 命令行:`image-flash-detector.exe --help` 查看 **`Thresholds (optional)`** 分组(如 `--stable-ratio`、`--video-low-similarity`、`--motional-sharp-delta` 等)。未指定时保持内置默认,与改参前行为一致。
|
|
88
|
+
- **优先级**:先读 `--config` 中的数值,再应用命令行中显式传入的门限(CLI 覆盖 JSON)。
|
|
89
|
+
- **仅 JSON**:稳定段细查的 `sf_*` 字段(如 `sf_scene_edge_sim`、`sf_rect_templ_min`)、以及 `video_sim_ratio_stages`(数组,元素为 `[帧数阈值, 相似度比例上限]`)只能在配置 JSON 里写,不设独立 CLI。键名与 [flash_params.hpp](src/flash/flash_params.hpp) 中成员一致。
|
|
90
|
+
|
|
91
|
+
**`--config` JSON 常用字段(可选)**
|
|
92
|
+
|
|
93
|
+
| 字段 | 类型 | 说明 |
|
|
94
|
+
|------|------|------|
|
|
95
|
+
| `step_name` | 字符串 | 含特定子串时会跳过整段场景解析(如部分拍照相关步骤)。 |
|
|
96
|
+
| `operation_type` | 字符串 | 如 `normal_swipe`:在动效段启用滑动闪屏分析。 |
|
|
97
|
+
| `swipe_type` | 字符串 | 如 `swipe_photo_scroll_bar`:整段按特殊场景处理。 |
|
|
98
|
+
| `action_type` | 字符串 | 如 `side_swipe`:与 `operation_type` 组合影响动效分析器挂载。 |
|
|
99
|
+
| `scene_type` | 字符串 | 如 `PLAY_VIDEO`:与 `normal_swipe` 等组合影响是否走「视频黑花闪」分支。 |
|
|
100
|
+
| `is_lock_special` | 布尔 | 解锁专项:按相似度切分后再解析等。 |
|
|
101
|
+
| `video_start_timestamp` | 整数 | 相对时间原点(毫秒);默认多为首帧时间。 |
|
|
102
|
+
| `blurred_image_time_list` | 整数数组 | 采集卡花屏时刻;落在此区间内的 finding 会被过滤。 |
|
|
103
|
+
|
|
104
|
+
查看全部开关:
|
|
105
|
+
|
|
106
|
+
```bat
|
|
107
|
+
image-flash-detector.exe --help
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 2.3 打包与发布(PyPI)
|
|
111
|
+
|
|
112
|
+
在仓库根目录执行 **`publish.bat`**(需已安装 [uv](https://docs.astral.sh/uv/)):会先编译原生程序、将 **`image-flash-detector.exe`** 拷入包内、再执行 **`uv build`** 生成 **`dist\`** 下的 wheel 与 sdist。
|
|
113
|
+
|
|
114
|
+
上传到 PyPI 前请在环境中设置 **`PYPI_TOKEN`**(API token);脚本在校验通过后会执行 **`uv publish --token %PYPI_TOKEN%`**。本地仅安装 wheel 时可用例如 **`uv pip install dist\*.whl`**(文件名随版本变化, setuptools 会将包名规范为下划线形式,如 `image_flash_detector-*.whl`)。
|
|
115
|
+
|
|
116
|
+
安装后可在控制台运行 **`image-flash-detector`**(与 `image-flash-detector.exe` 等价,由 Python 入口转发到捆绑的 exe)。
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## 3. 结果说明
|
|
121
|
+
|
|
122
|
+
输出为 **JSON**,根对象包含 **`version`**、**`input_type`**、**`findings`**。未检出时 **`findings` 为空数组 `[]`**(不代表画面绝对无问题,与阈值、场景划分、配置有关)。
|
|
123
|
+
|
|
124
|
+
### 3.1 根级字段
|
|
125
|
+
|
|
126
|
+
| 字段 | 类型 | 含义 |
|
|
127
|
+
|------|------|------|
|
|
128
|
+
| `version` | 整数 | 结果格式版本,当前为 `1`。 |
|
|
129
|
+
| `input_type` | 字符串 | 与本次 `--type` 一致:`dir` / `video` / `image` / `list`。 |
|
|
130
|
+
| `findings` | 数组 | 每条表示一段检出的**闪屏/异常时间区间**及元数据。 |
|
|
131
|
+
|
|
132
|
+
### 3.2 `findings[]` 每条记录:字段说明与 `scene` / `flash_type`
|
|
133
|
+
|
|
134
|
+
#### 字段列表
|
|
135
|
+
|
|
136
|
+
| 字段 | 类型 | 含义 |
|
|
137
|
+
|------|------|------|
|
|
138
|
+
| `flash_type` | 字符串 | **检出问题类型**(算法分支),取值与含义见本节 **「`flash_type` 常见取值」**。 |
|
|
139
|
+
| `scene` | 字符串 | 该 finding 所在时间段的场景切分类型,取值见本节 **「`scene` 取值」**。 |
|
|
140
|
+
| `start_time_ms` | 整数 | 区间起点**绝对时间戳**(毫秒)。 |
|
|
141
|
+
| `end_time_ms` | 整数 | 区间终点**绝对时间戳**(毫秒)。 |
|
|
142
|
+
| `during_time_ms` | 整数 | 持续时间,`end_time_ms - start_time_ms`。 |
|
|
143
|
+
| `video_start_time_ms` | 整数 | 相对**序列/视频时间原点**的起点:`start_time_ms - video_start_timestamp`。 |
|
|
144
|
+
| `video_end_time_ms` | 整数 | 相对原点的终点:`end_time_ms - video_start_timestamp`。 |
|
|
145
|
+
| `start_frame` | 整数 | 起点在输入序列中的**帧序号**(从 0 起,与加载顺序一致)。 |
|
|
146
|
+
| `end_frame` | 整数 | 终点帧序号。 |
|
|
147
|
+
| `path_start` | 字符串 | 起点帧对应的文件路径或展示用标签(视频临时帧可能为临时 PNG 路径或 `video:frame=N` 形式)。 |
|
|
148
|
+
| `path_end` | 字符串 | 终点帧对应路径或标签,含义同 `path_start`。 |
|
|
149
|
+
|
|
150
|
+
**时间戳与帧号**:目录/列表模式优先用**文件名 stem 前缀数字**作为毫秒时间;若使用 `--frame-interval-ms` 则用序号乘以间隔。视频模式按 FPS 将帧序号映射为毫秒。
|
|
151
|
+
|
|
152
|
+
#### `scene` 取值
|
|
153
|
+
|
|
154
|
+
| `scene` | 含义 |
|
|
155
|
+
|---------|------|
|
|
156
|
+
| `STABLE` | 算法将该区段判为**相对稳定**的界面停留段。 |
|
|
157
|
+
| `ANIMATOR` | 判为**动效/过渡**段(如列表滑动动画区域)。 |
|
|
158
|
+
| `SPECIAL` | 判为**特殊交互**段(如跟手滑动、相册滚动条等配置触发)。 |
|
|
159
|
+
|
|
160
|
+
#### `flash_type` 常见取值(场景向 + 算法向 + 阈值)
|
|
161
|
+
|
|
162
|
+
**稳定场景**指时间轴上被切分为 **`scene` = `STABLE`** 的一段:界面**整体相对静止**,多数相邻帧彼此很像(观感上页面停住,没有明显整列表滑动或全屏跟手拖拽),与动效段、特殊交互段区分;**上表**已列出三类 `scene` 的简要含义。
|
|
163
|
+
|
|
164
|
+
`stable_scene_change`、`stable_white_trans`、`stable_content` 在上述**稳定段**内、基于相邻帧差分区域做三帧细查;若整段被识别为**类视频播放**(如配置 `normal_swipe` + `PLAY_VIDEO`,或按帧率与相似度统计命中视频模式),则走 **`stable_video`** 分支:在序列上寻找**低模板相似度**帧并配对上报,而**不再**走上述差分矩形 + 三帧稳定细查路径(实现见 `src/flash/stable_analyzer.cpp` 中 `is_video_scene` / `analyze_video_scene_images`)。
|
|
165
|
+
|
|
166
|
+
`motional_swipe_pure` 仅在 **`scene` = `ANIMATOR`** 且配置为滑动动效时触发;`special_*` 在 **`scene` = `SPECIAL`** 的跟手等特殊段触发。
|
|
167
|
+
|
|
168
|
+
下列阈值均可通过 **`--config` JSON**(键名为 **snake_case**,与 [`flash_params.hpp`](src/flash/flash_params.hpp) 一致)或 **`--help` → Thresholds (optional)** 中部分 CLI 选项调整;未列出者多为仅 JSON 可调(如 `sf_*`)。**CLI 选项名**为同一键的 **kebab-case**(如 `stable_ratio` ↔ `--stable-ratio`)。
|
|
169
|
+
|
|
170
|
+
| `flash_type` | 场景角度说明(用户可见现象) | 算法角度说明(判定摘要) | 主要阈值参数(键名 · 默认 · 作用) |
|
|
171
|
+
|--------------|------------------------------|--------------------------|-------------------------------------|
|
|
172
|
+
| `stable_scene_change` | 整体仍像「停住」,但**某一局部**在极短时间内**内容跳变**:像闪了一小块错误图层、弹层错位,或整屏短暂和前后对不上。<br>有时表现为:前后两帧整体还能对齐,**中间一帧在变化区域里很突兀**。 | 在相邻帧差分得到的**变化矩形**上,取前/中/后三帧的局部与全局模板相似度、**相位相关**等;满足「中间帧在变化区内相似度偏低,但**首尾全图仍较像**」等组合条件,且异常持续时间落在阈值内(`check_scene_change`)。 | **`stable_ratio`** · `0.95` · 判定「稳定帧」的模板相似度下限。<br>**`stable_max_rect_area_ratio`** · `0.01` · 稳定帧允许的差分矩形最大面积占比。<br>**`rect_min_width_ratio`** / **`rect_min_height_ratio`** / **`rect_min_area_ratio`** · `0.1` / `0.05` / `0.01` · 过滤过小的差分轮廓。<br>**`sf_rect_templ_min`** · `0.9` · 候选「非闪光」矩形模板相似度下限(跳过)。<br>**`sf_rect_diff_max`** · `0.9` · 与上配合的矩形差分比上限。<br>**`sf_scene_edge_sim`** · `0.9` · 首尾全图相似度高于此且中间区低于 **`sf_scene_mid_sim`**(`0.8`)时快速判场景切换。<br>**`sf_pure_mid_high`** · `0.8`、**`sf_min_rect_ratio`** · `0.05` · 中间纯色过高或变化区过小时排除。<br>**`sf_rect_pure_high`** · `0.9`、**`sf_phase_corr_max`** · `0.5`、**`sf_prev_global_pure_high`** · `0.8` · 排除高纯色/高相关假阳性。<br>**`sf_template_mid_low`** · `0.5`、**`sf_pure_drop_max`** · `0.4` · 中间帧模板与主色跌落约束。<br>**`sf_rect_pure_hi_alt`** · `0.85`、**`sf_flash_ms_short`** · `100`、**`sf_flash_ms_long`** · `200` · 持续时间窗(ms)。<br>**`sf_max_lookback_frames`** · `10` · 向前追溯帧数上限。<br>**`sf_error_iou`** · `0.5` · 历史误差矩形与当前矩形 IOU 关联门槛。 |
|
|
173
|
+
| `stable_white_trans` | 稳定段里出现**偏亮/偏白的单色或近单色过渡**:像**闪白、蒙层突然变亮、灰阶被「洗」成一片**;通常**不是**长时间均匀渐隐(会尝试排除渐隐)。 | 在变化矩形内统计**主色占比与主色灰阶**沿三帧的变化;结合矩形模板相似度、三帧相似度方差等过滤正常过渡(`check_white_trans`)。 | 除上表 **`stable_*` / `rect_*` / `sf_rect_templ_min` / `sf_rect_diff_max` / `sf_max_lookback_frames`** 等公共前置外:<br>**`sf_white_mrt`** · `0.9` · 矩形模板相似度上限,高于则视为正常。<br>**`sf_white_mts`** · `0.95`、**`sf_white_std_ts`** · `0.01` · 三帧整体相似度与方差联合过滤「无波动」序列。<br>**`sf_white_pure_mid`** · `0.9`、**`sf_white_min_rd`** · `0.4` · 中间帧主色与相邻帧差分幅度。<br>**`sf_white_pure_max_group`** · `0.8` · 进入强白过渡分支的主色占比条件。<br>**`sf_white_pd_same_dir`** · `40`、**`sf_white_pd_opposite`** · `20` · 主色灰阶变化幅度(同向/反向)。<br>**`sf_white_mx01_max`** · `0.85`、**`sf_white_pure_pair_max`** · `0.85` · 首尾主色与中间配对约束。 |
|
|
174
|
+
| `stable_content` | 前后在变化区域**几乎像「空/纯色底」**,**中间一帧却像「有内容」或更花**:观感接近**中间多出一帧杂讯或错误内容**,前后又「回到」简单背景。 | 三帧在矩形内**主色占比**与**模板相似度**联合判定(`check_content_flash`)。 | 公共前置同 **`stable_scene_change`**(`stable_ratio`、`sf_rect_templ_min`、`sf_rect_diff_max` 等)。<br>**`sf_content_pure_end`** · `0.9` · 首尾帧矩形内主色占比须高于此。<br>**`sf_content_pure_mid`** · `0.8` · 中间帧主色占比须低于此。<br>**`sf_content_template_min`** · `0.9` · 三帧模板相似度最小值须低于此才上报。 |
|
|
175
|
+
| `stable_video` | 在**像在看视频**的那段里,**连续几帧对不上**(卡顿、花帧、黑场闪),或**相邻低相似帧成对**;也可能从**高纯色帧**切入下一帧异常。 | 段被 **`is_video_scene`** 标为类视频后,收集低模板相似帧并成对筛选(`analyze_video_scene_images`);另可由配置 **`operation_type`=`normal_swipe` 且 `scene_type`=`PLAY_VIDEO`** 强制走视频分支(非数值阈值)。 | **`video_high_similarity`** · `0.99` · 统计「高相似」帧的阈值。<br>**`video_scene_similarity_ratio_max`** · `0.3` · 高相似帧占比低于此则直接判为视频场景。<br>**`video_avg_fps_min`** · `20`、**`video_avg_fps_max`** · `60` · 平均运动帧率窗口。<br>**`video_sim_ratio_stages`** · `[[10,0.5],…,[100,0.1]]` · 按帧数分段的相似度比例表(仅 JSON)。<br>**`video_low_similarity`** · `0.5` · 低相似帧判定。<br>**`video_pair_near_ms`** · `200` · 两低相似帧间隔小于此(ms)易上报。<br>**`video_neighbor_pure_ratio`** · `0.7` · 邻帧高纯色时的上报条件。<br>**`video_pair_far_ms`** · `500` · 与前帧组合的时间上限(ms)。 |
|
|
176
|
+
| `motional_swipe_pure` | **滑动列表/页面**时中间**夹高纯色帧**,且**相似度陡变**;后续帧同色占比**剧烈跳变**。 | 需 **`operation_type`/`action_type`** 命中滑动动效;两次**陡变**间隔、中间纯色与后续**色占比跳变**(`motional_analyzer.cpp`)。 | **`motional_sharp_sim_delta`** · `0.5` · 相邻帧模板相似度差超过此记为陡变。<br>**`motional_sharp_max_span_ms`** · `200` · 两次陡变最大间隔(ms)。<br>**`motional_mid_pure_min`** · `0.2` · 中间帧纯色占比下限。<br>**`motional_color_jump_min`** · `0.1` · 后续帧同色占比相邻差最大值下限。<br>**`motional_sim_high_keep`** · `0.95` · 高于此相似度则重置「上一帧」参考。<br>**`motional_next_sim_threshold`** · `0.98` · 向前扫描时低于此相似度才采样纯色比例。 |
|
|
177
|
+
| `special_follow_hand_pure` | **跟手滑动**时**整图或大片突然高纯色**,常伴**左半屏仍稳定**。 | 纯色占比**升→降**包络;峰值帧**左半屏**主色约束;时间与阶跃幅度(`build_pure_flash`)。 | **`special_pure_spike`** · `0.3` · 相邻帧纯色占比上升/下降超过此触发峰谷检测。<br>**`special_pure_step_min`** · `0.2` · 峰值到前后相邻步长的最小变化(`build_pure_flash` 内)。<br>**`special_left_pure_min`** · `0.5` · 峰值帧左半屏主色占比下限。<br>**`special_pure_span_max_ms`** · `300` · 首末帧时间跨度上限(ms)。<br>**`special_template_break`** · `0.5` · 模板相似度低于此会打断峰跟踪。 |
|
|
178
|
+
| `special_follow_hand_low_similarity` | **多数帧连贯**,**中间一两帧**与前后明显不一致(孤立坏帧)。 | 当前与前一帧相似度双低,且**两侧窗口**内相似度均高(`special_analyzer.cpp`)。 | **`special_isolated_low_sim`** · `0.6` · 当前帧与前一帧模板相似度须**均不高于**此(代码中为 `>` 跳过)。<br>**`special_surround_sim_min`** · `0.9` · 左右各 **`special_surround_window`** 帧内相似度最小值须 ≥ 此值。<br>**`special_surround_window`** · `3` · 单侧参与统计的帧数。 |
|
|
179
|
+
|
|
180
|
+
实际运行中是否出现某一类,仍取决于场景切分、**`--config`** 与输入数据;调参后判定结果可能变化。
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## 4. 各异常类型检测流程图
|
|
185
|
+
|
|
186
|
+
流程图源文件在 **`./docs/flowcharts/*.mmd`**(Mermaid);下方插图路径均为**相对仓库根目录 `README.md`** 的 `./docs/flowcharts/*.png`(与 `src/` 同级下的 `docs/` 目录)。若修改 `.mmd`,可在 `docs/flowcharts` 目录执行:
|
|
187
|
+
|
|
188
|
+
`npx @mermaid-js/mermaid-cli -i <name>.mmd -o <name>.png -b white -w 1800 -H 1400`
|
|
189
|
+
|
|
190
|
+
对应实现:`src/flash/image_flash_analyzer.cpp`、`video_scene_parser.cpp`、`stable_analyzer.cpp`、`motional_analyzer.cpp`、`special_analyzer.cpp`。
|
|
191
|
+
|
|
192
|
+
### 4.1 总览:从输入到 `findings`
|
|
193
|
+
|
|
194
|
+

|
|
195
|
+
|
|
196
|
+
### 4.2 `STABLE` 段:视频类分支 vs 纯稳定分支
|
|
197
|
+
|
|
198
|
+

|
|
199
|
+
|
|
200
|
+
### 4.3 纯稳定三帧细查:`stable_scene_change` / `stable_white_trans` / `stable_content`
|
|
201
|
+
|
|
202
|
+

|
|
203
|
+
|
|
204
|
+
### 4.4 `stable_video`:低相似帧收集与成对上报
|
|
205
|
+
|
|
206
|
+

|
|
207
|
+
|
|
208
|
+
### 4.5 `motional_swipe_pure`(动效段 + 滑动配置)
|
|
209
|
+
|
|
210
|
+

|
|
211
|
+
|
|
212
|
+
### 4.6 `special_follow_hand_pure` 与 `special_follow_hand_low_similarity`
|
|
213
|
+
|
|
214
|
+

|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
src/flash_detector_cpu/__init__.py
|
|
4
|
+
src/flash_detector_cpu/_launch.py
|
|
5
|
+
src/flash_detector_cpu/bin/image-flash-detector.exe
|
|
6
|
+
src/image_flash_detector.egg-info/PKG-INFO
|
|
7
|
+
src/image_flash_detector.egg-info/SOURCES.txt
|
|
8
|
+
src/image_flash_detector.egg-info/dependency_links.txt
|
|
9
|
+
src/image_flash_detector.egg-info/entry_points.txt
|
|
10
|
+
src/image_flash_detector.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|