savastakan's picture
Initial upload: code + 5 record checkpoints + fuse
f211247 verified
Raw
History Blame Contribute Delete
3.45 kB
#!/usr/bin/env python3
"""Quality gate — preprocessing.yaml thresholds uygulama.
Her kayda quality_gate_pass (bool) + quality_gate_reasons (list) ekler.
"""
import json, yaml
from pathlib import Path
from collections import Counter
ROOT = Path("/arf/scratch/stakan/hitit-proje")
SOURCES = ROOT / "datasets" / "sources"
def main():
cfg = yaml.safe_load(open(ROOT / "hitit_ocr" / "configs" / "preprocessing.yaml"))
gates = cfg['quality_gates']
blur_min = gates['blur_laplacian_min_variance']
exp_min = gates['exposure_mean_min']
exp_max = gates['exposure_mean_max']
cont_min = gates['contrast_std_min']
w_min = gates['resolution_min_w']
h_min = gates['resolution_min_h']
total = 0
passed = 0
reason_counts = Counter()
for d in sorted(SOURCES.iterdir()):
if not d.is_dir(): continue
for mf in ['manifest.jsonl', 'manifest_classification.jsonl', 'manifest_detection.jsonl']:
mp = d / mf
if not mp.exists(): continue
records = []
with open(mp) as f:
for line in f:
r = json.loads(line)
reasons = []
# Sadece integrity_ok=True olanlara uygula; diğerleri None bırak
if r.get('integrity_ok') is True:
blur = r.get('blur_score')
expo = r.get('exposure_mean')
cont = r.get('contrast_std')
w = r.get('width')
h = r.get('height')
if blur is not None and blur < blur_min:
reasons.append('blur')
if expo is not None and (expo < exp_min or expo > exp_max):
reasons.append('exposure')
if cont is not None and cont < cont_min:
reasons.append('contrast')
if w and w < w_min:
reasons.append('width')
if h and h < h_min:
reasons.append('height')
r['quality_gate_pass'] = len(reasons) == 0
r['quality_gate_reasons'] = reasons
if mf == 'manifest.jsonl':
total += 1
if r['quality_gate_pass']: passed += 1
for rr in reasons: reason_counts[rr] += 1
else:
r['quality_gate_pass'] = None
r['quality_gate_reasons'] = None
records.append(r)
with open(mp, 'w') as f:
for r in records:
f.write(json.dumps(r, ensure_ascii=False) + '\n')
print(f"Total: {total:,}, passed: {passed:,} (%{100*passed/max(1,total):.1f})")
print(f"Fail reasons:")
for rr, n in reason_counts.most_common():
print(f" {rr}: {n:,}")
with open(ROOT / "datasets" / "processed" / "quality_gate_report.json", 'w') as f:
json.dump({
"config_version": cfg['version'],
"thresholds": gates,
"total_scored": total,
"passed": passed,
"pass_rate": round(100*passed/max(1,total), 2),
"fail_reasons": dict(reason_counts),
}, f, indent=2, ensure_ascii=False)
if __name__ == '__main__':
main()