pokemon_ocr_step2.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. # -*- coding: utf-8 -*-
  2. """pokemon OCR step2: 对 images_pokemon_out/crops 跑 PaddleOCR, 输出分行文本。
  3. 复用 grading_ocr_step2 逻辑, 路径改为 images_pokemon_out。"""
  4. import os, sys, json, csv, time
  5. sys.stdout.reconfigure(encoding="utf-8")
  6. OUT = "/home/martin/顾工交接/wzj/images_pokemon_out"
  7. RECORDS = os.path.join(OUT, "crop_records.json")
  8. print("[OCR] 初始化 PaddleOCR ...")
  9. from paddleocr import PaddleOCR
  10. _t_load0 = time.perf_counter()
  11. ocr = PaddleOCR(use_doc_orientation_classify=True, use_doc_unwarping=False,
  12. use_textline_orientation=True)
  13. t_load = time.perf_counter() - _t_load0
  14. print(f"[OCR] 加载完成 (耗时 {t_load:.2f}s)\n")
  15. with open(RECORDS, encoding="utf-8") as f:
  16. records = json.load(f)
  17. ocr_results = {}
  18. rows_csv = []
  19. t_ocr = 0.0 # OCR 推理累计
  20. n_ok = 0
  21. print(f"[OCR] 处理 {len(records)} 张裁剪图 ...\n")
  22. _t_all0 = time.perf_counter()
  23. for i, rec in enumerate(records):
  24. name = rec["file"]
  25. crop_path = rec["crop_path"]
  26. try:
  27. _t = time.perf_counter()
  28. result = ocr.predict(crop_path)
  29. t_ocr += time.perf_counter() - _t
  30. n_ok += 1
  31. except Exception as e:
  32. ocr_results[name] = {"lines": [], "error": str(e)}
  33. rows_csv.append([name, rec["true_label"], str(rec.get("box") or ""), rec.get("conf") or "", ""])
  34. if (i+1) % 100 == 0:
  35. print(f" [{i+1}/{len(records)}] (有错误)", flush=True)
  36. continue
  37. lines = []
  38. for res in result:
  39. if isinstance(res, dict):
  40. t = res.get("rec_texts")
  41. if t: lines.extend(list(t))
  42. elif hasattr(res, "rec_texts") and res.rec_texts:
  43. lines.extend(list(res.rec_texts))
  44. text_joined = " | ".join(lines) if lines else ""
  45. ocr_results[name] = {"lines": lines, "text": text_joined}
  46. rows_csv.append([name, rec["true_label"], str(rec.get("box") or ""), rec.get("conf") or "", text_joined])
  47. if (i+1) % 200 == 0:
  48. print(f" [{i+1}/{len(records)}] 完成", flush=True)
  49. with open(os.path.join(OUT, "ocr_result.json"), "w", encoding="utf-8") as f:
  50. json.dump(ocr_results, f, ensure_ascii=False, indent=2)
  51. with open(os.path.join(OUT, "ocr_summary.csv"), "w", encoding="utf-8-sig", newline="") as f:
  52. w = csv.writer(f)
  53. w.writerow(["filename", "true_label", "box_xyxy", "conf", "ocr_text_lines"])
  54. w.writerows(rows_csv)
  55. n_empty = sum(1 for v in ocr_results.values() if not v.get("lines"))
  56. print(f"\n[OCR] 完成. JSON + CSV 已保存. 共 {len(records)} 张, OCR空文本 {n_empty} 张")
  57. # ===== 计时报告 =====
  58. t_all = time.perf_counter() - _t_all0
  59. N = max(len(records), 1)
  60. print("\n" + "=" * 50)
  61. print("⏱ 计时报告 (pokemon_ocr_step2.py)")
  62. print("=" * 50)
  63. print(f" PaddleOCR 加载 : {t_load:7.2f}s")
  64. print(f" OCR 推理(累计) : {t_ocr:7.2f}s | 均 {t_ocr/N*1000:6.1f} ms/张")
  65. print(f" {'-'*46}")
  66. print(f" 处理总耗时({N}张) : {t_all:7.2f}s | 均 {t_all/N*1000:6.1f} ms/张 | 吞吐 {N/t_all:.2f} 张/s")
  67. print("=" * 50)
  68. # 写 timing.log
  69. import datetime
  70. with open(os.path.join(OUT, "timing.log"), "a", encoding="utf-8") as lf:
  71. lf.write(f"\n[{datetime.datetime.now():%Y-%m-%d %H:%M:%S}] === 步骤② pokemon_ocr_step2.py (PaddleOCR 评级标签识别) ===\n")
  72. lf.write(f" 样本数: {N} 张 (OCR空文本 {n_empty})\n")
  73. lf.write(f" PaddleOCR 加载 : {t_load:.2f}s\n")
  74. lf.write(f" OCR 推理累计 : {t_ocr:.2f}s (均 {t_ocr/N*1000:.1f} ms/张)\n")
  75. lf.write(f" 处理总耗时 : {t_all:.2f}s (均 {t_all/N*1000:.1f} ms/张, 吞吐 {N/t_all:.2f} 张/s)\n")
  76. print(f"✓ 计时已写入: {os.path.join(OUT, 'timing.log')}")