def _perform_template_matching(self, minimap): context_slice = self._get_scaled_context() context_coords = get_coords_from_slices(context_slice) template_match = cv2.matchTemplate( self.gray_map[context_slice], cv2.cvtColor(minimap, cv2.COLOR_RGB2GRAY), cv2.TM_CCOEFF_NORMED) # match is an array, the same shape as the context. Next, we must find the minimum value # in the array because we're using the TM_CCOEFF_NORMED matching method. if context_slice != slice(None, None, None): context_last_known = coordinate_sum( scale_coords(self.last_known_position, self.scale), [-x for x in context_coords]) x_rows = np.arange(template_match.shape[0]) - context_last_known[0] y_rows = np.arange(template_match.shape[0]) - context_last_known[1] x_grid, y_grid = np.meshgrid(x_rows, y_rows) match_adjustment = np.sqrt(np.sqrt(x_grid**2 + y_grid**2)) / 1000 template_match -= match_adjustment else: match_adjustment = None _, template_match_value, _, match_position = cv2.minMaxLoc( template_match) scaled_position = coordinate_sum(match_position, context_coords) scaled_position = coordinate_offset(scaled_position, self.minimap_iter.size // 2) if self.debug: self.__debug_context(match_position, context_slice) self.__debug_template_match(template_match, match_adjustment) self.__debug_land(scaled_position) return scaled_position, template_match_value
def _is_position_on_land(self, unscaled_position): on_land = False if unscaled_position: land_mask_coords = scale_coords(unscaled_position, self.land_mask_scale) on_land = bool(self.land_mask[land_mask_coords[1], land_mask_coords[0]]) return on_land
def __debug_land(self, scaled_position): land_debug = np.copy(self.land_mask) if scaled_position: unscaled_position = self._unscale_coords(scaled_position) on_land = self._is_position_on_land(unscaled_position) land_debug = cv2.cvtColor(land_debug, cv2.COLOR_GRAY2BGR) land_mask_coords = scale_coords(unscaled_position, self.land_mask_scale) cv2.circle(land_debug, land_mask_coords, 10, LAND() if on_land else WATER(), cv2.FILLED) cv2.imshow("land", land_debug) cv2.waitKey(10)
def _get_scaled_context(self): # Context defines the area that the template matching will be limited to. # This area gets larger each time a match is missed to account for movement processing. context_slice = slice(None) if self.last_known_position: max_reachable_dist = self._calculate_max_travel_distance() context_coords, context_size = find_path_bounds( self.gray_map.shape[0], [scale_coords(self.last_known_position, self.scale)], crop_border=0, min_size=max_reachable_dist) context_slice = create_slice(context_coords, context_size) return context_slice