find_feature 操作示例

返回:文件索引 / README

本文演示 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 的便捷封裝,只返回置信度最高的那個匹配結果(BoxNone);同樣支援列表輸入

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 任務列表中即可找到並執行。

在 GitHub 查看來源 ↗ · 頁面產生時間: 2026年8月10日