find_feature 操作示例
本文演示
find_feature系列函式的用法。 每個示例都是可直接放入src/tasks/onetime/並註冊執行的完整任務檔案, 風格與src/tasks/test/下的除錯任務保持一致。
函式速覽
| 函式 | 何時用 |
|---|---|
find_feature(feature_name, box, threshold) |
對當前幀做一次模板匹配;找到時返回 List[Box],未找到時返回空列表;feature_name 也可傳入列表 |
find_one(feature_name, box, threshold) |
find_feature 的便捷封裝,只返回置信度最高的那個匹配結果(Box 或 None);同樣支援列表輸入 |
feature_name 接受 FeatureList 列舉值、列舉值組成的列表,或直接使用字串。
框架會根據當前解析度自動選取 _2k / _4k 字尾變體(如有);如果傳入列表,會對列表中的每個元素分別做這一步處理。
不傳
box時的預設搜尋區域模板圖片(
feature_name對應的素材檔案)的推薦製作方式: 直接對遊戲進行截圖,然後使用本軟體 debug 模式左側「模板」Tab 內的功能, 對截圖的某區域進行標記——該功能會自動將裁剪後的模板圖片儲存到assets/images/, 並將該區域的座標寫入assets/coco_annotations.json,無需手動調整資料結構。⚠️ 若使用外部標註軟體,需自行維護
coco_annotations.json中的資料結構,不推薦。當呼叫時省略
box引數,框架會自動從coco_annotations.json讀取該模板的標註位置, 並將其換算成相對比例,再對映到實際程式視窗的對應區域進行掃描。這意味著:你不需要手動計算座標,只需通過「模板」Tab 正確標記模板在截圖中的位置, 框架就能自動把搜尋範圍限定在螢幕上的合理區域,避免全屏誤匹配。
如果需要在預設搜尋區域的基礎上增加容差,可使用
vertical_variance/horizontal_variance引數指定 y / x 方向的相對比例偏差,無需顯式傳入box。如果你需要動態指定搜尋範圍(例如根據上一步操作的結果縮小區域), 才需要顯式傳入
box。
示例一:檢測單個圖示並點選
場景:等待關閉按鈕(
×)出現後點擊。
# src/tasks/onetime/ExampleFindFeature.py
from src.data.FeatureList import FeatureList as fL
from src.core.BaseEfTask import BaseEfTask
class ExampleFindFeature(BaseEfTask):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.name = "示例:find_feature 点击图标"
self.description = "检测关闭按钮并点击"
def run(self):
# find_feature 返回 List[Box],未找到时返回空列表
# 不传 box:框架自动从 coco_annotations.json 读取 fL.close 的标注位置限定搜索区域
result = self.find_feature(feature=fL.close)
if not result:
self.log_info("未找到关闭按钮")
return
# 取第一个匹配结果点击
self.click(result[0], after_sleep=0.5)
self.log_info("已点击关闭按钮")
示例二:動態指定搜尋區域(box 引數)
場景:上一步操作後 ESC 圖示可能出現在右上角的不固定位置, 需要動態限制搜尋範圍;或者你希望覆蓋模板預設位置,手動控制掃描區域。
# src/tasks/onetime/ExampleFindFeatureBox.py
from src.data.FeatureList import FeatureList as fL
from src.core.BaseEfTask import BaseEfTask
class ExampleFindFeatureBox(BaseEfTask):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.name = "示例:find_feature + box"
self.description = "动态指定搜索区域的模板匹配"
def run(self):
# box_of_screen 的参数是 0.0~1.0 的相对比例
# 显式传入 box 会覆盖从 coco_annotations.json 读取的默认搜索位置
# 这里只在右上角 20%×15% 的区域搜索,比默认区域更宽松
top_right = self.box_of_screen(0.8, 0.0, 1.0, 0.15)
result = self.find_feature(
feature=fL.esc,
box=top_right,
threshold=0.8, # 相似度阈值,越高越严格
)
if result:
self.log_info(f"在右上角找到 ESC 图标,坐标:{result[0].x}, {result[0].y}")
self.click(result[0])
else:
self.log_info("右上角未找到 ESC 图标")
示例三:檢測多個候選圖示之一
場景:列表中可能出現兩種不同圖示(例如聊天圖示的亮色/暗色版本), 任意找到一種即可點選。
# src/tasks/onetime/ExampleFindFeatureMultiple.py
from src.data.FeatureList import FeatureList as fL
from src.core.BaseEfTask import BaseEfTask
class ExampleFindFeatureMultiple(BaseEfTask):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.name = "示例:find_feature 多候选图标"
self.description = "在多个候选图标中找到任意一个并点击"
def run(self):
# 传入列表,框架会依次尝试每个 feature_name,返回所有命中结果
result = self.find_feature(
feature=[fL.chat_icon, fL.chat_icon_dark, fL.chat_icon_2],
box=self.box.right,
threshold=0.75,
)
if not result:
self.log_info("未找到聊天图标")
return
# find_feature 按置信度从高到低排列,result[0] 是最佳匹配
self.log_info(f"找到图标:{result[0].name},相似度:{result[0].confidence:.2f}")
self.click(result[0], after_sleep=0.5)
示例四:用 find_one 取置信度最高的結果
場景:螢幕上同時存在多個相似圖示(例如列表裡有若干個「關閉」按鈕), 只需要操作相似度最高的那個時,使用
find_one更簡潔。find_one在內部呼叫find_feature後取置信度最大的Box返回; 未找到時返回None,無需手動取result[0]。
# src/tasks/onetime/ExampleFindOne.py
from src.data.FeatureList import FeatureList as fL
from src.core.BaseEfTask import BaseEfTask
class ExampleFindOne(BaseEfTask):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.name = "示例:find_one"
self.description = "取置信度最高的图标并点击"
def run(self):
# find_one 直接返回 Box 或 None,不需要 result[0]
# 模板的默认搜索位置(由 coco_annotations.json 中的标注坐标决定)会被自动使用
best = self.find_one(feature=fL.close, threshold=0.8)
if not best:
self.log_info("未找到关闭按钮")
return
self.log_info(f"找到关闭按钮,置信度:{best.confidence:.2f}")
self.click(best, after_sleep=0.5)
示例五:輪詢等待圖標出現
場景:某個圖示需要等待數秒後才出現(如戰鬥結束後的獎勵圖示),
find_feature不會自動等待,需要用迴圈輪詢。
# src/tasks/onetime/ExampleFindFeatureWait.py
from src.data.FeatureList import FeatureList as fL
from src.core.BaseEfTask import BaseEfTask
class ExampleFindFeatureWait(BaseEfTask):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.name = "示例:find_feature 轮询等待"
self.description = "等待图标出现后再执行操作"
def run(self):
# 最多等待 30 秒(60 次 × 0.5 秒)
result = None
for _ in range(60):
result = self.find_feature(
feature=fL.claim_gift,
box=self.box.bottom_right,
threshold=0.8,
)
if result:
break
self.next_frame()
self.sleep(0.5)
if not result:
self.log_info("等待领取礼物图标超时,任务结束")
return
self.log_info("检测到领取礼物图标,执行点击")
self.click(result[0], after_sleep=1)
註冊與執行
將上述任意示例檔案儲存到 src/tasks/onetime/ 後,在 src/config.py 中註冊:
config["onetime_tasks"].append(
["src.tasks.onetime.ExampleFindFeature", "ExampleFindFeature"]
)
重啟程式(python main_debug.py),在 GUI 任務列表中即可找到並執行。