Example #1
0
    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')
Example #2
0
    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
Example #3
0
    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))