OCR 操作示例
本文演示四个核心屏幕识别/点击函数的用法。 每个示例都是可直接放入
src/tasks/onetime/并注册运行的完整任务文件, 风格与src/tasks/test/下的调试任务保持一致。
函数速览
| 函数 | 何时用 |
|---|---|
ocr(match, box) |
立即扫描一次,不等待;适合循环轮询或判断当前画面 |
wait_ocr(match, box, time_out) |
持续扫描直到出现匹配或超时;返回 List[Box],超时返回 None |
click(target, after_sleep) |
点击坐标或 Box 对象 |
wait_click_ocr(match, box, time_out) |
wait_ocr + click 的一步组合 |
Box.name 属性保存 OCR 识别到的文字内容,可用于二次判断。
示例一:用 wait_click_ocr 点击简单按钮
场景:打开信用交易所,等待"立即刷新"按钮出现后点击。
# src/tasks/onetime/ExampleClickOcr.py
import re
from src.core.BaseEfTask import BaseEfTask
class ExampleClickOcr(BaseEfTask):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.name = "示例:wait_click_ocr"
self.description = "等待指定文字出现后自动点击"
def run(self):
# 等待顶部区域出现"信用交易所"并点击,最多等 5 秒
self.wait_click_ocr(
match=re.compile("信用交易所"),
box=self.box.top,
time_out=5,
)
# 等待左下角出现"收取信用"或"无待领取信用"其中之一并点击
# recheck_time=1:> 0 即启用,等待 recheck_time 秒后重新定位文字坐标再点击,降低因元素位移导致点偏的概率
result = self.wait_click_ocr(
match=[re.compile("收取信用"), re.compile("无待领取信用")],
box=self.box.bottom_left,
time_out=7,
recheck_time=1,
)
if not result:
self.log_info("未找到收取信用或无待领取信用")
return
# result 是 List[Box],Box.name 是识别到的文字
if "收取信用" in result[0].name:
self.log_info("已点击收取信用,等待弹窗关闭")
self.wait_pop_up()
else:
self.log_info("本次无待领取信用,跳过")
示例二:用 wait_ocr + 手动 click 拆分识别与点击
场景:需要在点击前先记录识别结果或做额外判断时,手动拆分两步。
# src/tasks/onetime/ExampleWaitOcrClick.py
import re
from src.core.BaseEfTask import BaseEfTask
class ExampleWaitOcrClick(BaseEfTask):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.name = "示例:wait_ocr + click"
self.description = "先等待识别,再手动点击"
def run(self):
# 等待右侧出现"好友"按钮(最多 7 秒)
result = self.wait_ocr(
match=re.compile("好友"),
box=self.box.right,
time_out=7,
)
if not result:
self.log_info("超时未找到好友按钮,任务结束")
return
# result 是 List[Box],取第一个匹配项点击
# after_sleep=1:点击后等待 1 秒,让页面完成跳转
self.click(result[0], after_sleep=1)
self.log_info(f"已点击:{result[0].name}")
# 等待确认弹窗出现并点击,点击后将鼠标移回原位
confirm = self.wait_ocr(match="确认", box=self.box.bottom, time_out=5)
if confirm:
self.click(confirm[0], after_sleep=0.5)
示例三:用 ocr 循环轮询(不阻塞等待)
场景:需要在某个文字消失之前持续等待,
wait_ocr等待的是"出现", 而等待"消失"只能用ocr自行轮询。
# src/tasks/onetime/ExampleOcrPolling.py
import re
from src.core.BaseEfTask import BaseEfTask
class ExampleOcrPolling(BaseEfTask):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.name = "示例:ocr 轮询"
self.description = "等待某文字消失,或用 ocr 读取当前状态"
def run(self):
# 等待"舰桥"提示文字从左侧区域消失(最多 60 秒)
for _ in range(120):
if not self.ocr(match="舰桥", box=self.box.left):
self.log_info("舰桥提示已消失,继续执行")
break
self.next_frame()
self.sleep(0.5)
else:
self.log_info("等待舰桥消失超时,任务中断")
return
# 单次扫描右上角,判断当前有没有武器补给提示
if self.ocr(match=re.compile("武器补给"), box=self.box.top_right):
self.log_info("检测到武器补给,跳过本次任务")
return
self.log_info("画面正常,继续后续操作")
示例四:wait_ocr 读取屏幕上的数字
场景:等待指定区域出现数字文本并解析为整数(例如读取剩余票数)。
# src/tasks/onetime/ExampleOcrReadNumber.py
import re
from src.core.BaseEfTask import BaseEfTask
class ExampleOcrReadNumber(BaseEfTask):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.name = "示例:wait_ocr 读数字"
self.description = "识别屏幕上的数字并解析为整数"
def run(self):
# box_of_screen(x1, y1, x2, y2) 的参数是 0.0~1.0 的相对比例
ticket_box = self.box_of_screen(
1224 / 1920, 235 / 1080,
1551 / 1920, 356 / 1080,
)
num_str = self.wait_ocr(
match=re.compile(r"\d+"),
box=ticket_box,
time_out=5,
)
if not num_str:
self.log_info("未识别到数字")
return
try:
count = int(num_str[0].name)
except ValueError:
self.log_info(f"识别内容无法转为数字:{num_str[0].name}")
return
self.log_info(f"当前剩余票数:{count}")
示例五:alt=True — 大世界交互点击
为什么需要
alt=True?游戏大世界场景中,交互键默认为
F,但直接发送F键不可靠: 角色可能正在移动,或场景内可交互道具过多,导致F键命中错误的目标。更可靠的做法是先按住
Alt键,再用鼠标点击目标。 按住Alt后游戏会锁定鼠标焦点到对应按钮,此时鼠标点击的优先级高于 场景内的通用交互,不会被其他道具或移动状态干扰。
alt=True让框架在发送点击前自动按下Alt、点击后再松开, 一步完成"Alt + 鼠标点击"的组合操作。经验法则:大世界内与场景物件/NPC 交互时使用
alt=True; 普通菜单 UI 按钮通常不需要。
# src/tasks/onetime/ExampleAltClick.py
import re
from src.core.BaseEfTask import BaseEfTask
class ExampleAltClick(BaseEfTask):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.name = "示例:alt=True 点击"
self.description = "演示大世界场景中需要按住 Alt 才能可靠触发的交互"
def run(self):
# 大世界场景:等待屏幕右下角出现"放弃"交互提示并点击
# 直接发 F 键可能因角色移动或道具干扰而命中错误目标
# alt=True 让框架先按住 Alt 再点击,锁定到正确的交互目标
if self.wait_ocr(match=re.compile("放弃"), box=self.box.bottom_right, time_out=5):
self.log_info("发现放弃交互,执行 Alt+点击")
self.wait_click_ocr(
match=re.compile("放弃"),
box=self.box.bottom_right,
time_out=5,
recheck_time=1,
alt=True,
)
self.wait_click_ocr(
match=re.compile("确认"),
box=self.box.bottom_right,
time_out=5,
)
# 等待"激发"交互出现,同样使用 alt=True 确保在大世界内可靠点击
self.sleep(1)
if not self.wait_click_ocr(
match=re.compile("激发"),
box=self.box.bottom_right,
time_out=5,
recheck_time=1,
alt=True,
):
self.log_info("没有找到『激发』交互,任务结束")
return
self.log_info("激发成功,进入战斗")
示例六:recheck_time — 等待后重新定位再点击
为什么需要
recheck_time?
wait_ocr找到目标文字后会立即尝试点击,但部分元素在刚出现时仍在移动 (例如弹出动画、滚动列表);或文字刚好出现在过渡画面里,1~2 帧后就消失。 此时直接点击可能命中偏移后的位置,或点到已消失的元素而静默失败。
recheck_time > 0会让wait_click_ocr在找到结果后等待recheck_time秒 (等待时长即传入的数值), 然后再做一次ocr重新获取文字坐标。若仍能找到同一文字,以新坐标执行点击; 若期间元素已消失,则本次点击跳过,避免误操作。 注意:这只是降低偏移的概率,并不能保证等待期间动画一定已完成。经验法则:元素在出现后位置仍可能偏移,或需要规避短暂出现后消失的过渡元素时, 加
recheck_time=1;画面静止、按钮始终可见时不需要。
# src/tasks/onetime/ExampleRecheckTime.py
import re
from src.core.BaseEfTask import BaseEfTask
class ExampleRecheckTime(BaseEfTask):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.name = "示例:recheck_time"
self.description = "演示点击前等待画面稳定的用法"
def run(self):
# 点击"领取奖励"按钮,该按钮有淡入动画,刚出现时位置可能仍在偏移
# recheck_time=1:> 0 即启用,等待 recheck_time 秒后重新定位文字坐标再点击,降低点偏的概率
result = self.wait_click_ocr(
match=re.compile("领取奖励"),
box=self.box.bottom_right,
time_out=10,
recheck_time=1,
)
if not result:
self.log_info("未找到领取奖励按钮,任务结束")
return
self.log_info("已点击领取奖励")
# 等待确认弹窗出现并点击,同样加 recheck_time 等待弹窗坐标稳定后再点击
self.wait_click_ocr(
match=re.compile("确认"),
box=self.box.bottom,
time_out=5,
recheck_time=1,
)
注册与运行
将上述任意示例文件保存到 src/tasks/onetime/ 后,在 src/config.py 中注册:
config["onetime_tasks"].append(
["src.tasks.onetime.ExampleClickOcr", "ExampleClickOcr"]
)
重启程序(python main_debug.py),在 GUI 任务列表中即可找到并运行。
相关文档
| 文档 | 说明 |
|---|---|
| 图像模板匹配示例.md | 用模板匹配识别图标:find_feature 完整示例任务 |