Speed up template pathing (#226)

* Speed up template pathing

* change comment
This commit is contained in:
aeon0
2021-12-07 12:14:50 +01:00
committed by GitHub
parent 19af63f965
commit 9644e7a36e
3 changed files with 42 additions and 26 deletions
+5 -5
View File
@@ -28,8 +28,8 @@ class IChar:
self._screen = screen
self._config = Config()
self._last_tp = time.time()
# It actually is 0.04s per frame but many people have issues with it (because of lag?)
self._cast_duration = self._char_config["casting_frames"] * 0.05 + 0.04
# Add a bit to be on the save side
self._cast_duration = self._char_config["casting_frames"] * 0.04 + 0.01
def can_teleport(self) -> bool:
return bool(self._skill_hotkeys["teleport"])
@@ -82,7 +82,7 @@ class IChar:
mouse.move(pos_monitor[0], pos_monitor[1], randomize=3, delay_factor=[factor*0.1, factor*0.14])
wait(0.012, 0.02)
mouse.click(button="right")
wait(self._cast_duration, self._cast_duration + 0.03)
wait(self._cast_duration, self._cast_duration + 0.02)
else:
# in case we want to walk we actually want to move a bit before the point cause d2r will always "overwalk"
pos_screen = self._screen.convert_monitor_to_screen(pos_monitor)
@@ -140,11 +140,11 @@ class IChar:
keyboard.send(self._char_config["battle_command"])
wait(0.08, 0.19)
mouse.click(button="right")
wait(self._cast_duration + 0.08, self._cast_duration + 0.1)
wait(self._cast_duration + 0.13, self._cast_duration + 0.16)
keyboard.send(self._char_config["battle_orders"])
wait(0.08, 0.19)
mouse.click(button="right")
wait(self._cast_duration + 0.08, self._cast_duration + 0.1)
wait(self._cast_duration + 0.13, self._cast_duration + 0.16)
keyboard.send(self._char_config["weapon_switch"])
wait(0.3, 0.35)
# Make sure that we are back at the previous skill
+13 -11
View File
@@ -92,15 +92,15 @@ class Pather:
122: {'ELDRITCH_2': (353, -145), 'ELDRITCH_3': (-149, -119)},
123: {'ELDRITCH_3': (-99, -252), 'ELDRITCH_2': (403, -279), 'ELDRITCH_4': (-62, -109)},
# Shenk
140: {'SHENK_0': (-149, -227), 'SHENK_17': (-500, 235), 'SHENK_15': (80, 13), 'SHENK_1': (445, -161)},
141: {'SHENK_0': (-129, 44), 'SHENK_17': (-520, 528), 'SHENK_15': (77, 293), 'SHENK_1': (464, 107), 'SHENK_2': (-167, -34)},
142: {'SHENK_1': (584, 376), 'SHENK_2': (-52, 235), 'SHENK_3': (357, -129), 'SHENK_4': (-443, -103)},
143: {'SHENK_2': (141, 505), 'SHENK_3': (549, 139), 'SHENK_4': (-251, 165), 'SHENK_6': (-339, -69)},
144: {'SHENK_6': (-108, 123), 'SHENK_7': (481, 151)},
145: {'SHENK_12': (97, -133), 'SHENK_7': (803, 372), 'SHENK_6': (209, 347), 'SHENK_8': (-245, 18)},
146: {'SHENK_12': (272, 111), 'SHENK_9': (-331, -144), 'SHENK_8': (-72, 258)},
147: {'SHENK_16': (317, -18), 'SHENK_9': (-67, 139), 'SHENK_10': (-431, 67)},
148: {'SHENK_16': (682, 103), 'SHENK_9': (301, 263), 'SHENK_10': (-65, 188), 'SHENK_11': (-306, 139)},
140: {'SHENK_0': (-149, -227), 'SHENK_1': (445, -161), 'SHENK_17': (-500, 235), 'SHENK_15': (80, 13)},
141: {'SHENK_0': (-129, 44), 'SHENK_1': (464, 107), 'SHENK_2': (-167, -34), 'SHENK_17': (-520, 528), 'SHENK_15': (77, 293)},
142: {'SHENK_1': (584, 376), 'SHENK_4': (-443, -103), 'SHENK_2': (-52, 235), 'SHENK_3': (357, -129)},
143: {'SHENK_4': (-251, 165), 'SHENK_2': (141, 505), 'SHENK_3': (549, 139), 'SHENK_6': (-339, -69)},
144: {'SHENK_6': (-108, 123), 'SHENK_7': (481, 151)},
145: {'SHENK_7': (803, 372), 'SHENK_12': (97, -133), 'SHENK_6': (209, 347), 'SHENK_8': (-245, 18)},
146: {'SHENK_12': (272, 111), 'SHENK_9': (-331, -144), 'SHENK_8': (-72, 258)},
147: {'SHENK_16': (317, -18), 'SHENK_9': (-67, 139), 'SHENK_10': (-431, 67)},
148: {'SHENK_16': (682, 103), 'SHENK_9': (301, 263), 'SHENK_10': (-65, 188), 'SHENK_11': (-306, 139)},
149: {'SHENK_11': (261, 395), 'SHENK_10': (495, 421), 'SHENK_13': (393, -9)},
# A4 town
160: {"A4_TOWN_4": (-100, -133), "A4_TOWN_3": (-117, 238), "A4_TOWN_0": (-364, 151), "A4_TOWN_6": (24, -425), "A4_TOWN_5": (-347, -277)},
@@ -236,7 +236,7 @@ class Pather:
def find_abs_node_pos(self, node_idx: int, img: np.ndarray) -> Tuple[float, float]:
node = self._nodes[node_idx]
template_match = self._template_finder.search([*node], img, best_match=False)
template_match = self._template_finder.search([*node], img, best_match=False, roi=self._config.ui_roi["cut_skill_bar"], use_grayscale=True)
if template_match.valid:
# Get reference position of template in abs coordinates
ref_pos_abs = self._screen.convert_screen_to_abs(template_match.position)
@@ -378,5 +378,7 @@ if __name__ == "__main__":
char = Hammerdin(config.hammerdin, config.char, screen, t_finder, ui_manager, pather)
# pather.traverse_nodes_fixed("pindle_save_dist", char)
# pather.traverse_nodes(Location.A3_TRAV_START, Location.A3_TRAV_SAVE_DIST, char)
pather.traverse_nodes(Location.A3_TOWN_START, Location.A3_STASH_WP, char)
t = time.time()
pather.traverse_nodes(Location.A5_SHENK_START, Location.A5_SHENK_SAVE_DIST, char)
print(time.time()-t)
# display_all_nodes(pather, filter="TRAV")
+24 -10
View File
@@ -37,7 +37,12 @@ class TemplateFinder:
key = file_name[:-4].upper()
template_img = load_template(file_path, 1.0, True)
mask = alpha_to_mask(template_img)
self._templates[key] = [cv2.cvtColor(template_img, cv2.COLOR_BGRA2BGR), 1.0, mask]
self._templates[key] = [
cv2.cvtColor(template_img,cv2.COLOR_BGRA2BGR),
cv2.cvtColor(template_img,cv2.COLOR_BGRA2GRAY),
1.0,
mask
]
def get_template(self, key):
return cv2.cvtColor(self._templates[key][0], cv2.COLOR_BGRA2BGR)
@@ -49,7 +54,8 @@ class TemplateFinder:
threshold: float = None,
roi: List[float] = None,
normalize_monitor: bool = False,
best_match: bool = False
best_match: bool = False,
use_grayscale: bool = False,
) -> TemplateMatch:
"""
Search for a template in an image
@@ -59,6 +65,7 @@ class TemplateFinder:
:param roi: Region of Interest of the inp_img to restrict search area. Format [left, top, width, height]
:param normalize_monitor: If True will return positions in monitor coordinates. Otherwise in coordinates of the input image.
:param best_match: If list input, will search for list of templates by best match. Default behavior is first match.
:param use_grayscale: Use grayscale template matching for speed up
:return: Returns a TempalteMatch object with a valid flag
"""
threshold = self._config.advanced_options["template_threshold"] if threshold is None else threshold
@@ -70,17 +77,20 @@ class TemplateFinder:
if type(ref) == str:
templates = [self._templates[ref][0]]
scales = [self._templates[ref][1]]
masks = [self._templates[ref][2]]
templates_gray = [self._templates[ref][1]]
scales = [self._templates[ref][2]]
masks = [self._templates[ref][3]]
names = [ref]
best_match = False
elif type(ref) == list:
templates = [self._templates[i][0] for i in ref]
scales = [self._templates[i][1] for i in ref]
masks = [self._templates[i][2] for i in ref]
templates_gray = [self._templates[i][1] for i in ref]
scales = [self._templates[i][2] for i in ref]
masks = [self._templates[i][3] for i in ref]
names = ref
else:
templates = [ref]
templates_gray = [cv2.cvtColor(ref, cv2.COLOR_BGRA2GRAY)]
scales = [1.0]
masks = [None]
best_match = False
@@ -99,6 +109,9 @@ class TemplateFinder:
rh *= scale
if img.shape[0] > template.shape[0] and img.shape[1] > template.shape[1]:
if use_grayscale:
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
template = templates_gray[count]
self.last_res = cv2.matchTemplate(img, template, cv2.TM_CCOEFF_NORMED, mask=mask)
np.nan_to_num(self.last_res, copy=False, nan=0.0, posinf=0.0, neginf=0.0)
_, max_val, _, max_pos = cv2.minMaxLoc(self.last_res)
@@ -137,7 +150,8 @@ class TemplateFinder:
time_out: float = None,
threshold: float = None,
best_match: bool = False,
take_ss: bool = True
take_ss: bool = True,
use_grayscale: bool = False
) -> TemplateMatch:
"""
Helper function that will loop and keep searching for a template
@@ -152,7 +166,7 @@ class TemplateFinder:
start = time.time()
while 1:
img = self._screen.grab()
template_match = self.search(ref, img, roi=roi, threshold=threshold, best_match=best_match)
template_match = self.search(ref, img, roi=roi, threshold=threshold, best_match=best_match, use_grayscale=use_grayscale)
is_loading_black_roi = np.average(img[:, 0:self._config.ui_roi["loading_left_black"][2]]) < 1.0
if not is_loading_black_roi or "LOADING" in ref:
if template_match.valid:
@@ -172,14 +186,14 @@ if __name__ == "__main__":
config = Config()
screen = Screen(config.general["monitor"])
template_finder = TemplateFinder(screen)
search_templates = ["TP_ACTIVE", "TP_INACTIVE"]
search_templates = ["A3_TOWN_1"]
while 1:
# img = cv2.imread("")
img = screen.grab()
display_img = img.copy()
start = time.time()
for key in search_templates:
template_match = template_finder.search(key, img, best_match=True, threshold=0.35)
template_match = template_finder.search(key, img, best_match=True, threshold=0.35, use_grayscale=True)
if template_match.valid:
cv2.putText(display_img, str(template_match.name), template_match.position, cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2, cv2.LINE_AA)
cv2.circle(display_img, template_match.position, 7, (255, 0, 0), thickness=5)