API: wingman.vision
视觉模块,提供屏幕检测、图像匹配、形状识别等功能。
模块概述
vision 模块提供屏幕视觉检测功能:
- 颜色检测 - 查找颜色、检查颜色存在、获取主要颜色
- 图像匹配 - 查找图像模板
- 模板批量管理 - 具名登记模板、批量识别(templateAdd / templateFindAll)
查找颜色
find_color(color, tolerance?, region?) / findColor(color, tolerance?, region?)
说明:查找指定颜色在屏幕中的第一个位置。
函数签名:
find_color(color: dict | int, tolerance: int = 10, region: dict = None) -> dict | NonefindColor(color: table | number, tolerance: number = 10, region: table = nil) -> table | nil参数:
color- 颜色值,支持{r: number, g: number, b: number}或整数0xRRGGBBtolerance- 可选,容差值(0-255),默认 10region- 可选,搜索区域{x: number, y: number, width: number, height: number},默认全屏
返回:
- 找到时返回
{x: number, y: number} - 未找到时返回
None/nil
from wingman import vision
# 查找红色
pos = vision.find_color({"r": 255, "g": 0, "b": 0}, 10)
if pos:
print(f"找到颜色: {pos['x']}, {pos['y']}")
# 使用十六进制颜色
pos = vision.find_color(0xFF0000, 10)查找所有颜色
find_all_colors(color, tolerance?, region?) / findAllColors(color, tolerance?, region?)
说明:查找所有匹配颜色的位置。
函数签名:
find_all_colors(color: dict | int, tolerance: int = 10, region: dict = None) -> list[dict]findAllColors(color: table | number, tolerance: number = 10, region: table = nil) -> table参数:
color- 颜色值,支持字典{r, g, b}或整数tolerance- 可选,容差值(0-255),默认 10region- 可选,搜索区域,默认全屏
返回:
- Python: 列表
[{x: number, y: number}, ...] - Lua: 数组
[{x: number, y: number}, ...]
from wingman import vision
positions = vision.find_all_colors({"r": 255, "g": 0, "b": 0}, 5)
for i, pos in enumerate(positions):
print(f"位置 {i}: {pos['x']}, {pos['y']}")检查颜色存在
has_color(color, tolerance?, region?) / hasColor(color, tolerance?, region?)
说明:检查区域内是否包含指定颜色。
函数签名:
has_color(color: dict | int, tolerance: int = 10, region: dict = None) -> boolhasColor(color: table | number, tolerance: number = 10, region: table = nil) -> boolean参数:
color- 颜色值tolerance- 可选,容差值(0-255),默认 10region- 可选,搜索区域,默认全屏
返回:
- 是否找到颜色
from wingman import vision
if vision.has_color({"r": 0, "g": 255, "b": 0}, 10):
print("找到了绿色")获取主要颜色
get_dominant_color(region?) / getDominantColor(region?)
说明:获取区域内主要颜色(出现次数最多的颜色)。
函数签名:
get_dominant_color(region: dict = None) -> dictgetDominantColor(region: table = nil) -> table参数:
region- 可选,分析区域,默认全屏
返回:
- 颜色对象
{r: number, g: number, b: number, a: number}
from wingman import vision
color = vision.get_dominant_color({"x": 0, "y": 0, "width": 200, "height": 200})
print(f"主要颜色: {color['r']}, {color['g']}, {color['b']}")查找图像
find_image(template_path, threshold?, region?) / findImage(templatePath, threshold?, region?)
说明:查找图像模板在屏幕中的位置。
函数签名:
find_image(template_path: str, threshold: float = 0.9, region: dict = None) -> dictfindImage(templatePath: string, threshold: number = 0.9, region: table = nil) -> table参数:
template_path/templatePath- 模板图片路径threshold- 可选,匹配阈值(0.0-1.0),默认 0.9region- 可选,搜索区域,默认全屏
返回:
- 匹配结果对象:
found/found- 是否找到position/position- 位置{x: number, y: number}confidence/confidence- 置信度(0-1)region/region- 匹配区域{x: number, y: number, width: number, height: number}
from wingman import vision
result = vision.find_image("target.png", 0.9)
if result['found']:
print(f"找到图像: {result['position']['x']}, {result['position']['y']}")
print(f"置信度: {result['confidence']}")图像模板批量管理(templateAdd / templateFindAll)
说明:具名模板登记面 + 批量识别。v1 注册表驻内存(进程生命周期); 登记时校验模板文件存在(坏路径登记期即拒,重名拒绝——显式 templateRemove 后可重新登记);批量识别逐个模板匹配,输出名序确定,单模板失败按未 命中落账不中断整批。
| 函数 | 签名 | 说明 |
|---|---|---|
templateAdd | templateAdd(name, path) -> bool | 登记具名模板(路径须存在;重名拒绝) |
templateRemove | templateRemove(name) -> bool | 移除登记(未知名 false) |
templateHas | templateHas(name) -> bool | 查询登记 |
templateList | templateList() -> [{name, path}] | 全部登记,名序确定 |
templateFindAll | templateFindAll(names?, threshold?, region?) -> [{name, found, position?, confidence?, region?}] | 批量识别:names 空/缺省 = 全部登记模板,未知名跳过 |
from wingman import vision
vision.templateAdd("start_btn", "assets/start.png")
vision.templateAdd("settings_btn", "assets/settings.png")
# 批量识别全部登记模板(或传 ["start_btn"] 过滤;未知名跳过)
for hit in vision.template_find_all(threshold=0.85):
if hit["found"]:
print(hit["name"], hit["position"], hit["confidence"])
else:
print(hit["name"], "未命中")AI 视觉识别(aiSetup / aiLocate / aiElements)
AI 语义定位:截取当前屏幕(或指定区域)→ JPEG → OpenAI 兼容视觉模型 → 结构化包围盒(像素坐标),配合 input.click 完成「识别目标并点击」。 需 WINGMAN_ENABLE_VISION 构建(与 findImage 同门禁)。
Android:
wingman.vision五函数同形可用(截帧走 captureFrame 注入, 参数与返回一致;aiSetupLocal例外——onnxruntime NDK 依赖未收口, Android 侧恒返回false,不静默切 HTTP);无 OpenCV 构建下aiSetup注册桌面 stub 同语义假体(aiSetup恒true、aiSetupStatus.configured恒false)。
端点约定:OpenAI 兼容 chat.completions(baseUrl 填到 /v1 为止)—— 云端 API 与本地推理服务(Ollama http://127.0.0.1:11434/v1、vLLM 等)同形, 模型需支持图像输入与坐标定位(如 Qwen2.5-VL 系列)。模型被要求只回 {"found": bool, "label": str, "bbox_2d": [x1,y1,x2,y2], "confidence": 0-1}, 坐标为 0–1000 归一值,按帧尺寸换算像素。
ai_setup(cfg) / aiSetup(cfg)
说明:配置 provider(进程级驻内存,重复调用整体覆盖)。
参数(cfg 表):
baseUrl(string,必填)— 到/v1为止的 OpenAI 兼容端点model(string,必填)— 视觉模型名apiKey(string)— 明文凭据,仅推荐本地/测试环境apiKeyEnc+passphrase(string,成对)— 凭据加密面:apiKeyEnc为crypto.encryptAES(apiKey, passphrase)的密文(AES-256-GCM,与密钥 保险箱同型原语),配置文件里只存密文,运行时解密后仅驻内存,不落盘、 不进日志;apiKey与apiKeyEnc二选一timeoutSeconds(int,默认 60)
返回:bool(baseUrl/model 缺失或密文解密失败返回 false)
ai_setup_status() / aiSetupStatus()
返回:{configured, localMode, baseUrl, model, hasKey, lastError}——凭据 明文不出查询接口(只有 hasKey 标志位);localMode 标识当前走本地 ONNX 检测(见下节)。
ai_locate(desc, region?) / aiLocate(desc, region?)
说明:定位屏幕上符合自然语言描述的目标。
参数:
desc(string)— 目标描述,如「登录按钮」「左上角红色关闭叉」region(表,可选)— 只在该区域内截帧识别;带region时返回的坐标相对 region 左上角(不回加偏移,如需全屏坐标请自行加上 region.x/region.y)
返回:
{found=true, x, y, w, h, confidence, label}— 像素包围盒(左上角+尺寸){found=false, error}— 未配置 / 截帧失败 / HTTP 失败 / 模型未找到目标,error可区分原因
from wingman import vision, input, crypto
# 配置侧:密文预先用 crypto 生成后写进配置(明文不落盘)
cipher = crypto.encryptAES("sk-xxx", "machine-passphrase")
assert vision.aiSetup({
"baseUrl": "http://127.0.0.1:11434/v1", # 本地 Ollama
"model": "qwen2.5-vl:7b",
"apiKeyEnc": cipher,
"passphrase": "machine-passphrase",
})
box = vision.aiLocate("设置图标")
if box["found"]:
input.click(box["x"] + box["w"] // 2, box["y"] + box["h"] // 2)批量元素识别(aiElements)
一次 provider 调用取回多个元素(坐标语义同 aiLocate),供批量断言、 遍历点击等场景。截帧/凭据/容错口径与 aiLocate 共用(0–1000 归一按帧 换算像素;协议约定模型回 {"found": bool, "elements": [{"label": str, "bbox_2d": [x1,y1,x2,y2], "confidence": 0-1}]})。
ai_elements(desc, region?) / aiElements(desc, region?)
参数:
desc(string)— 元素筛选描述;空串 = 列出屏幕上全部可交互元素region(表,可选)— 只在该区域内截帧识别;带region时返回的坐标相对 region 左上角(不回加偏移,如需全屏坐标请自行加上 region.x/region.y)
返回:
{found=true, elements=[{label, x, y, w, h, confidence}, ...]}— 像素 包围盒列表(顺序即模型返回顺序){found=false, elements=[]}— 屏幕无匹配元素(正常空批){found=false, error}— 未配置 / 截帧失败 / HTTP 失败,error可区分原因 (失败与正常空批靠error字段区分)
单项 bbox 缺失或退化只跳过该项,不废整批。
page = vision.aiElements("") # 全部可交互元素
if page["found"]:
for el in page["elements"]:
print(el["label"], el["x"], el["y"], el["w"], el["h"])本地 ONNX 检测 provider(aiSetupLocal)
不依赖外部推理服务的本地视觉定位:加载本地 ONNX 检测模型(YOLOv5/v8 导出约定)直接推理,aiLocate/aiElements 入口自动分流,返回形状与 HTTP provider 完全一致。需 WINGMAN_ENABLE_ML 构建(onnxruntime, Windows/Linux 档收口,Linux 为开发档验证);未构建 ML 时 aiSetupLocal 恒返回 false,不静默降级到 HTTP provider。
ai_setup_local(cfg) / aiSetupLocal(cfg)
说明:切换到本地检测 provider。与 aiSetup 的 HTTP provider 互斥, 后调用者生效;reset 双清。模型加载失败返回 false 且不影响既有配置。
参数(cfg 表):
modelPath(string,必填)— ONNX 模型文件路径labels(string 列表,可选)— classId→名称表;aiLocate的desc与 label 按双向大小写不敏感子串匹配,命中者中置信最高者胜出minConfidence(float,默认 0.5)— 检测置信阈值
返回:bool
模型约定:YOLOv5 布局 [1,N,5+C](conf=obj×cls)与 YOLOv8 布局 [1,4+C,N](无 obj)按输出形状自动判别;输入按模型 NCHW 尺寸 resize 到 0–1 归一,输出框按比例还原原图像素。
限制:预处理为简单 resize、无 letterbox(极端长宽比画面检测框会有 系统性偏移);分割(segment)未实现,诚实报错返回空位图。
assert vision.aiSetupLocal({
"modelPath": "models/ui-detector.onnx",
"labels": ["button", "input", "checkbox"],
"minConfidence": 0.6,
})
box = vision.aiLocate("button") # 本地推理,返回形状同 HTTP provider
if box["found"]:
input.click(box["x"] + box["w"] // 2, box["y"] + box["h"] // 2)可用接口
| Python 函数 | Lua 函数 | 说明 | 参数 |
|---|---|---|---|
find_color(color, tolerance?, region?) | findColor(color, tolerance?, region?) | 查找颜色 | color: 颜色值 tolerance: 容差(默认10) region: 搜索区域(可选) 返回: 位置对象或None/nil |
find_all_colors(color, tolerance?, region?) | findAllColors(color, tolerance?, region?) | 查找所有颜色 | 返回: 位置数组 |
has_color(color, tolerance?, region?) | hasColor(color, tolerance?, region?) | 检查颜色存在 | 返回: 是否存在 |
get_dominant_color(region?) | getDominantColor(region?) | 获取主要颜色 | region: 分析区域(可选) 返回: 颜色对象RGBA |
find_image(path, threshold?, region?) | findImage(path, threshold?, region?) | 查找图像 | path: 模板路径 threshold: 匹配阈值(默认0.9) region: 搜索区域(可选) 返回: 匹配结果对象 |
template_add(name, path) | templateAdd(name, path) | 登记具名模板 | name: 模板名(重名拒绝) path: 模板图像路径(须存在) 返回: 是否成功 |
template_remove(name) | templateRemove(name) | 移除登记 | 返回: 是否成功 |
template_has(name) | templateHas(name) | 查询登记 | 返回: 是否已登记 |
template_list() | templateList() | 全部登记 | 返回: [{name, path}](名序) |
template_find_all(names?, threshold?, region?) | templateFindAll(names?, threshold?, region?) | 批量识别 | names: 过滤名单(空=全部,未知名跳过) threshold: 匹配阈值(默认0.9) region: 搜索区域(可选) 返回: [{name,found,position?,confidence?,region?}](名序) |
ai_setup(cfg) | aiSetup(cfg) | 配置 AI 视觉 provider | cfg: 配置表(baseUrl/model/凭据) 返回: 是否成功 |
ai_setup_status() | aiSetupStatus() | 查询 provider 配置状态 | 返回: |
ai_setup_local(cfg) | aiSetupLocal(cfg) | 切换本地 ONNX 检测 provider(需 ML 构建) | cfg: 配置表(modelPath/labels/minConfidence) 返回: 是否成功 |
ai_locate(desc, region?) | aiLocate(desc, region?) | AI 语义定位屏幕目标 | desc: 目标描述 region: 区域(可选) 返回: {found,x,y,w,h,confidence,label} 或 |
ai_elements(desc, region?) | aiElements(desc, region?) | AI 批量元素识别 | desc: 筛选描述(空串=全部可交互元素) region: 区域(可选) 返回: {found,elements:[{label,x,y,w,h,confidence}]} 或 |