#!/usr/bin/env python # -*- coding: utf-8 -*- """ 测试 image-match:用模板图生成合成截图(模拟手机屏中缩略图),再跑匹配并校验中心点。 用法: python test_img_match.py [screenshot_path] - 仅 template_path: 用模板生成合成截图再匹配(用于验证流程与 RoMa 参数) - template_path + screenshot_path: 用真实截图与模板匹配(用于实机调试) 输出: 打印 JSON 结果及期望中心点(合成时),成功时退出码 0。 """ import os import sys import json import tempfile import subprocess # 项目根目录 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) PROJECT_ROOT = os.path.dirname(os.path.dirname(SCRIPT_DIR)) IMAGE_MATCH = os.path.join(SCRIPT_DIR, "image-match.py") def load_image_cv(path): import cv2 import numpy as np with open(path, "rb") as f: data = np.frombuffer(f.read(), dtype=np.uint8) img = cv2.imdecode(data, cv2.IMREAD_COLOR) if img is not None: return img return cv2.imread(path) def make_synthetic_screenshot(template_path, scale=0.45, offset_x=100, offset_y=350, screen_w=1080, screen_h=2340): """用模板图生成一张合成截图:黑色背景,模板缩放后贴在 (offset_x, offset_y)。""" import cv2 import numpy as np tpl = load_image_cv(template_path) if tpl is None: raise FileNotFoundError(f"无法读取模板: {template_path}") h, w = tpl.shape[:2] new_w = int(round(w * scale)) new_h = int(round(h * scale)) small = cv2.resize(tpl, (new_w, new_h), interpolation=cv2.INTER_AREA) screen = np.zeros((screen_h, screen_w, 3), dtype=np.uint8) screen[:] = (30, 30, 30) # 深灰模拟界面 x1, y1 = offset_x, offset_y x2, y2 = min(offset_x + new_w, screen_w), min(offset_y + new_h, screen_h) sx2 = x2 - x1 sy2 = y2 - y1 screen[y1:y1 + sy2, x1:x1 + sx2] = small[:sy2, :sx2] expect_cx = offset_x + new_w // 2 expect_cy = offset_y + new_h // 2 return screen, (expect_cx, expect_cy, offset_x, offset_y, new_w, new_h) def run_match(screenshot_path, template_path, method="feature"): py = os.environ.get("PYTHON", "python") cmd = [py, IMAGE_MATCH, screenshot_path, template_path, "0.8", method] r = subprocess.run(cmd, capture_output=True, text=True, timeout=60, cwd=PROJECT_ROOT) out = (r.stdout or "").strip() err = (r.stderr or "").strip() if r.returncode != 0 and out: try: return json.loads(out) except json.JSONDecodeError: pass if out: try: return json.loads(out) except json.JSONDecodeError: pass return {"success": False, "error": err or out or "unknown error", "returncode": r.returncode} def main(): if len(sys.argv) < 2: print("用法: python test_img_match.py [screenshot_path]") sys.exit(2) template_path = os.path.abspath(sys.argv[1]) if not os.path.exists(template_path): print(json.dumps({"success": False, "error": f"模板不存在: {template_path}"})) sys.exit(1) screenshot_path = sys.argv[2] if len(sys.argv) > 2 else None expect_center = None if screenshot_path is None: # 合成截图 screenshot_path = os.path.join(tempfile.gettempdir(), "ef_test_screenshot.png") screen, (expect_cx, expect_cy, ox, oy, nw, nh) = make_synthetic_screenshot( template_path, scale=0.45, offset_x=100, offset_y=350 ) import cv2 cv2.imwrite(screenshot_path, screen) expect_center = (expect_cx, expect_cy) print("合成截图已生成:", screenshot_path, "期望中心:", expect_center, file=sys.stderr) result = run_match(screenshot_path, template_path) print(json.dumps(result, ensure_ascii=False, indent=2)) if expect_center and result.get("success"): cx, cy = result.get("center_x"), result.get("center_y") ex, ey = expect_center tol = 25 if abs(cx - ex) <= tol and abs(cy - ey) <= tol: print("中心点与期望一致 (容差 %d px)" % tol, file=sys.stderr) else: print("中心点与期望偏差: 得到 (%d,%d) 期望 (%d,%d)" % (cx, cy, ex, ey), file=sys.stderr) if not result.get("success"): sys.exit(1) sys.exit(0) if __name__ == "__main__": main()