首次提交
This commit is contained in:
100
tools/analyze_ocr_result.py
Normal file
100
tools/analyze_ocr_result.py
Normal file
@@ -0,0 +1,100 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
分析一个 ocr_result.jsonl,判断"冗余文字过多"是真冗余还是误杀。
|
||||
复现过滤逻辑:看文字的垂直位置分布(distinct_bands)、每帧文字框数、有没有稳定字幕行。
|
||||
|
||||
用法: python temp/analyze_ocr_result.py "ocr_result (1).jsonl"
|
||||
"""
|
||||
import json
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
|
||||
PATH = sys.argv[1] if len(sys.argv) > 1 else "ocr_result.jsonl"
|
||||
|
||||
|
||||
def parse(path):
|
||||
"""解析 'pic_path: X' + json 交替格式,返回 [(frame, detections), ...]。"""
|
||||
pairs = []
|
||||
cur_frame = None
|
||||
with open(path, encoding="utf-8") as f:
|
||||
for line in f:
|
||||
line = line.rstrip("\n")
|
||||
if line.startswith("pic_path:"):
|
||||
cur_frame = line.split("pic_path:", 1)[1].strip()
|
||||
elif line.strip():
|
||||
try:
|
||||
data = json.loads(line)
|
||||
pairs.append((cur_frame, data.get("TextDetections", [])))
|
||||
except json.JSONDecodeError:
|
||||
pass
|
||||
return pairs
|
||||
|
||||
|
||||
def center_y(det):
|
||||
poly = det.get("Polygon", [])
|
||||
ys = [p.get("Y", 0) for p in poly]
|
||||
return sum(ys) / len(ys) if ys else 0
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
pairs = parse(PATH)
|
||||
except FileNotFoundError:
|
||||
print(f"找不到文件: {PATH}")
|
||||
return
|
||||
if not pairs:
|
||||
print("没解析到数据(格式不对?)")
|
||||
return
|
||||
|
||||
n_frames = len(pairs)
|
||||
boxes_per_frame = [len(d) for _, d in pairs]
|
||||
total_boxes = sum(boxes_per_frame)
|
||||
frames_with_text = sum(1 for b in boxes_per_frame if b)
|
||||
|
||||
# 所有文字框的中心 Y
|
||||
all_cy = []
|
||||
for _, dets in pairs:
|
||||
for det in dets:
|
||||
all_cy.append(center_y(det))
|
||||
|
||||
print(f"文件: {PATH}")
|
||||
print("=" * 60)
|
||||
print(f"帧/图数: {n_frames}")
|
||||
print(f"有文字的: {frames_with_text}")
|
||||
print(f"文字框总数: {total_boxes}")
|
||||
print(f"平均每帧框数: {total_boxes / n_frames:.1f}")
|
||||
print(f"最多一帧框数: {max(boxes_per_frame) if boxes_per_frame else 0}")
|
||||
|
||||
# distinct vertical bands(复现 merge.py 的冗余判定:中心Y间隔>80算一个新垂直簇)
|
||||
cys = sorted(all_cy)
|
||||
bands = 1 if cys else 0
|
||||
for i in range(1, len(cys)):
|
||||
if cys[i] - cys[i - 1] > 80:
|
||||
bands += 1
|
||||
print(f"不同垂直位置簇: {bands} (>=8 会被判冗余)")
|
||||
|
||||
# Y 分布直方图(每 100px 一档),看文字集中在哪还是散布全屏
|
||||
hist = defaultdict(int)
|
||||
for y in all_cy:
|
||||
hist[int(y // 100) * 100] += 1
|
||||
print("\n文字垂直分布(Y每100px一档,看文字集中度):")
|
||||
if hist:
|
||||
mx = max(hist.values())
|
||||
for y in sorted(hist):
|
||||
bar = "#" * int(hist[y] / mx * 40)
|
||||
print(f" y={y:>5}-{y+99:<5} {hist[y]:>6} {bar}")
|
||||
|
||||
# 判定
|
||||
print("\n" + "=" * 60)
|
||||
if bands >= 8:
|
||||
print(f"❌ 真冗余:文字散布在 {bands} 个不同垂直位置(满屏文字/弹幕/文档类)。")
|
||||
elif total_boxes / n_frames > 10:
|
||||
print(f"⚠️ 偏冗余:平均每帧 {total_boxes/n_frames:.0f} 个文字框,画面文字很多。")
|
||||
else:
|
||||
topy = max(hist, key=hist.get) if hist else 0
|
||||
print(f"✅ 可能误杀:文字主要集中在 y={topy}~{topy+99},像是有固定字幕行的。")
|
||||
print(" 若确实有正常字幕,可放宽 merge.py 的 distinct_bands 阈值。")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user