def _preprocess_ability_icon(self, icon): """Preprocess an ability icon cut from frame. Main idea here is to find color of icon first. Color of ability icon is same as of arrow icon on right side. Given color, remove all parts with different colors. Author: Appcell Args: None Returns: None """ ability_pos = OW.get_ability_icon_pos(self.player2['pos'])[self.game_type] color = self.image_with_gap[ability_pos[ 0] + ability_pos[1]/2, ability_pos[2] + ability_pos[3] + 6] filtered_icon = np.zeros((icon.shape[0], icon.shape[1])) # TODO: Labelling needed here!!! Especially when background looks # similar to foreground. # TODO: There must be a better way for this for i in range(icon.shape[0]): for j in range(icon.shape[1]): if ImageUtils.color_distance(icon[i, j, :], color) \ < OW.ABILITY_ICON_COLOR_FILTER_THRESHOLD[self.game_type]: filtered_icon[i, j] = 255 return filtered_icon.astype('uint8')
def get_headshot(self): """Tell if elimination comes with a headshot. Author: Appcell Args: None Returns: None """ ability_pos = OW.get_ability_icon_pos(self.player2['pos'])[self.game_type] color = self.image_with_gap[ability_pos[ 0] + ability_pos[1]/2, ability_pos[2] + ability_pos[3] + 6] # TODO: Write consts here into ow.py if ImageUtils.color_distance(color, np.array([255, 255, 255])) > 40: self.is_headshot = True
def get_ability_and_assists(self): """Retrieve info of ability and assisting players in a row If distance between 2 avatar icons, width of arrow icon removed, is not divisible by width of an assist icon, then an ability icon must exist somewhere. Cut it off and compare with all possible ability icons to find the best match. After removing ability icon & arrow icon, what's left between 2 avatars must be n assist icons. Cut each from killfeed image, and then compare with references. Pick the one with maximum score as result. All results are written into self.ability and self.assists. Author: Appcell Args: None Returns: None """ if self.player1['pos'] == -1 or self.player2['pos'] == -1: return distance = self.player2[ 'pos'] - self.player1['pos'] - OW.KILLFEED_ICON_WIDTH[self.game_type] gap = ImageUtils.crop( self.image_with_gap, [0, self.image_with_gap.shape[0], self.player1['pos'], distance]) ability_icon = ImageUtils.crop( self.image_with_gap, OW.get_ability_icon_pos(self.player2['pos'])[self.game_type]) # Error gets too much with lowQ videos. Use edge detection instead. # Honestly it's not the best choice, since for non-OWL videos it # doesn't work anymore. But again, for non-OWL videos we expect a # better resolution. edge_image = cv2.Canny(self.image, 100, 200) # Get the "spanned" edge image. roi_x_min = self.player1['pos'] + OW.KILLFEED_ICON_WIDTH[self.game_type] + 4 roi_x_max = self.player2['pos'] - OW.ABILITY_GAP_NORMAL[self.game_type] if roi_x_max - roi_x_min < OW.ASSIST_GAP[self.game_type]: return edge_span = (np.sum(edge_image, 0) / 255)[roi_x_min:roi_x_max] edges = list(filter( lambda i: edge_span[i] >= self.image.shape[0] * 0.7, range(0, roi_x_max - roi_x_min))) if not edges: # Assist avatar doesn't exist return edge = edges[-1] # The end of assist avatars list assist_num = int(round(float(edge) / OW.ASSIST_GAP[self.game_type])) ability_list = OW.ABILITY_LIST[self.player1['chara']] ability_icons_ref = self.frame.game.ability_icons_ref[ self.player1['chara']] if (distance - OW.ABILITY_GAP_NORMAL[self.game_type]) % OW.ASSIST_GAP[self.game_type] > 5: # Has ability icon max_prob = -10 for (ind, ability_index) in enumerate(ability_list): filtered_icon = self._preprocess_ability_icon(ability_icon) score = measure.compare_ssim( filtered_icon, ability_icons_ref[ind], multichannel=True) if score > max_prob: max_prob = score self.ability = ability_index if max_prob < 0.1 and self.player1['chara'] == OW.GENJI: self.ability = OW.ABILITY_E for i in range(assist_num): # TODO: write this into ow.py! assist_icon = ImageUtils.crop( self.image, [ OW.ABILITY_ICON_Y_MIN[self.game_type], OW.ASSIST_ICON_HEIGHT[self.game_type], 8 + self.player1['pos'] + i * OW.ASSIST_GAP[self.game_type] \ + OW.KILLFEED_ICON_WIDTH[self.game_type], OW.ASSIST_ICON_WIDTH[self.game_type]]) assist = { "chara": "empty", "player": "empty", "team": self.player1['team'] } max_score = -10 for (chara, icon) in self.frame.game.assist_icons_ref.iteritems(): score = measure.compare_ssim(assist_icon, icon, multichannel=True) if score > max_score: max_score = score assist['chara'] = chara self.assists.append(self._set_assist_info(assist))