Chore: Rename "threshold" in template matching to "similarity"

to be differ from the "threshold" in color matching
This commit is contained in:
LmeSzinc 2024-12-09 15:20:34 +08:00
parent 40b3c252dc
commit 164db6f4da
10 changed files with 44 additions and 46 deletions

View File

@ -124,14 +124,14 @@ class ModuleBase:
return button
def appear(self, button, offset=0, interval=0, threshold=None):
def appear(self, button, offset=0, interval=0, similarity=0.85, threshold=30):
"""
Args:
button (Button, Template, HierarchyButton, str):
offset (bool, int):
interval (int, float): interval between two active events.
threshold (int, float): 0 to 1 if use offset, bigger means more similar,
0 to 255 if not use offset, smaller means more similar
similarity (int, float): 0 to 1.
threshold (int, float): 0 to 255 if not use offset, smaller means more similar
Returns:
bool:
@ -167,20 +167,19 @@ class ModuleBase:
elif offset:
if isinstance(offset, bool):
offset = self.config.BUTTON_OFFSET
appear = button.match(self.device.image, offset=offset,
threshold=self.config.BUTTON_MATCH_SIMILARITY if threshold is None else threshold)
appear = button.match(self.device.image, offset=offset, similarity=similarity)
else:
appear = button.appear_on(self.device.image,
threshold=self.config.COLOR_SIMILAR_THRESHOLD if threshold is None else threshold)
appear = button.appear_on(self.device.image, threshold=threshold)
if appear and interval:
self.interval_timer[button.name].reset()
return appear
def appear_then_click(self, button, screenshot=False, genre='items', offset=0, interval=0, threshold=None):
def appear_then_click(self, button, screenshot=False, genre='items', offset=0, interval=0, similarity=0.85,
threshold=30):
button = self.ensure_button(button)
appear = self.appear(button, offset=offset, interval=interval, threshold=threshold)
appear = self.appear(button, offset=offset, interval=interval, similarity=similarity, threshold=threshold)
if appear:
if screenshot:
self.device.sleep(self.config.WAIT_BEFORE_SAVING_SCREEN_SHOT)

View File

@ -198,13 +198,13 @@ class Button(Resource):
self._match_binary_init = False
self._match_luma_init = False
def match(self, image, offset=30, threshold=0.85):
def match(self, image, offset=30, similarity=0.85):
"""Detects button by template matching. To Some button, its location may not be static.
Args:
image: Screenshot.
offset (int, tuple): Detection area offset.
threshold (float): 0-1. Similarity.
similarity (float): 0-1. Similarity.
Returns:
bool.
@ -223,25 +223,25 @@ class Button(Resource):
if self.is_gif:
for template in self.image:
res = cv2.matchTemplate(template, image, cv2.TM_CCOEFF_NORMED)
_, similarity, _, point = cv2.minMaxLoc(res)
_, sim, _, point = cv2.minMaxLoc(res)
self._button_offset = area_offset(self._button, offset[:2] + np.array(point))
if similarity > threshold:
if sim > similarity:
return True
return False
else:
res = cv2.matchTemplate(self.image, image, cv2.TM_CCOEFF_NORMED)
_, similarity, _, point = cv2.minMaxLoc(res)
_, sim, _, point = cv2.minMaxLoc(res)
self._button_offset = area_offset(self._button, offset[:2] + np.array(point))
return similarity > threshold
return sim > similarity
def match_binary(self, image, offset=30, threshold=0.85):
def match_binary(self, image, offset=30, similarity=0.85):
"""Detects button by template matching. To Some button, its location may not be static.
This method will apply template matching under binarization.
Args:
image: Screenshot.
offset (int, tuple): Detection area offset.
threshold (float): 0-1. Similarity.
similarity (float): 0-1. Similarity.
Returns:
bool.
@ -266,9 +266,9 @@ class Button(Resource):
_, image_binary = cv2.threshold(image_gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
# template matching
res = cv2.matchTemplate(template, image_binary, cv2.TM_CCOEFF_NORMED)
_, similarity, _, point = cv2.minMaxLoc(res)
_, sim, _, point = cv2.minMaxLoc(res)
self._button_offset = area_offset(self._button, offset[:2] + np.array(point))
if similarity > threshold:
if sim > similarity:
return True
return False
else:
@ -278,18 +278,18 @@ class Button(Resource):
_, image_binary = cv2.threshold(image_gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
# template matching
res = cv2.matchTemplate(self.image_binary, image_binary, cv2.TM_CCOEFF_NORMED)
_, similarity, _, point = cv2.minMaxLoc(res)
_, sim, _, point = cv2.minMaxLoc(res)
self._button_offset = area_offset(self._button, offset[:2] + np.array(point))
return similarity > threshold
return sim > similarity
def match_luma(self, image, offset=30, threshold=0.85):
def match_luma(self, image, offset=30, similarity=0.85):
"""
Detects button by template matching under Y channel (Luminance)
Args:
image: Screenshot.
offset (int, tuple): Detection area offset.
threshold (float): 0-1. Similarity.
similarity (float): 0-1. Similarity.
Returns:
bool.
@ -310,16 +310,16 @@ class Button(Resource):
image_luma = rgb2luma(image)
for template in self.image_luma:
res = cv2.matchTemplate(template, image_luma, cv2.TM_CCOEFF_NORMED)
_, similarity, _, point = cv2.minMaxLoc(res)
_, sim, _, point = cv2.minMaxLoc(res)
self._button_offset = area_offset(self._button, offset[:2] + np.array(point))
if similarity > threshold:
if sim > similarity:
return True
else:
image_luma = rgb2luma(image)
res = cv2.matchTemplate(self.image_luma, image_luma, cv2.TM_CCOEFF_NORMED)
_, similarity, _, point = cv2.minMaxLoc(res)
_, sim, _, point = cv2.minMaxLoc(res)
self._button_offset = area_offset(self._button, offset[:2] + np.array(point))
return similarity > threshold
return sim > similarity
def match_appear_on(self, image, threshold=30):
"""

View File

@ -39,9 +39,7 @@ class ManualConfig:
"""
module.base
"""
COLOR_SIMILAR_THRESHOLD = 10
BUTTON_OFFSET = 30
BUTTON_MATCH_SIMILARITY = 0.85
WAIT_BEFORE_SAVING_SCREEN_SHOT = 1
"""

View File

@ -332,11 +332,11 @@ class GridPredictor:
color = cv2.mean(crop(mask.image, area=np.rint(area).astype(int), copy=False))
return color[0] > 235
def is_similar_to(self, grid, threshold=0.9):
def is_similar_to(self, grid, similarity=0.9):
"""
Args:
grid (GridPredictor): Another Grid instance.
threshold (float): 0 to 1.
similarity (float): 0 to 1.
Returns:
bool: If current grid is similar to another.
@ -346,5 +346,5 @@ class GridPredictor:
piece_1 = self._image_similar_piece
piece_2 = grid._image_similar_full
res = cv2.matchTemplate(piece_2, piece_1, cv2.TM_CCOEFF_NORMED)
_, similarity, _, point = cv2.minMaxLoc(res)
return similarity > threshold
_, sim, _, point = cv2.minMaxLoc(res)
return sim > similarity

View File

@ -117,7 +117,7 @@ class DossierReward(Combat, UI):
in: dossier meta page
"""
self.device.screenshot()
if self.appear(DOSSIER_REWARD_RECEIVE, offset=(-40, 10, -10, 40), threshold=0.7):
if self.appear(DOSSIER_REWARD_RECEIVE, offset=(-40, 10, -10, 40), similarity=0.7):
logger.info('Found dossier reward red dot')
return True
else:

View File

@ -29,7 +29,7 @@ class FleetSelector:
int: Index of current fleet, 1 to 4. return 0 if unrecognized.
"""
for index, button in enumerate([FLEET_1, FLEET_2, FLEET_3, FLEET_4]):
if self.main.appear(button, offset=(20, 20), threshold=0.75):
if self.main.appear(button, offset=(20, 20), similarity=0.75):
return index + 1
logger.info('Unknown OpSi fleet')

View File

@ -104,7 +104,7 @@ class StrategicSearchHandler(MapEventHandler):
else:
self.device.screenshot()
self.appear(STRATEGIC_SEARCH_DEVICE_CHECK, offset=(20, 200), threshold=0.7)
self.appear(STRATEGIC_SEARCH_DEVICE_CHECK, offset=(20, 200), similarity=0.7)
STRATEGIC_SEARCH_DEVICE_STOP.load_offset(STRATEGIC_SEARCH_DEVICE_CHECK)
STRATEGIC_SEARCH_DEVICE_CONTINUE.load_offset(STRATEGIC_SEARCH_DEVICE_CHECK)
@ -129,7 +129,7 @@ class StrategicSearchHandler(MapEventHandler):
else:
self.device.screenshot()
self.appear(STRATEGIC_SEARCH_SUBMIT_CHECK, offset=(20, 20), threshold=0.7)
self.appear(STRATEGIC_SEARCH_SUBMIT_CHECK, offset=(20, 20), similarity=0.7)
STRATEGIC_SEARCH_SUBMIT_OFF.load_offset(STRATEGIC_SEARCH_SUBMIT_CHECK)
STRATEGIC_SEARCH_SUBMIT_ON.load_offset(STRATEGIC_SEARCH_SUBMIT_CHECK)

View File

@ -180,14 +180,14 @@ def parse_time(string):
return timedelta(hours=result[0], minutes=result[1], seconds=result[2])
def match_template(image, template, area, offset=30, threshold=0.85):
def match_template(image, template, area, offset=30, similarity=0.85):
"""
Args:
image (np.ndarray): Screenshot
template (np.ndarray):
area (tuple): Crop area of image.
offset (int, tuple): Detection area offset.
threshold (float): 0-1. Similarity. Lower than this value will return float(0).
similarity (float): 0-1. Similarity. Lower than this value will return float(0).
Returns:
similarity (float):
"""
@ -198,8 +198,9 @@ def match_template(image, template, area, offset=30, threshold=0.85):
image = crop(image, offset + area, copy=False)
res = cv2.matchTemplate(image, template, cv2.TM_CCOEFF_NORMED)
_, sim, _, point = cv2.minMaxLoc(res)
similarity = sim if sim >= threshold else 0.0
return similarity
if sim < similarity:
sim = 0.0
return sim
def get_research_series_jp_old(image):
@ -274,7 +275,7 @@ def get_research_genre_jp(image):
"""
genre = ''
for button in RESEARCH_DETAIL_GENRE:
if button.match(image, offset=(30, 20), threshold=0.9):
if button.match(image, offset=(30, 20), similarity=0.9):
# DETAIL_GENRE_H_0.name.split("_")[2] == 'H'
genre = button.name.split("_")[2]
break
@ -308,7 +309,7 @@ def get_research_cost_jp(image):
template=template,
area=DETAIL_COST.area,
offset=(10, 10),
threshold=0.8)
similarity=0.8)
if not sim:
continue
for cost in costs:
@ -343,7 +344,7 @@ def get_research_ship_jp(image):
template=load_image(template),
area=DETAIL_BLUEPRINT.area,
offset=(10, 10),
threshold=0.9)
similarity=0.9)
if sim > similarity:
similarity = sim
ship = name

View File

@ -462,7 +462,7 @@ class Retirement(Enhancement, QuickRetireSettingHandler):
self.device.screenshot()
# End
if not self.appear(RETIRE_COIN, threshold=0.97):
if not self.appear(RETIRE_COIN, similarity=0.97):
return True
if count > 3:
logger.warning('_retire_select_one failed after 3 trial')

View File

@ -477,7 +477,7 @@ class UI(InfoHandler):
return True
# Dorm popup
if self.appear(DORM_INFO, offset=(30, 30), threshold=0.75, interval=3):
if self.appear(DORM_INFO, offset=(30, 30), similarity=0.75, interval=3):
self.device.click(DORM_INFO)
return True
if self.appear_then_click(DORM_FEED_CANCEL, offset=(30, 30), interval=3):