From 0bb9af7275db151fc10521db5518f020b8557b1a Mon Sep 17 00:00:00 2001 From: LmeSzinc <37934724+LmeSzinc@users.noreply.github.com> Date: Sat, 30 Mar 2024 00:19:10 +0800 Subject: [PATCH] Fix: AdaptiveScroll to handle transparent scroll on complex background (#391) --- .../SYNTHESIZE_SCROLL.png | Bin 10591 -> 10249 bytes .../ITEM_CONSUMABLE_SCROLL.png | Bin 9740 -> 8745 bytes module/ui/scroll.py | 51 +++++++++++++++++- tasks/combat/support.py | 48 +++-------------- .../assets_daily_synthesize_consumable.py | 8 +-- tasks/daily/synthesize.py | 6 +-- .../assets/assets_item_consumable_usage.py | 8 +-- tasks/item/consumable_usage.py | 4 +- 8 files changed, 68 insertions(+), 57 deletions(-) diff --git a/assets/share/daily/synthesize_consumable/SYNTHESIZE_SCROLL.png b/assets/share/daily/synthesize_consumable/SYNTHESIZE_SCROLL.png index d3f240e787a66593c898ee1f47919d9ce9d604be..fd5cb945f0e31ff97c46c3d162637320c4140cd4 100644 GIT binary patch literal 10249 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 G^#1_M{6Uid literal 10591 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 literal 9740 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 Q9m(^q*A~yJcOnn`7jhwDr~m)} diff --git a/module/ui/scroll.py b/module/ui/scroll.py index 7500e9c35..358e6a01f 100644 --- a/module/ui/scroll.py +++ b/module/ui/scroll.py @@ -1,9 +1,10 @@ import numpy as np +from scipy import signal from module.base.base import ModuleBase from module.base.button import Button, ButtonWrapper from module.base.timer import Timer -from module.base.utils import color_similarity_2d, random_rectangle_point +from module.base.utils import color_similarity_2d, random_rectangle_point, rgb2gray from module.logger import logger @@ -46,7 +47,7 @@ class Scroll: Returns: np.ndarray: Shape (n,), dtype bool. """ - image = main.image_crop(self.area) + image = main.image_crop(self.area, copy=False) image = color_similarity_2d(image, color=self.color) mask = np.max(image, axis=1 if self.is_vertical else 0) > self.color_threshold self.length = np.sum(mask) @@ -210,3 +211,49 @@ class Scroll: def prev_page(self, main, page=0.8, random_range=(-0.01, 0.01), skip_first_screenshot=True): return self.drag_page(-page, main=main, random_range=random_range, skip_first_screenshot=skip_first_screenshot) + + +class AdaptiveScroll(Scroll): + def __init__(self, area, parameters: dict = None, background=5, is_vertical=True, name='Scroll'): + """ + Args: + area (Button, tuple): A button or area of the whole scroll. + prominence (dict): Parameters passing to scipy.find_peaks + background (int): + is_vertical (bool): True if vertical, false if horizontal. + name (str): + """ + if parameters is None: + parameters = {} + self.parameters = parameters + self.background = background + super().__init__(area, color=(255, 255, 255), is_vertical=is_vertical, name=name) + + def match_color(self, main): + if self.is_vertical: + area = (self.area[0] - self.background, self.area[1], self.area[2] + self.background, self.area[3]) + image = main.image_crop(area, copy=False) + image = rgb2gray(image) + image = image.flatten() + wlen = area[2] - area[0] + else: + area = (self.area[0], self.area[1] - self.background, self.area[2], self.area[3] + self.background) + image = main.image_crop(area, copy=False) + image = rgb2gray(image) + image = image.flatten('F') + wlen = area[3] - area[1] + + parameters = { + 'height': 128, + 'prominence': 30, + 'wlen': wlen, + 'width': 2, + } + parameters.update(self.parameters) + peaks, _ = signal.find_peaks(image, **parameters) + peaks //= wlen + + self.length = len(peaks) + mask = np.zeros((self.total,), dtype=np.bool_) + mask[peaks] = 1 + return mask diff --git a/tasks/combat/support.py b/tasks/combat/support.py index ff628217d..568b74b68 100644 --- a/tasks/combat/support.py +++ b/tasks/combat/support.py @@ -1,12 +1,11 @@ import cv2 import numpy as np -from scipy import signal from module.base.button import ClickButton from module.base.timer import Timer -from module.base.utils import area_offset, area_size, crop, load_image, rgb2luma +from module.base.utils import area_offset, crop, load_image from module.logger import logger -from module.ui.scroll import Scroll +from module.ui.scroll import AdaptiveScroll from tasks.base.assets.assets_base_popup import POPUP_CANCEL from tasks.base.ui import UI from tasks.combat.assets.assets_combat_support import COMBAT_SUPPORT_ADD, COMBAT_SUPPORT_LIST, \ @@ -116,41 +115,6 @@ class NextSupportCharacter: return SUPPORT_SELECTED.match_template(image, similarity=0.75, direct_match=True) -class SupportListScroll(Scroll): - def cal_position(self, main): - """ - Args: - main (ModuleBase): - - Returns: - float: 0 to 1. - """ - image = main.device.image - - temp_area = list(self.area) - temp_area[0] = int(temp_area[0] * 0.98) - temp_area[2] = int(temp_area[2] * 1.02) - - line = rgb2luma(crop(image, temp_area)).flatten() - width = area_size(temp_area)[0] - parameters = { - "height": 180, - "prominence": 30, - "distance": width * 0.75, - } - peaks, _ = signal.find_peaks(line, **parameters) - peaks //= width - self.length = len(peaks) - middle = np.mean(peaks) - - position = (middle - self.length / 2) / (self.total - self.length) - position = position if position > 0 else 0.0 - position = position if position < 1 else 1.0 - logger.attr( - self.name, f"{position:.2f} ({middle}-{self.length / 2})/({self.total}-{self.length})") - return position - - class CombatSupport(UI): def support_set(self, support_character_name: str = "FirstCharacter"): """ @@ -212,8 +176,8 @@ class CombatSupport(UI): out: COMBAT_SUPPORT_LIST """ logger.hr("Combat support search") - scroll = SupportListScroll(area=COMBAT_SUPPORT_LIST_SCROLL.area, color=(194, 196, 205), - name=COMBAT_SUPPORT_LIST_SCROLL.name) + scroll = AdaptiveScroll(area=COMBAT_SUPPORT_LIST_SCROLL.area, + name=COMBAT_SUPPORT_LIST_SCROLL.name) if scroll.appear(main=self): if not scroll.at_bottom(main=self): # Dropdown to load the entire support list, so large threshold is acceptable @@ -311,8 +275,8 @@ class CombatSupport(UI): out: COMBAT_SUPPORT_LIST """ skip_first_screenshot = True - scroll = SupportListScroll(area=COMBAT_SUPPORT_LIST_SCROLL.area, color=(194, 196, 205), - name=COMBAT_SUPPORT_LIST_SCROLL.name) + scroll = AdaptiveScroll(area=COMBAT_SUPPORT_LIST_SCROLL.area, + name=COMBAT_SUPPORT_LIST_SCROLL.name) interval = Timer(1) next_support = None if scroll.appear(main=self): diff --git a/tasks/daily/assets/assets_daily_synthesize_consumable.py b/tasks/daily/assets/assets_daily_synthesize_consumable.py index 87043b768..fc349da7d 100644 --- a/tasks/daily/assets/assets_daily_synthesize_consumable.py +++ b/tasks/daily/assets/assets_daily_synthesize_consumable.py @@ -141,9 +141,9 @@ SYNTHESIZE_SCROLL = ButtonWrapper( name='SYNTHESIZE_SCROLL', share=Button( file='./assets/share/daily/synthesize_consumable/SYNTHESIZE_SCROLL.png', - area=(458, 80, 464, 628), - search=(438, 60, 484, 648), - color=(134, 130, 144), - button=(458, 80, 464, 628), + area=(460, 90, 464, 618), + search=(440, 70, 484, 638), + color=(167, 165, 177), + button=(460, 90, 464, 618), ), ) diff --git a/tasks/daily/synthesize.py b/tasks/daily/synthesize.py index 718b60bba..28309cf15 100644 --- a/tasks/daily/synthesize.py +++ b/tasks/daily/synthesize.py @@ -1,5 +1,5 @@ from module.ocr.ocr import * -from module.ui.scroll import Scroll +from module.ui.scroll import AdaptiveScroll, Scroll from tasks.base.assets.assets_base_page import MENU_CHECK, MENU_SCROLL, SYNTHESIZE_CHECK from tasks.base.assets.assets_base_popup import POPUP_CONFIRM from tasks.base.page import Page, page_menu, page_synthesize @@ -32,7 +32,7 @@ class SynthesizeUI(UI): scroll = Scroll(MENU_SCROLL.button, color=(191, 191, 191), name=MENU_SCROLL.name) case page_synthesize.name: check_image = SYNTHESIZE_CHECK - scroll = Scroll(SYNTHESIZE_SCROLL.button, color=(210, 210, 210), name=SYNTHESIZE_SCROLL.name) + scroll = AdaptiveScroll(SYNTHESIZE_SCROLL.button, name=SYNTHESIZE_SCROLL.name) case _: logger.info(f'No page matched, just skip') return @@ -109,7 +109,7 @@ class SynthesizeUI(UI): else self.__class__.default_candidate_items # Search target button from top to bottom - scroll = Scroll(SYNTHESIZE_SCROLL.button, color=(210, 210, 210), name=SYNTHESIZE_SCROLL.name) + scroll = AdaptiveScroll(SYNTHESIZE_SCROLL.button, name=SYNTHESIZE_SCROLL.name) if scroll.appear(main=self): skip_first_screenshot = True while 1: diff --git a/tasks/item/assets/assets_item_consumable_usage.py b/tasks/item/assets/assets_item_consumable_usage.py index 1670c72b3..12549bf8c 100644 --- a/tasks/item/assets/assets_item_consumable_usage.py +++ b/tasks/item/assets/assets_item_consumable_usage.py @@ -7,10 +7,10 @@ ITEM_CONSUMABLE_SCROLL = ButtonWrapper( name='ITEM_CONSUMABLE_SCROLL', share=Button( file='./assets/share/item/consumable_usage/ITEM_CONSUMABLE_SCROLL.png', - area=(837, 89, 843, 615), - search=(817, 69, 863, 635), - color=(118, 117, 121), - button=(837, 89, 843, 615), + area=(838, 90, 842, 614), + search=(818, 70, 862, 634), + color=(141, 141, 153), + button=(838, 90, 842, 614), ), ) SIMPLE_PROTECTIVE_GEAR = ButtonWrapper( diff --git a/tasks/item/consumable_usage.py b/tasks/item/consumable_usage.py index 6df481dc5..e1d67180b 100644 --- a/tasks/item/consumable_usage.py +++ b/tasks/item/consumable_usage.py @@ -1,5 +1,5 @@ from module.ocr.ocr import * -from module.ui.scroll import Scroll +from module.ui.scroll import AdaptiveScroll from tasks.base.assets.assets_base_popup import POPUP_CONFIRM from tasks.base.page import page_item from tasks.daily.assets.assets_daily_synthesize_consumable import \ @@ -54,7 +54,7 @@ class ConsumableUsageUI(ItemUI): # Determine if there is a scroll bar. If there is a scroll bar, # pull it down and check if the consumable to be used can be found - scroll = Scroll(area=ITEM_CONSUMABLE_SCROLL.button, color=(200, 200, 200), name=ITEM_CONSUMABLE_SCROLL.name) + scroll = AdaptiveScroll(area=ITEM_CONSUMABLE_SCROLL.button, name=ITEM_CONSUMABLE_SCROLL.name) if scroll.appear(main=self): if not scroll.at_top(main=self): scroll.set_top(main=self)