# coding=utf-8 """ T2_Identify.py - 视觉识别系统测试 (Vision System Test) 【核心功能】 - 静态分析:仅截图并分析,不进行任何点击操作。 - 视觉验证:测试 OCR 识别准确率、发送者判定 (颜色/几何)、消息类型分类。 - 调试工具:生成详细的检测日志和标记框图片 (T2_Identify_Debug.jpg)。 【使用场景】 - 当发现机器人“看不见”某条消息时。 - 当机器人把“对方”的消息误认为是“我”的消息时。 - 调整 OCR 阈值或几何判定规则后的快速验证。 """ import os import sys import logging import cv2 import json # Add project root project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) if project_root not in sys.path: sys.path.append(project_root) from WeiXin import WxUtil # Setup Logger logger = logging.getLogger("T2_Identify") logger.setLevel(logging.INFO) formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') # Console Handler ch = logging.StreamHandler() ch.setFormatter(formatter) logger.addHandler(ch) # File Handler log_file = os.path.join(WxUtil.LOG_DIR, "T2_Identify.log") fh = logging.FileHandler(log_file, mode='w', encoding='utf-8') fh.setFormatter(formatter) logger.addHandler(fh) def main(): logger.info("--- T2: Identify Elements ---") # 1. Connect d = WxUtil.connect_device() if not d: logger.error("Device connection failed.") return # 2. Screenshot/Image Source if len(sys.argv) > 1: screenshot_path = sys.argv[1] logger.info(f"Using provided image: {screenshot_path}") else: screenshot_path = os.path.join(WxUtil.OUTPUT_DIR, "T2_Screenshot.jpg") logger.info("Taking screenshot...") try: d.screenshot(screenshot_path) logger.info(f"Screenshot saved to: {screenshot_path}") except Exception as e: logger.error(f"Failed to take screenshot: {e}") # If screenshot fails, try to use existing one for debugging if it exists if os.path.exists(screenshot_path): logger.warning(f"Using existing screenshot at {screenshot_path}") else: return # 3. Analyze (Using the internal _scan function to see raw detection) logger.info("Scanning image for elements...") messages, debug_img, chat_title = WxUtil._scan_chat_messages(screenshot_path) # 4. Output Raw Detection logger.info(f"Chat Title: {chat_title}") logger.info(f"--- Raw Detection ({len(messages)} items) ---") for i, msg in enumerate(messages): # Format for readability content = msg.get('content', '') if content is None: content = "[None]" type_str = msg.get('type', 'unknown') sender_str = msg.get('sender', 'unknown') center = msg.get('center', (0,0)) y = msg.get('y', 0) time_disp = msg.get('time_display', 'N/A') logger.info(f"[{i}] {type_str:<8} | {sender_str:<4} | y={y:<4} | time={time_disp} | {content}") # 5. Merging Logic (Simulate what the bot SHOULD do) logger.info("--- Merged Dialogues (Simulated) ---") merged_msgs = [] if messages: current_msg = messages[0].copy() last_y = current_msg['y'] # Track Y of the last element in the current merge block for i in range(1, len(messages)): next_msg = messages[i] # Merge Criteria: # 1. Same Sender # 2. Same Type (text) # 3. Vertically close (y_diff < 100) relative to the LAST line, not the first # 4. Not a timestamp is_same_sender = (current_msg['sender'] == next_msg['sender']) is_text = (current_msg['type'] == 'text' and next_msg['type'] == 'text') # Use last_y to compare with next_msg['y'] y_diff = next_msg['y'] - last_y is_close = (y_diff < 120) # Tolerance for line spacing (slightly increased) if is_same_sender and is_text and is_close: # Merge content current_msg['content'] += " " + next_msg['content'] # Update last_y to this message's y last_y = next_msg['y'] else: merged_msgs.append(current_msg) current_msg = next_msg.copy() last_y = current_msg['y'] merged_msgs.append(current_msg) for i, msg in enumerate(merged_msgs): content = msg.get('content', '') sender = msg.get('sender', 'unknown') logger.info(f"[{i}] {sender}: {content}") # 6. Save Debug Image debug_path = os.path.join(WxUtil.OUTPUT_DIR, "T2_Identify_Debug.jpg") if debug_img is not None: cv2.imwrite(debug_path, debug_img) logger.info(f"Debug image saved to: {debug_path}") if __name__ == "__main__": main()