screenshot-vision-algorithm 0.3.5__tar.gz → 0.3.8__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.
Files changed (48) hide show
  1. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/PKG-INFO +1 -1
  2. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/pyproject.toml +1 -1
  3. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/wechat/algorithms/speaker_band.py +10 -3
  4. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/wechat/ocr/avatar_guard.py +1 -1
  5. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/wechat/ocr/nickname_binding.py +26 -11
  6. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm.egg-info/PKG-INFO +1 -1
  7. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/README.md +0 -0
  8. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/setup.cfg +0 -0
  9. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/__init__.py +0 -0
  10. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/_config.py +0 -0
  11. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/__init__.py +0 -0
  12. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/wechat/__init__.py +0 -0
  13. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/wechat/algorithms/__init__.py +0 -0
  14. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/wechat/algorithms/avatar_column.py +0 -0
  15. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/wechat/algorithms/badge_detection.py +0 -0
  16. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/wechat/algorithms/card_bbox.py +0 -0
  17. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/wechat/algorithms/phash_utils.py +0 -0
  18. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/wechat/algorithms/template_matching.py +0 -0
  19. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/wechat/algorithms/title_ocr.py +0 -0
  20. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/wechat/merge/__init__.py +0 -0
  21. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/wechat/merge/multipage.py +0 -0
  22. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/wechat/ocr/__init__.py +0 -0
  23. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/wechat/ocr/badge_ocr.py +0 -0
  24. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/wechat/ocr/text_ocr_adapter.py +0 -0
  25. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/wechat/profiles/__init__.py +0 -0
  26. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/wechat/profiles/android.py +0 -0
  27. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/wechat/profiles/harmony.py +0 -0
  28. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/wechat/profiles/ios.py +0 -0
  29. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/wechat/templates/android/8.0.69/chat_back_chevron.png +0 -0
  30. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/wechat/templates/android/8.0.69/chat_input_emoji_smile.png +0 -0
  31. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/wechat/templates/android/8.0.69/chat_input_plus.png +0 -0
  32. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/wechat/templates/android/8.0.69/chat_input_voice.png +0 -0
  33. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/wechat/templates/android/8.0.69/chat_title_more_dots.png +0 -0
  34. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/wechat/templates/android/8.0.69/favorite_label.png +0 -0
  35. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/wechat/templates/android/8.0.69/new_messages_hint_suffix.png +0 -0
  36. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/wechat/templates/android/8.0.69/unread_divider_hint.png +0 -0
  37. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/wechat/templates/android/8.0.69/unread_divider_hint_v2_textonly.png +0 -0
  38. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/wechat/templates/android/8.0.69/wechat_note_header.png +0 -0
  39. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/xhs/__init__.py +0 -0
  40. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/android/zhihu/__init__.py +0 -0
  41. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/logging.py +0 -0
  42. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm/png_utils.py +0 -0
  43. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm.egg-info/SOURCES.txt +0 -0
  44. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm.egg-info/dependency_links.txt +0 -0
  45. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm.egg-info/requires.txt +0 -0
  46. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/src/screenshot_vision_algorithm.egg-info/top_level.txt +0 -0
  47. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/tests/test_card_bbox.py +0 -0
  48. {screenshot_vision_algorithm-0.3.5 → screenshot_vision_algorithm-0.3.8}/tests/test_package.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: screenshot_vision_algorithm
3
- Version: 0.3.5
3
+ Version: 0.3.8
4
4
  Summary: Multi-platform screenshot vision algorithms: WeChat (card bbox, speaker bands, avatar detection, OCR helpers), XHS & Zhihu (planned)
5
5
  License: MIT
6
6
  Requires-Python: >=3.10
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "screenshot_vision_algorithm"
7
- version = "0.3.5"
7
+ version = "0.3.8"
8
8
  description = "Multi-platform screenshot vision algorithms: WeChat (card bbox, speaker bands, avatar detection, OCR helpers), XHS & Zhihu (planned)"
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -26,7 +26,7 @@ from screenshot_vision_algorithm.android.wechat.algorithms.template_matching imp
26
26
  CHAT_BAND_FIRST_AVATAR_TOP_GAP_REJECT_BASELINE = 30
27
27
 
28
28
  #: 首个发言人筒上移量(一个头像高度,防止几何误差),见 PRD §5 补充2。
29
- CHAT_FIRST_BAND_TOP_EXTEND_BASELINE = 100
29
+ CHAT_FIRST_BAND_TOP_EXTEND_BASELINE = 20
30
30
 
31
31
  #: 底部输入区预留(与主列表 scanner 一脉,baseline)。
32
32
  CHAT_COMPOSER_RESERVE_BOTTOM_BASELINE = 160
@@ -173,7 +173,7 @@ def detect_chat_side_avatar_ytops(
173
173
  y1 = max(0, bounds.y_top)
174
174
  y2 = min(h, bounds.y_bottom_excl)
175
175
  try:
176
- from processor.left_avatar_column import (
176
+ from screenshot_vision_algorithm.android.wechat.algorithms.avatar_column import (
177
177
  detect_left_avatar_column_layout,
178
178
  left_avatar_ytops,
179
179
  )
@@ -254,7 +254,7 @@ def build_prd_speaker_vertical_bands(
254
254
  if not merged_starts or y - merged_starts[-1] >= min_sep:
255
255
  merged_starts.append(y)
256
256
 
257
- # 首个筒上界上移(PRD §5 补充2):上移 100px @1080,防几何误差与系统变化。
257
+ # 首个筒上界上移(PRD §5 补充2):上移 20px @1080,防几何误差与系统变化。
258
258
  first_band_extend = int(round(int(first_band_top_extend_baseline) * sw))
259
259
 
260
260
  bands: list[tuple[int, int]] = []
@@ -275,6 +275,13 @@ def build_prd_speaker_vertical_bands(
275
275
  elif first_band_start < orphan_top[1]:
276
276
  orphan_top = (orphan_top[0], first_band_start)
277
277
 
278
+ # 无 orphan 时,首个 band 上界对齐 y_ct,保证纵向连续全覆盖
279
+ # (extend 较小且头像紧贴 y_ct 时可能产生小间隙)
280
+ if orphan_top is None and bands:
281
+ first_y0, first_y1 = bands[0]
282
+ if first_y0 > y_ct:
283
+ bands[0] = (y_ct, first_y1)
284
+
278
285
  return PrdChatVerticalLayout(
279
286
  content_bounds=bounds,
280
287
  orphan_top_band=orphan_top,
@@ -19,7 +19,7 @@ except ImportError:
19
19
  cv2 = None # type: ignore[assignment]
20
20
 
21
21
  try:
22
- from processor.left_avatar_column import AvatarCentroid
22
+ from screenshot_vision_algorithm.android.wechat.algorithms.avatar_column import AvatarCentroid
23
23
  except ImportError:
24
24
  AvatarCentroid = None # type: ignore[misc, assignment]
25
25
 
@@ -351,6 +351,9 @@ _PURE_TIME_RE = re.compile(r"^\d{1,2}:\d{2}(:\d{2})?$")
351
351
  _WEEKDAY_TIME_RE = re.compile(
352
352
  r"^周[一二三四五六日天].*?(?:上午|下午|晚上|凌晨)?\s*\d{0,2}[::]?\d{0,2}"
353
353
  )
354
+ _YESTERDAY_TODAY_TIME_RE = re.compile(
355
+ r"^(?:昨天|今天)\s*\d{0,2}:?\d{0,2}$"
356
+ )
354
357
  _MOBILE_PHONE_SUFFIX_RE = re.compile(r"1\d{10}\s*$")
355
358
 
356
359
 
@@ -388,6 +391,8 @@ def _is_chat_timestamp_or_divider(text: str) -> bool:
388
391
  return True
389
392
  if _WEEKDAY_TIME_RE.match(t):
390
393
  return True
394
+ if _YESTERDAY_TODAY_TIME_RE.match(t):
395
+ return True
391
396
  return False
392
397
 
393
398
 
@@ -411,7 +416,7 @@ def _is_avatar_column_nickname_row(
411
416
  avatar_layout: Any = None,
412
417
  ) -> bool:
413
418
  try:
414
- from processor.left_avatar_column import nickname_bbox_in_avatar_column
419
+ from screenshot_vision_algorithm.android.wechat.algorithms.avatar_column import nickname_bbox_in_avatar_column
415
420
  except ImportError:
416
421
  nickname_bbox_in_avatar_column = None # type: ignore[assignment,misc]
417
422
  if avatar_layout is not None and nickname_bbox_in_avatar_column is not None:
@@ -446,7 +451,7 @@ def _avatar_anchor_for_block(
446
451
  if avatar_layout is None or getattr(avatar_layout, "empty", True):
447
452
  return None
448
453
  try:
449
- from processor.left_avatar_column import find_avatar_anchor_for_nickname_bbox
454
+ from screenshot_vision_algorithm.android.wechat.algorithms.avatar_column import find_avatar_anchor_for_nickname_bbox
450
455
  except ImportError:
451
456
  return None
452
457
  return find_avatar_anchor_for_nickname_bbox(
@@ -463,9 +468,9 @@ def _load_left_avatar_layout(
463
468
  if png_path is None:
464
469
  return None
465
470
  try:
466
- from processor.chat_bubble_geometry_prd import compute_chat_content_vertical_bounds
467
- from processor.left_avatar_column import detect_left_avatar_column_layout
468
- from processor.nickname_avatar_guard import load_png_bgr
471
+ from screenshot_vision_algorithm.android.wechat.algorithms.speaker_band import compute_chat_content_vertical_bounds
472
+ from screenshot_vision_algorithm.android.wechat.algorithms.avatar_column import detect_left_avatar_column_layout
473
+ from screenshot_vision_algorithm.android.wechat.ocr.avatar_guard import load_png_bgr
469
474
  except ImportError:
470
475
  return None
471
476
  arr = load_png_bgr(str(png_path))
@@ -595,7 +600,7 @@ def _nickname_passes_avatar_guard(
595
600
  if bgr_guard is None:
596
601
  return not config.require_avatar_guard_for_nickname
597
602
  try:
598
- from processor.nickname_avatar_guard import avatar_roi_pass
603
+ from screenshot_vision_algorithm.android.wechat.ocr.avatar_guard import avatar_roi_pass
599
604
  except ImportError:
600
605
  return not config.require_avatar_guard_for_nickname
601
606
 
@@ -687,13 +692,13 @@ def _load_prd_layout_optional(
687
692
  if png_path is None or not config.use_prd_chat_vertical_bands:
688
693
  return None
689
694
  try:
690
- from processor.chat_bubble_geometry_prd import (
695
+ from screenshot_vision_algorithm.android.wechat.algorithms.speaker_band import (
691
696
  build_prd_speaker_vertical_bands,
692
697
  compute_chat_content_vertical_bounds,
693
698
  detect_chat_side_avatar_ytops,
694
699
  merge_avatar_ytops_time_order,
695
700
  )
696
- from processor.nickname_avatar_guard import load_png_bgr
701
+ from screenshot_vision_algorithm.android.wechat.ocr.avatar_guard import load_png_bgr
697
702
  except ImportError:
698
703
  return None
699
704
  arr = load_png_bgr(str(png_path))
@@ -962,7 +967,17 @@ def _resume_thumb_bindings_and_orphans(
962
967
  _cy1, _cy2 = float(tbb[1]), float(tbb[3])
963
968
  for _bi, (_b0, _b1) in enumerate(_sb_list):
964
969
  if _cy2 > float(_b0) and _cy1 < float(_b1):
965
- band_idx = _bi # 相交 → 候选;持续覆盖 → 最后一个(下方)胜出
970
+ band_idx = _bi # 相交 → 候选;持续覆盖 → 最后一个(下方)胜出
971
+
972
+ # ── 如果卡片与 orphan_top_band 相交 → 直接记为找不到归属 ──
973
+ if layout_opt is not None:
974
+ ot = getattr(layout_opt, "orphan_top_band", None)
975
+ if ot is not None:
976
+ oy0, oy1 = float(ot[0]), float(ot[1])
977
+ _cy1, _cy2 = float(tbb[1]), float(tbb[3])
978
+ if _cy2 > oy0 and _cy1 < oy1:
979
+ orphan += 1
980
+ continue
966
981
 
967
982
  matched_nickname: Optional[str] = None
968
983
 
@@ -1177,7 +1192,7 @@ def first_attrib_verbatim_display_line_and_bbox(
1177
1192
  scale_w = float(original_width) / 1080.0
1178
1193
  if png_path is not None:
1179
1194
  try:
1180
- from processor.nickname_avatar_guard import load_png_bgr
1195
+ from screenshot_vision_algorithm.android.wechat.ocr.avatar_guard import load_png_bgr
1181
1196
 
1182
1197
  bgr_guard = load_png_bgr(str(png_path))
1183
1198
  except ImportError:
@@ -1748,7 +1763,7 @@ def extract_nicknames(
1748
1763
  bgr_guard = None
1749
1764
  if png_path is not None:
1750
1765
  try:
1751
- from processor.nickname_avatar_guard import load_png_bgr
1766
+ from screenshot_vision_algorithm.android.wechat.ocr.avatar_guard import load_png_bgr
1752
1767
 
1753
1768
  bgr_guard = load_png_bgr(str(png_path))
1754
1769
  except ImportError:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: screenshot_vision_algorithm
3
- Version: 0.3.5
3
+ Version: 0.3.8
4
4
  Summary: Multi-platform screenshot vision algorithms: WeChat (card bbox, speaker bands, avatar detection, OCR helpers), XHS & Zhihu (planned)
5
5
  License: MIT
6
6
  Requires-Python: >=3.10