Files
ocr_data/tools/analyze_ocr_result.py
2026-09-28 16:09:31 +08:00

101 lines
3.4 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- 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()