refactor(task): 将培育中 acquisitions 函数所有 OCR 改为模板匹配

This commit is contained in:
XcantloadX 2025-03-16 20:24:20 +08:00
parent 425e998adb
commit 6e336d94f1
10 changed files with 39 additions and 40 deletions

View File

@ -1 +1 @@
{"definitions":{"05890a1b-8764-4e9f-9d21-65d292c22e13":{"name":"InPurodyuusu.BoxGoalClearNext","displayName":"培育目标达成 NEXT 文字区域","type":"hint-box","annotationId":"05890a1b-8764-4e9f-9d21-65d292c22e13","useHintRect":false}},"annotations":[{"id":"05890a1b-8764-4e9f-9d21-65d292c22e13","type":"rect","data":{"x1":79,"y1":503,"x2":157,"y2":532}}]} {"definitions":{"05890a1b-8764-4e9f-9d21-65d292c22e13":{"name":"InPurodyuusu.TextGoalClearNext","displayName":"培育目标达成 NEXT 文字","type":"template","annotationId":"05890a1b-8764-4e9f-9d21-65d292c22e13","useHintRect":false}},"annotations":[{"id":"05890a1b-8764-4e9f-9d21-65d292c22e13","type":"rect","data":{"x1":79,"y1":503,"x2":157,"y2":532}}]}

View File

@ -1 +1 @@
{"definitions":{"582d36c0-0916-4706-9833-4fbc026701f5":{"name":"InPurodyuusu.BoxPDrinkMaxConfirmTitle","displayName":"P饮料溢出 不领取弹窗标题","type":"hint-box","annotationId":"582d36c0-0916-4706-9833-4fbc026701f5","useHintRect":false}},"annotations":[{"id":"582d36c0-0916-4706-9833-4fbc026701f5","type":"rect","data":{"x1":46,"y1":829,"x2":270,"y2":876}}]} {"definitions":{"582d36c0-0916-4706-9833-4fbc026701f5":{"name":"InPurodyuusu.TextPDrinkMaxConfirmTitle","displayName":"P饮料溢出 不领取弹窗标题","type":"template","annotationId":"582d36c0-0916-4706-9833-4fbc026701f5","useHintRect":false}},"annotations":[{"id":"582d36c0-0916-4706-9833-4fbc026701f5","type":"rect","data":{"x1":46,"y1":829,"x2":270,"y2":876}}]}

Binary file not shown.

After

Width:  |  Height:  |  Size: 465 KiB

View File

@ -0,0 +1 @@
{"definitions":{"8c179a21-be6f-4db8-a9b0-9afeb5c36b1c":{"name":"InPurodyuusu.TextPDrink","displayName":"文本「Pドリンク」","type":"template","annotationId":"8c179a21-be6f-4db8-a9b0-9afeb5c36b1c","useHintRect":false,"description":"用于 P 饮料选择对话框"}},"annotations":[{"id":"8c179a21-be6f-4db8-a9b0-9afeb5c36b1c","type":"rect","data":{"x1":244,"y1":615,"x2":357,"y2":641}}]}

View File

@ -1 +1 @@
{"definitions":{"6b58d90d-2e5e-4b7f-bc01-941f2633de89":{"name":"InPurodyuusu.BoxSelectPStuff","displayName":"选择奖励对话框提示语","type":"hint-box","annotationId":"6b58d90d-2e5e-4b7f-bc01-941f2633de89","useHintRect":false},"b3c9e526-de47-44c2-9bda-e9a8a79fdb5a":{"name":"InPurodyuusu.BoxSelectPStuffComfirm","displayName":"选择奖励对话框 领取按钮","type":"hint-box","annotationId":"b3c9e526-de47-44c2-9bda-e9a8a79fdb5a","useHintRect":false}},"annotations":[{"id":"6b58d90d-2e5e-4b7f-bc01-941f2633de89","type":"rect","data":{"x1":62,"y1":558,"x2":655,"y2":716}},{"id":"b3c9e526-de47-44c2-9bda-e9a8a79fdb5a","type":"rect","data":{"x1":256,"y1":1064,"x2":478,"y2":1128}}]} {"definitions":{"b3c9e526-de47-44c2-9bda-e9a8a79fdb5a":{"name":"InPurodyuusu.BoxSelectPStuffComfirm","displayName":"选择奖励对话框 领取按钮","type":"hint-box","annotationId":"b3c9e526-de47-44c2-9bda-e9a8a79fdb5a","useHintRect":false},"c948f136-416f-447e-8152-54a1cd1d1329":{"name":"InPurodyuusu.TextClaim","displayName":"文字「受け取る」","type":"template","annotationId":"c948f136-416f-447e-8152-54a1cd1d1329","useHintRect":false,"description":"用于 P 物品、P 饮料、技能卡选择对话框"},"0c0627be-4a09-4450-a078-1858d3ace532":{"name":"InPurodyuusu.TextPItem","displayName":"文字「Pアイテム」","type":"template","annotationId":"0c0627be-4a09-4450-a078-1858d3ace532","useHintRect":false,"description":"用于 P 物品选择对话框"}},"annotations":[{"id":"b3c9e526-de47-44c2-9bda-e9a8a79fdb5a","type":"rect","data":{"x1":256,"y1":1064,"x2":478,"y2":1128}},{"id":"c948f136-416f-447e-8152-54a1cd1d1329","type":"rect","data":{"x1":144,"y1":608,"x2":245,"y2":647}},{"id":"0c0627be-4a09-4450-a078-1858d3ace532","type":"rect","data":{"x1":247,"y1":613,"x2":354,"y2":645}}]}

Binary file not shown.

After

Width:  |  Height:  |  Size: 737 KiB

View File

@ -0,0 +1 @@
{"definitions":{"d271a24f-efe8-424d-8fd5-f6b3756ba4ca":{"name":"InPurodyuusu.TextSkillCard","displayName":"文字「スキルカード」","type":"template","annotationId":"d271a24f-efe8-424d-8fd5-f6b3756ba4ca","useHintRect":false,"description":"用于技能卡选择对话框"}},"annotations":[{"id":"d271a24f-efe8-424d-8fd5-f6b3756ba4ca","type":"rect","data":{"x1":229,"y1":614,"x2":372,"y2":645}}]}

View File

@ -1 +1 @@
{"definitions":{"6b58d90d-2e5e-4b7f-bc01-941f2633de89":{"name":"InPurodyuusu.BoxSkillCardEnhaced","displayName":"技能卡强化文本提示","type":"hint-box","annotationId":"6b58d90d-2e5e-4b7f-bc01-941f2633de89","useHintRect":false}},"annotations":[{"id":"6b58d90d-2e5e-4b7f-bc01-941f2633de89","type":"rect","data":{"x1":49,"y1":948,"x2":676,"y2":1106}}]} {"definitions":{"6b58d90d-2e5e-4b7f-bc01-941f2633de89":{"name":"InPurodyuusu.IconSkillCardEventBubble","displayName":"技能卡事件气泡框图标","type":"template","annotationId":"6b58d90d-2e5e-4b7f-bc01-941f2633de89","useHintRect":false,"description":"背景上左右两边的星星"}},"annotations":[{"id":"6b58d90d-2e5e-4b7f-bc01-941f2633de89","type":"rect","data":{"x1":46,"y1":1007,"x2":79,"y2":1047}}]}

View File

@ -1,6 +1,7 @@
from typing import Literal from typing import Literal
from logging import getLogger from logging import getLogger
from kotonebot.backend.preprocessor import HsvColorFilter
from kotonebot.tasks.actions.loading import loading from kotonebot.tasks.actions.loading import loading
from .. import R from .. import R
@ -14,7 +15,7 @@ from kotonebot import (
sleep, sleep,
Interval, Interval,
) )
from ..game_ui import CommuEventButtonUI from ..game_ui import CommuEventButtonUI, WhiteFilter
from .pdorinku import acquire_pdorinku from .pdorinku import acquire_pdorinku
from kotonebot.backend.dispatch import SimpleDispatcher from kotonebot.backend.dispatch import SimpleDispatcher
from kotonebot.tasks.actions.commu import handle_unread_commu from kotonebot.tasks.actions.commu import handle_unread_commu
@ -55,7 +56,7 @@ def acquire_skill_card():
def select_p_item(): def select_p_item():
""" """
前置条件P物品选择对话框受け取るPアイテムを選んでください;\n 前置条件P物品选择对话框受け取るPアイテムを選んでください;\n
结束条件P物品获取动画 结束状态P物品获取动画
""" """
# 前置条件 [screenshots/produce/in_produce/select_p_item.png] # 前置条件 [screenshots/produce/in_produce/select_p_item.png]
# 前置条件 [screenshots/produce/in_produce/claim_p_item.png] # 前置条件 [screenshots/produce/in_produce/claim_p_item.png]
@ -73,12 +74,12 @@ def select_p_item():
def hanlde_skill_card_enhance(): def hanlde_skill_card_enhance():
""" """
前置条件技能卡强化对话框\n 前置条件技能卡强化对话框\n
结束条件技能卡强化动画结束后瞬间 结束状态技能卡强化动画结束后瞬间
:return: 是否成功处理对话框 :return: 是否成功处理对话框
""" """
# 前置条件 [kotonebot-resource\sprites\jp\in_purodyuusu\screenshot_skill_card_enhane.png] # 前置条件 [kotonebot-resource\sprites\jp\in_purodyuusu\screenshot_skill_card_enhane.png]
# 结束条件 [screenshots/produce/in_produce/skill_card_enhance.png] # 结束状态 [screenshots/produce/in_produce/skill_card_enhance.png]
cards = image.find_multi([ cards = image.find_multi([
R.InPurodyuusu.A, R.InPurodyuusu.A,
R.InPurodyuusu.M R.InPurodyuusu.M
@ -93,7 +94,7 @@ def hanlde_skill_card_enhance():
device.screenshot() device.screenshot()
if image.find(R.InPurodyuusu.ButtonEnhance, colored=True): if image.find(R.InPurodyuusu.ButtonEnhance, colored=True):
device.click() device.click()
elif '強化' in ocr.ocr(rect=R.InPurodyuusu.BoxSkillCardEnhaced).squash().text: elif image.find(R.InPurodyuusu.IconSkillCardEventBubble):
device.click_center() device.click_center()
break break
it.wait() it.wait()
@ -104,11 +105,10 @@ AcquisitionType = Literal[
"PDrinkSelect", # P饮料主动领取 "PDrinkSelect", # P饮料主动领取
"PDrinkMax", # P饮料到达上限 "PDrinkMax", # P饮料到达上限
"PSkillCardAcquire", # 技能卡领取 "PSkillCardAcquire", # 技能卡领取
"PSkillCardChange", # 技能卡更换
"PSkillCardSelect", # 技能卡选择 "PSkillCardSelect", # 技能卡选择
"PSkillCardEnhanced", # 技能卡强化 "PSkillCardEnhanced", # 技能卡强化
"PSkillCardEnhanceSelect", # 技能卡强化选择 "PSkillCardEnhanceSelect", # 技能卡强化选择
"PSkillCardRemove", # 技能卡移除 "PSkillCardEvent", # 技能卡事件(随机强化、删除、更换)
"PItemClaim", # P物品领取 "PItemClaim", # P物品领取
"PItemSelect", # P物品选择 "PItemSelect", # P物品选择
"Clear", # 目标达成 "Clear", # 目标达成
@ -118,7 +118,7 @@ AcquisitionType = Literal[
"Loading", # 加载画面 "Loading", # 加载画面
] ]
@measure_time(file_path='logs/acquisition.time.log') @measure_time()
@action('处理培育事件', screenshot_mode='manual') @action('处理培育事件', screenshot_mode='manual')
def acquisitions() -> AcquisitionType | None: def acquisitions() -> AcquisitionType | None:
"""处理行动开始前和结束后可能需要处理的事件,直到到行动页面为止""" """处理行动开始前和结束后可能需要处理的事件,直到到行动页面为止"""
@ -158,10 +158,10 @@ def acquisitions() -> AcquisitionType | None:
logger.info("Leave button found") logger.info("Leave button found")
device.click(leave) device.click(leave)
return "PDrinkMax" return "PDrinkMax"
if ocr.find(contains('報酬'), rect=R.InPurodyuusu.BoxPDrinkMaxConfirmTitle): if image.find(R.InPurodyuusu.TextPDrinkMaxConfirmTitle):
logger.debug("PDrink max confirm found") logger.debug("PDrink max confirm found")
device.screenshot() device.screenshot()
if ocr.find(contains('報酬'), rect=R.InPurodyuusu.BoxPDrinkMaxConfirmTitle): if image.find(R.InPurodyuusu.TextPDrinkMaxConfirmTitle):
if confirm := image.find(R.Common.ButtonConfirm): if confirm := image.find(R.Common.ButtonConfirm):
logger.info("Confirm button found") logger.info("Confirm button found")
device.click(confirm) device.click(confirm)
@ -190,7 +190,7 @@ def acquisitions() -> AcquisitionType | None:
sleep(1) sleep(1)
return "Clear" return "Clear"
# 目标达成 NEXT # 目标达成 NEXT
if ocr.find(regex('NEXT|next'), rect=R.InPurodyuusu.BoxGoalClearNext): if image.find(R.InPurodyuusu.TextGoalClearNext, preprocessors=[WhiteFilter()]):
logger.info("Goal clear (達成) next found") logger.info("Goal clear (達成) next found")
device.click_center() device.click_center()
sleep(1) sleep(1)
@ -218,53 +218,44 @@ def acquisitions() -> AcquisitionType | None:
# 物品选择对话框 # 物品选择对话框
logger.debug("Check award select dialog...") logger.debug("Check award select dialog...")
if result := ocr.find(contains("受け取る"), rect=R.InPurodyuusu.BoxSelectPStuff): if image.find(R.InPurodyuusu.TextClaim):
logger.info("Award select dialog found.") logger.info("Award select dialog found.")
logger.debug(f"Dialog text: {result.text}")
# P饮料选择 # P饮料选择
logger.debug("Check PDrink select...") logger.debug("Check PDrink select...")
if "Pドリンク" in result.text: if image.find(R.InPurodyuusu.TextPDrink):
logger.info("PDrink select found") logger.info("PDrink select found")
acquire_pdorinku(index=0) acquire_pdorinku(index=0)
return "PDrinkSelect" return "PDrinkSelect"
# 技能卡选择 # 技能卡选择
logger.debug("Check skill card select...") logger.debug("Check skill card select...")
if "スキルカード" in result.text: if image.find(R.InPurodyuusu.TextSkillCard):
logger.info("Acquire skill card found") logger.info("Acquire skill card found")
acquire_skill_card() acquire_skill_card()
return "PSkillCardSelect" return "PSkillCardSelect"
# P物品选择 # P物品选择
logger.debug("Check PItem select...") logger.debug("Check PItem select...")
if "Pアイテム" in result.text: if image.find(R.InPurodyuusu.TextPItem):
logger.info("Acquire PItem found") logger.info("Acquire PItem found")
select_p_item() select_p_item()
return "PItemSelect" return "PItemSelect"
# 技能卡变更事件 # 技能卡变更事件
# 包括下面这些:
# 1. 技能卡更换
# [screenshots/produce/in_produce/support_card_change.png]
# 2. 技能卡强化
# [screenshots/produce/in_produce/skill_card_enhance.png]
# 3. 技能卡移除
# [screenshots/produce/in_produce/skill_card_removal.png]
logger.debug("Check skill card events...") logger.debug("Check skill card events...")
if result := ocr.ocr(rect=R.InPurodyuusu.BoxSkillCardEnhaced).squash(): if image.find(R.InPurodyuusu.IconSkillCardEventBubble):
# 技能卡更换(支援卡效果) device.click() # 不能 click_center因为中间是技能卡
# [screenshots/produce/in_produce/support_card_change.png] return "PSkillCardEvent"
if "チェンジ" in result.text:
logger.info("Change skill card found")
device.click(*bottom_pos)
return "PSkillCardChange"
# 技能卡强化
# [screenshots/produce/in_produce/skill_card_enhance.png]
if "強化" in result.text:
logger.info("Enhance skill card found")
device.click(*bottom_pos)
return "PSkillCardEnhanced"
# 技能卡移除
# [screenshots\produce\in_produce\skill_card_removal.png]
if "削除" in result.text:
logger.info("Remove skill card found")
device.click(*bottom_pos)
return "PSkillCardRemove"
# 技能卡获取 # 技能卡获取
# [res/sprites/jp/in_purodyuusu/screenshot_skill_card_acquired.png] # [kotonebot-resource\sprites\jp\in_purodyuusu\screenshot_skill_card_acquired.png]
# 因为这个文本有缩放动画,因此暂时没法用模板匹配代替
if ocr.find("スキルカード獲得", rect=R.InPurodyuusu.BoxSkillCardAcquired): if ocr.find("スキルカード獲得", rect=R.InPurodyuusu.BoxSkillCardAcquired):
logger.info("Acquire skill card from loot box") logger.info("Acquire skill card from loot box")
device.click_center() device.click_center()

View File

@ -193,6 +193,12 @@ class CommuEventButtonUI:
return ocr_result.squash().text return ocr_result.squash().text
class WhiteFilter(HsvColorFilter): class WhiteFilter(HsvColorFilter):
"""
匹配时只匹配图像和模板中的白色部分
此类用于识别空心/透明背景的白色图标或文字
"""
def __init__(self): def __init__(self):
super().__init__(WHITE_LOW, WHITE_HIGH) super().__init__(WHITE_LOW, WHITE_HIGH)