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 完整示例任務 |