Skip to main content

WeChat screenshot computer-vision algorithms: card bbox, speaker bands, avatar detection, OCR helpers

Project description

wechat_screenshot_vision_algorithm

微信截图计算机视觉算法库 —— 简历卡片检测、发言人气泡分割、头像检测、OCR 辅助等。

安装

pip install wechat_screenshot_vision_algorithm

# 可选依赖
pip install wechat_screenshot_vision_algorithm[ocr]    # PaddleOCR >=3.0
pip install wechat_screenshot_vision_algorithm[png]    # Pillow PNG 压缩上传
pip install wechat_screenshot_vision_algorithm[merge]  # python-Levenshtein 多页文本合并

包结构

src/wechat_screenshot_vision_algorithm/
├── _config.py        # Platform/Profile 解析与参数查表
├── png_utils.py      # extras=[png]: PNG 长边压缩
├── algorithms/       # 默认依赖 (numpy + opencv)
│   ├── card_bbox.py          # 简历卡片 bbox 检测
│   ├── template_matching.py  # 模板匹配原语 (收藏标签/未读分割线/标题栏等)
│   ├── speaker_band.py       # 发言人气泡纵向分桶
│   ├── avatar_column.py      # 左侧头像列布局检测
│   ├── phash_utils.py        # dHash 感知哈希 (滚动到底检测 / 去重)
│   ├── badge_detection.py    # 未读红点 HSV 检测
│   └── title_ocr.py          # 群聊标题 OCR
├── ocr/              # extras=[ocr]: PaddleOCR ≥3.0
│   ├── text_ocr_adapter.py   # PaddleOCR 引擎封装 (UVDoc 已禁用)
│   ├── nickname_binding.py   # 昵称归属 (卡片/聊天气泡绑定)
│   ├── avatar_guard.py       # 昵称 vs 头像距离守门
│   └── badge_ocr.py          # 未读徽章数字 OCR
├── merge/            # extras=[merge]: python-Levenshtein
│   └── multipage.py          # N-gram + Levenshtein 多页拼接
├── profiles/         # 平台参数配置
│   ├── android_wechat.py     # 安卓微信 (头像左侧, 全部阈值)
│   ├── ios_wechat.py         # iOS 微信 (头像右侧, 占位)
│   └── harmony_wechat.py     # 鸿蒙微信 (占位)
└── templates/        # package_data (pip install 分发)
    └── wechat/{platform}/{version}/

核心概念

Platform / WeChatVersion / Profile

不同平台 (Android / iOS / 鸿蒙) 和微信版本的截图布局不同(头像列位置、颜色阈值、间距等),通过 Profile 统一参数化:

from wechat_screenshot_vision_algorithm import Platform, WeChatVersion, Profile

# 安卓微信 8.0.69
profile = Profile(platform=Platform.ANDROID, wechat_version=WeChatVersion.V8_0_69)

profile.AVATAR_SIDE         # "left" — Android 发言人头像在左侧
profile.CORE_THRESHOLD      # 0.80 — 模板匹配阈值
profile.VLINE_MIN_SEG_RATIO # 0.08 — 竖线候选列最低方差段占比
profile.templates_dir       # Path — 内嵌模板 PNG 目录

所有设计常量基于 1080px 屏幕宽度锚定;运行时按 device_screen_width / 1080 缩放。


模块详解

_config — 配置与 Profile 解析

名称 类型 说明
Platform Enum ANDROID, IOS, HARMONY 三平台枚举
WeChatVersion Enum V8_0_69 微信版本枚举
Profile Class 参数束:按 (platform, version) 查表返回阈值常量与模板路径
BASELINE_WIDTH int 设计基准宽度 1080px

Profile 实例的属性委托到对应平台模块(如 profiles/android_wechat.py),包含以下参数类:

卡片 bbox 检测参数: TOP_BAR_BOT_RATIO, BOT_BAR_TOP_RATIO, AVATAR_COLUMN_WIDTH_BASELINE, MIN_CARD_X_GAP_BASELINE, VLINE_MIN_SEG_RATIO, CARD_HSPAN_MIN_RATIO, HLINE_NEAR_VLINE_LIMIT_BASELINE, ZONE_MIN_HEIGHT, ZONE_MIN_SEG, LABEL_INTERSECT_MARGIN, GAP_MERGE_MAX_DIST

模板匹配参数: CORE_THRESHOLD, AUX_THRESHOLD

发言人气泡参数: CHAT_FIRST_BAND_TOP_EXTEND_BASELINE, CHAT_COMPOSER_RESERVE_BOTTOM_BASELINE, 头像 Hough 圆参数等

头像检测参数: LIST_HOUGH_MIN_DIST_BASELINE, LIST_HOUGH_MIN_R_BASELINE, NICKNAME_AVATAR_BIND_MAX_DY_BASELINE

卡片点击参数: FAVORITE_LABEL_TEMPLATE_W_BASELINE, FAVORITE_TO_CARD_TOP_OFFSET_BASELINE, REFERENCE_RESUME_CARD_TOP_GAP_BASELINE


algorithms.card_bbox — 简历卡片边界框检测

微信聊天列表截图中检测「收藏标签」并推导简历卡片精确 bbox。核心入口 _compute_exact_card_bboxes 基于三区方差 + 竖线分段判断卡片左右边界。

数据结构:

名称 字段 说明
FavoriteLabelHit x, y, w, h, score 收藏标签模板匹配命中 (y1, y2 属性)
ThumbnailCard index, top, bottom, left, right, click_x, click_y, click_side, favorite_hit 一张简历卡片的导出矩形(像素坐标)
BubbleBbox top, bottom, left, right 文本聊天气泡矩形 (卡片 zone 排除后的剩余 zone)
TrackedCard height, clicked 高度序列去重追踪状态

函数:

函数 签名 说明
_compute_exact_card_bboxes (ordered_hits, bgr_img, screen_w, screen_h) → list[ThumbnailCard] 核心算法:从收藏标签命中 + 截图推导卡片 bbox
derive_cards (...) → list[ThumbnailCard] 高层入口:整合模板匹配 + 竖线检测,输出卡片列表
drop_top_clamped_false_positive_cards (cards) → list[ThumbnailCard] 过滤顶部被截断的误检卡片
bbox_to_metadata_list (card) → list[int] 卡片 bbox 转为 [left, top, right, bottom]
card_bounding_tuple (card) → tuple 转为 (left, top, right, bottom) 元组
card_overlaps_processed (card, processed_bboxes) → bool 判断卡片是否与已处理卡片重叠
click_context_for_tap_thumbnail (card) → dict 生成 click_context (click_coords + click_side)
pick_first_unprocessed_card (cards, processed_bboxes) → ThumbnailCard|None 返回第一个不重叠的未处理卡片 (旧版,建议用 pick_next_unclicked_card)
pick_next_unclicked_card (cards, tracked_cards) → ThumbnailCard|None 基于高度序列匹配的卡片去重,返回下一个未点击卡片
y_interval_overlap_ratio (top_a, bottom_a, top_b, bottom_b) → float 两区间的 Y 轴重叠率

algorithms.template_matching — 模板匹配原语

所有模板匹配函数 + 布局常量,跨 collector 运行时和回归测试工具共享。

常量:

常量 说明
BASELINE_WIDTH 基准屏幕宽度 1080
CORE_THRESHOLD 收藏标签/新消息提示的硬阈值 0.80
TEMPLATES_DIR 模板 PNG 目录 (可通过 set_templates_dir 覆盖)
TEMPLATE_FILE 模板名到文件名的映射 dict

函数:

函数 说明
load_template(name) 加载模板 PNG 返回 BGR numpy 数组
set_templates_dir(path) 覆盖模板目录(iOS / 鸿蒙使用)
is_wechat_main_conversation_list_chrome(...) 检测是否为微信主会话列表页面
find_favorite_labels(...) 在截图中匹配收藏标签
find_new_messages_hints(...) 匹配「新消息」分割线
find_unread_dividers(...) 匹配未读消息分割线
find_wechat_note_header(...) 匹配微信笔记标题栏
find_chat_back_chevron(...) 匹配聊天返回箭头
find_chat_title_more_dots(...) 匹配聊天标题栏更多按钮
find_chat_input_voice(...) 匹配语音输入按钮
find_chat_input_emoji_smile(...) 匹配表情按钮
find_chat_input_plus(...) 匹配加号按钮
split_conversation_rows(...) 按头像分割会话列表行

algorithms.speaker_band — 发言人气泡纵向分桶

根据聊天截图中的发言人头像位置,划分发言人纵向区间(speaker bands)。

数据结构:

名称 说明
ChatVerticalBounds 聊天区域纵向边界 (top / bottom / title_bar_bottom / composer_top)
AvatarTimelineEntry 单条发言人头像时间线条目
PrdChatVerticalLayout PRD 规定的聊天纵向布局 (bounds + speaker_bands)

函数:

函数 说明
compute_chat_content_vertical_bounds(...) 计算聊天内容的纵向边界
detect_chat_side_avatar_ytops(...) 检测聊天侧发言人头像 Y 坐标
merge_avatar_ytops_time_order(...) 按时间顺序合并头像 Y 坐标
build_prd_speaker_vertical_bands(...) 构建 PRD 规定的发言人纵向分桶

algorithms.avatar_column — 左侧头像列布局检测

检测微信会话列表中左侧头像列的布局(数量、Y 坐标等)。

数据结构:

名称 说明
AvatarCentroid 单个头像质心 (x, y, radius)
LeftAvatarColumnLayout 左侧头像列布局 (centroids, median_x, gaps 等)

函数:

函数 说明
detect_left_avatar_column_layout(...) 用 Hough 圆检测左侧头像列
find_avatar_anchor_for_nickname_bbox(...) 为昵称 bbox 找到对应的发言人头像锚点
nickname_bbox_in_avatar_column(...) 判断昵称 bbox 是否在头像列区域内
left_avatar_ytops(layout) 提取所有头像的 Y 坐标列表

algorithms.phash_utils — 感知哈希与去重

dHash 感知哈希,用于滚动到底检测与会话去重。

数据结构:

名称 说明
PHashResult 哈希结果 (value, roi_kind, bbox)
ScrollDuplicationTracker 滚动去重追踪器 (observe → is_stuck)

函数:

函数 说明
compute_dhash(bgr, roi_kind) 计算截图的 dHash
hamming_distance(a, b) 两个哈希的汉明距离
is_duplicate(ph1, ph2, threshold) 判断两帧是否重复
crop_roi(bgr, roi_kind) 根据 roi_kind 裁剪 ROI
manual_labeling_phash_matches(a, b) 判定手动标注阶段是否匹配

algorithms.badge_detection — 未读红点检测

HSV 颜色空间检测微信会话列表中白底红字的未读徽章。

函数:

函数 说明
count_badges_white_on_red(bgr, min_area_px) 检测全图白底红字徽章数量
count_badges_per_row_roi(bgr, avatar_ytops, ...) 按行 ROI 统计徽章数

algorithms.title_ocr — 群聊标题 OCR

函数:

函数 说明
try_ocr_group_chat_title_from_png(png_path, scale_w) 从 PNG 截图 OCR 群聊标题文本

ocr.text_ocr_adapter — PaddleOCR 引擎封装

依赖: pip install wechat_screenshot_vision_algorithm[ocr]

PaddleOCR 3.x 引擎封装,已显式禁用 UVDoc 矫正(防止坐标变形)。跨 collector 和 housekeeping 后端共享。

数据结构:

名称 说明
OcrPageResult OCR 页面结果 (blocks, page_size, engine_info)
TextBlock 单个 OCR 文本块 (text, bbox_xyxy, confidence)

ocr.nickname_binding — 昵称归属

依赖: pip install wechat_screenshot_vision_algorithm[ocr]

将 OCR 识别出的文本块归因为「昵称」「正文」「丢弃」三类,并绑定到发言人或简历卡片。

数据结构:

名称 说明
NicknameOcrConfig 昵称 OCR 配置 (阈值、avatar_column_width 等)
NicknameExtraction 单条昵称提取结果
SpeakerBodySegment 发言人正文段落
ResumeThumbBinding 简历卡片绑定结果
ChatSpeakerAttribution 完整发言人归属结果

函数:

函数 说明
extract_nicknames(...) 主入口:从 OCR 页面结果提取昵称并归属
first_attrib_verbatim_display_line(...) 获取首次属性的原始显示行

ocr.avatar_guard — 头像距离守门

依赖: pip install wechat_screenshot_vision_algorithm[ocr]

验证 OCR 识别出的昵称文本块与对应发言人头像的距离是否合理。通过拉普拉斯方差、颜色均值、边缘形状等多重信号判断。

函数:

函数 说明
nickname_row_passes_prd_avatar_guard(...) PRD 规定的完整头像守门检查
nickname_row_passes_avatar_roi(...) 头像 ROI 区域通过性检查
avatar_roi_pass(...) 头像 ROI 多重信号判断
nickname_left_roi_passes_avatar_signal(...) 昵称左侧 ROI 的头像信号检测

ocr.badge_ocr — 未读数字 OCR

依赖: pip install wechat_screenshot_vision_algorithm[ocr]

对检测到的未读红点区域进行数字 OCR,返回未读计数。

函数:

函数 说明
ocr_unread_badge_digits(bgr, badge_hits) 对未读徽章区域进行数字 OCR,返回 {index: digit}

merge.multipage — 多页文本合并

依赖: pip install wechat_screenshot_vision_algorithm[merge]

将同一简历的多页 OCR 文本合并为完整简历文本。使用 N-gram 重叠检测 + Levenshtein 编辑距离相似度。

函数:

函数 说明
merge_multipage_ocr_texts(pages) 合并多页 OCR 文本,返回完整简历字符串
paragraph_content_bounds(merged, anchor) 在合并文本中查找锚点所在的段落边界

png_utils — PNG 压缩上传

依赖: pip install wechat_screenshot_vision_algorithm[png]

将截图 PNG 压缩到指定长边尺寸,用于上传前预处理。

函数:

函数 说明
resolved_collector_upload_long_edge_max(argparse_value) 解析上传 PNG 长边最大像素数(环境变量 COLLECTOR_UPLOAD_LONG_EDGE_MAX / 默认 1920)
maybe_resize_png_long_edge(png_bytes, long_edge_max) 如 PNG 长边超过限制则等比缩小

使用示例

from wechat_screenshot_vision_algorithm import Platform, WeChatVersion, Profile

# 1. 按平台选择 Profile
profile = Profile(platform=Platform.ANDROID, wechat_version=WeChatVersion.V8_0_69)

# 2. 模板匹配
from wechat_screenshot_vision_algorithm.algorithms.template_matching import (
    load_template, find_favorite_labels,
)
import cv2
screenshot = cv2.imread("chat_screenshot.png")
favorite_labels = find_favorite_labels(screenshot, scale_w=screenshot.shape[1] / profile.BASELINE_WIDTH)

# 3. 简历卡片检测
from wechat_screenshot_vision_algorithm.algorithms.card_bbox import (
    _compute_exact_card_bboxes, pick_next_unclicked_card,
)
cards = _compute_exact_card_bboxes(favorite_labels, screenshot,
                                    screen_w=screenshot.shape[1],
                                    screen_h=screenshot.shape[0])
print(f"检测到 {len(cards)} 张简历卡片")

# 4. 发言人分桶
from wechat_screenshot_vision_algorithm.algorithms.speaker_band import (
    compute_chat_content_vertical_bounds, build_prd_speaker_vertical_bands,
)
bounds = compute_chat_content_vertical_bounds(screenshot, scale_w=1.0)
layout = build_prd_speaker_vertical_bands(screenshot, bounds, scale_w=1.0)

# 5. OCR 昵称提取 (需 pip install wechat_screenshot_vision_algorithm[ocr])
from wechat_screenshot_vision_algorithm.ocr.text_ocr_adapter import OcrPageResult
from wechat_screenshot_vision_algorithm.ocr.nickname_binding import extract_nicknames, NicknameOcrConfig
# ... 初始化 PaddleOCR 并调用 extract_nicknames(ocr_result, config)

开发指南

添加新平台支持

  1. profiles/ 下创建新文件(如 ios_wechat.py),复制 android_wechat.py 并修改阈值
  2. 将模板 PNG 放入 templates/wechat/{platform}/{version}/
  3. _config.py_PROFILE_MODULES 中注册

本地开发安装

git clone https://github.com/yuyidream/wechat_screenshot_vision_algorithm.git
cd wechat_screenshot_vision_algorithm
pip install -e .            # 默认依赖
pip install -e ".[ocr,png,merge]"  # 全部可选依赖

运行测试

pytest tests/ -v

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

wechat_screenshot_vision_algorithm-0.2.2.tar.gz (136.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

File details

Details for the file wechat_screenshot_vision_algorithm-0.2.2.tar.gz.

File metadata

File hashes

Hashes for wechat_screenshot_vision_algorithm-0.2.2.tar.gz
Algorithm Hash digest
SHA256 e224f6cee8615922d62f2f350c5ddbf1a00029d97943276680b2b29da521048a
MD5 949c35899c8b8a0e6300bfbe44907a06
BLAKE2b-256 9528b1a452bccb7f58a64ee93e47036cbf43e286f5be21069326a9a5013927e8

See more details on using hashes here.

File details

Details for the file wechat_screenshot_vision_algorithm-0.2.2-py3-none-any.whl.

File metadata

File hashes

Hashes for wechat_screenshot_vision_algorithm-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 de132262f9906e2945dcf1ebcc24f4b6613018a754cde12f15e92f869dc89253
MD5 a80b9fa2638ffd1d53755fb73d7cea38
BLAKE2b-256 a1534d378fb20c9105ed811e9219b9d5d4029bfa31284692922ef812dbd0ee08

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page