예제 #1
0
    def get_ult_colors_from_image(self):
        """Get ultimate charge number colors from this frame.

        Author:
            Rigel

        Args:
            None

        Returns:
            @ult_color: array of int, -1: white number, 1: black number
        """
        left_pre_pos = OW.get_ult_charge_color_pre_pos(True)[self.game.game_type]
        left_pre_image = ImageUtils.rgb_to_gray(ImageUtils.crop(self.image, left_pre_pos))
        left_shear = ImageUtils.shear(left_pre_image, OW.get_tf_shear(True)[self.game.game_type])
        left_pos = OW.get_ult_charge_color_pos(True)[self.game.game_type]
        left_image = ImageUtils.crop(left_shear, left_pos)
        left_image_g = ImageUtils.contrast_adjust_log(left_image, OW.ULT_ADJUST_LOG_INDEX)
        left_bin = ImageUtils.binary_otsu(left_image_g)

        right_pre_pos = OW.get_ult_charge_color_pre_pos(False)[self.game.game_type]
        right_pre_image = ImageUtils.rgb_to_gray(ImageUtils.crop(self.image, right_pre_pos))
        right_shear = ImageUtils.shear(right_pre_image, OW.get_tf_shear(False)[self.game.game_type])
        right_pos = OW.get_ult_charge_color_pos(False)[self.game.game_type]
        right_image = ImageUtils.crop(right_shear, right_pos)
        right_image_g = ImageUtils.contrast_adjust_log(right_image, OW.ULT_ADJUST_LOG_INDEX)
        right_bin = ImageUtils.binary_otsu(right_image_g)
        return {
            "left": np.sign(2 * np.sum(left_bin) - np.size(left_bin)),
            "right": np.sign(2 * np.sum(right_bin) - np.size(right_bin))
        }
예제 #2
0
    def get_ult_status(self):
        """Retrieves ultimate statues info for current player in current frame.

        Author:
            Appcell

        Args:
            None

        Returns:
            None 
        """
        # Crop icon from current frame
        ult_icon_pos = OW.get_ult_icon_pos(
            self.index)[self.frame.game.game_type]
        ult_icon = ImageUtils.crop(self.image, ult_icon_pos)
        # Get reference icon image
        ult_icon_ref = OW.get_ult_icon_ref(
            self.index)[self.frame.game.game_type]
        # Tranfer both to grayscale for comparison
        ult_icon_ref, ult_icon = ImageUtils.rgb_to_gray(
            ult_icon_ref), ImageUtils.rgb_to_gray(ult_icon)

        # Compare cropped icon with reference, get the probability of them
        # being similar
        prob_map = cv2.matchTemplate(ult_icon, ult_icon_ref,
                                     cv2.TM_CCOEFF_NORMED)
        prob_map_cropped = prob_map[0:(ult_icon.shape[0] -
                                       ult_icon_ref.shape[0]), :]
        _, prob, _, loc = cv2.minMaxLoc(prob_map_cropped)

        # To avoid possible explosion effect.
        # When ult gets ready, brightness of icon goes above limit.
        brightness = np.mean(ult_icon)
        deviation = np.std(ult_icon)

        if brightness > OW.ULT_ICON_MAX_BRIGHTNESS[self.frame.game.game_type] \
            and deviation < OW.ULT_ICON_MAX_DEVIATION[self.frame.game.game_type]:
            prob = 1
            self.is_ult_ready = True
            return

        temp_ult_icon = ImageUtils.crop(
            ult_icon,
            [loc[1], ult_icon_ref.shape[0], loc[0], ult_icon_ref.shape[1]])
        prob_ssim = measure.compare_ssim(temp_ult_icon,
                                         ult_icon_ref,
                                         multichannel=False)

        if prob > OW.ULT_ICON_MAX_PROB[self.frame.game.game_type]:
            if prob_ssim > OW.ULT_ICON_MAX_PROB_SSIM[
                    self.frame.game.game_type]:
                self.is_ult_ready = True
예제 #3
0
def get_ability_icons_ref():
    """Read in all ability icons.

    Author:
        Appcell

    Args:
        None

    Returns:
        A dict of all ability icons, with chara names as keys and list of all
        abilities of this chara as values.
    """
    res_owl = {}
    res_custom = {}
    for (chara, ability_list) in ABILITY_LIST.iteritems():
        icons_list_owl = []
        icons_list_custom = []
        for i in ability_list:
            icon = ImageUtils.rgb_to_gray(
                ImageUtils.read("./images/abilities/" + chara + "/" + str(i) +
                                ".png"))
            icons_list_owl.append(
                ImageUtils.resize(icon, ABILITY_ICON_WIDTH[GAMETYPE_OWL],
                                  ABILITY_ICON_HEIGHT[GAMETYPE_OWL]))
            icons_list_custom.append(
                ImageUtils.resize(icon, ABILITY_ICON_WIDTH[GAMETYPE_CUSTOM],
                                  ABILITY_ICON_HEIGHT[GAMETYPE_CUSTOM]))
        res_owl[chara] = icons_list_owl
        res_custom[chara] = icons_list_custom

    return {GAMETYPE_OWL: res_owl, GAMETYPE_CUSTOM: res_custom}
예제 #4
0
    def get_ult_status(self):
        """Retrieves ultimate statues info for current player in current frame.

        Author:
            Appcell

        Args:
            None

        Returns:
            None 
        """
        # Crop icon from current frame
        ult_icon_pos = OW.get_ult_icon_pos(
            self.index)[self.frame.game.game_type]
        ult_icon = ImageUtils.crop(self.image, ult_icon_pos)
        # Get reference icon image
        ult_icon_ref = OW.get_ult_icon_ref(
            self.index)[self.frame.game.game_type]
        # Tranfer both to grayscale for comparison
        ult_icon_ref, ult_icon = ImageUtils.rgb_to_gray(
            ult_icon_ref), ImageUtils.rgb_to_gray(ult_icon)

        # Compare cropped icon with reference, get the probability of them
        # being similar
        prob = cv2.matchTemplate(ult_icon, ult_icon_ref,
                                 cv2.TM_CCOEFF_NORMED).max()

        # To avoid possible explosion effect.
        # When ult gets ready, brightness of icon goes above limit.
        brightness = np.mean(ult_icon)

        if brightness > OW.ULT_ICON_MAX_BRIGHTNESS[self.frame.game.game_type]:
            prob = 1

        if prob > OW.ULT_ICON_MAX_PROB[self.frame.game.game_type]:
            self.is_ult_ready = True
예제 #5
0
    def get_ult_charge(self):
        """Retrieves ultimate charge for current player.

        Author:

        Args:
            None

        Returns:
            None
        """
        if self.is_ult_ready:
            self.ult_charge = 100
            return
        if self.is_dead:
            return

        ult_charge_pre_pos = OW.get_ult_charge_pre_pos(
            self.index)[self.frame.game.game_type]
        ult_charge_pre_image = ImageUtils.rgb_to_gray(
            ImageUtils.crop(self.image, ult_charge_pre_pos))

        ult_charge_shear = ImageUtils.shear(
            ult_charge_pre_image,
            OW.get_tf_shear(self.index)[self.frame.game.game_type])

        ult_charges = [0, 0]

        # Here's another thought: we need to find the gap more intellectually,
        # not relying only on fixed position.
        # In detail, after shearing, find the gap by telling if there are more
        # than 2 colors in same column.
        ult_charge_image = ImageUtils.crop(
            ult_charge_shear,
            OW.get_ult_charge_pos(self.index)[self.frame.game.game_type])

        # TODO: I see there's no difference at all of brightness deviation!!
        # Our contrast adjusting must be seriously problematic. For grayscale
        # img, a simple normalization based on std would do.
        # ult_charge_image_g = ImageUtils.contrast_adjust_log(
        #     ult_charge_image, OW.ULT_ADJUST_LOG_INDEX)
        ult_charge_image_g = ImageUtils.normalize_gray(ult_charge_image)

        # tell if player is observed (more accurate than previous)
        # Here I use another local variable flag_observed, since the global one
        # might be inaccurate
        flag_observed = False
        deviation_row = ult_charge_image_g.max(
            axis=1) - ult_charge_image_g.min(axis=1)
        if deviation_row[2] - deviation_row[0] > \
            OW.ULT_GAP_DEVIATION_LIMIT[self.frame.game.game_type]:
            self.is_observed = True
            flag_observed = True

        # If current player is observed, there's a white dot on right side
        # needs to be removed.
        # TODO: write this into ow.py as well
        if flag_observed is True:
            ult_charge_image_g = ImageUtils.crop(ult_charge_image_g, [
                0, ult_charge_image_g.shape[0], 0,
                ult_charge_image_g.shape[1] - 5
            ])
        width = ult_charge_image_g.shape[1]
        height = ult_charge_image_g.shape[0]

        # Find the gap
        deviation = ult_charge_image_g.max(axis=0) - ult_charge_image_g.min(
            axis=0)
        gap = -1
        for i in range(width - 4, 3, -1):
            if deviation[i-3] - deviation[i] \
                > OW.ULT_GAP_DEVIATION_LIMIT[self.frame.game.game_type] \
                and deviation[i+3] - deviation[i] \
                > OW.ULT_GAP_DEVIATION_LIMIT[self.frame.game.game_type]:
                gap = i
                break

        bg_color = ult_charge_image_g[:, 0].mean()

        if bg_color < 0.6:
            # Dark background
            ult_charge_image_g = ImageUtils.inverse_gray(ult_charge_image_g)
        # No need to switch to BW here.

        if gap == -1:
            # Only one digit
            num = ImageUtils.remove_digit_vertical_edge(
                ult_charge_image_g,
                OW.ULT_GAP_DEVIATION_LIMIT[self.frame.game.game_type],
                ImageUtils.REMOVE_NUMBER_VERTICAL_EDGE_BOTH)
        else:
            # 2 digits
            num_left = ImageUtils.crop(
                ult_charge_image_g,
                [0, ult_charge_image_g.shape[0], 0, gap + 1])
            num_right = ImageUtils.crop(ult_charge_image_g, [
                0, ult_charge_image_g.shape[0], gap,
                ult_charge_image_g.shape[1] - gap
            ])

            if flag_observed is True:
                num_left = ImageUtils.crop(
                    num_left,
                    [0, num_left.shape[0], num_left.shape[1] \
                        - OW.ULT_CHARGE_NUMBER_WIDTH_OBSERVED[self.frame.game.game_type] - 1,
                     OW.ULT_CHARGE_NUMBER_WIDTH_OBSERVED[self.frame.game.game_type]])
                num_right = ImageUtils.crop(num_right, [
                    0, num_left.shape[0], 0, OW.
                    ULT_CHARGE_NUMBER_WIDTH_OBSERVED[self.frame.game.game_type]
                ])
            else:
                num_left = ImageUtils.crop(
                    num_left,
                    [0, num_left.shape[0], num_left.shape[1] \
                        - OW.ULT_CHARGE_NUMBER_WIDTH_OBSERVED[self.frame.game.game_type] - 1,
                     OW.ULT_CHARGE_NUMBER_WIDTH_OBSERVED[self.frame.game.game_type]])
                num_right = ImageUtils.crop(num_right, [
                    0, num_left.shape[0], 0, OW.
                    ULT_CHARGE_NUMBER_WIDTH_OBSERVED[self.frame.game.game_type]
                ])

            # if self.index == 5:
            #     cv2.imshow('t1', num_left)
            #     cv2.waitKey(0)
            #     cv2.imshow('t2', num_right)
            #     cv2.waitKey(0)
            # Since when cropping img we also included the slope on left side,
            # num_left could actually be empty
            # Also we need another recognition method. Simple MSE wouldn't work due to error.

        # ult_charge_image_g = ImageUtils.contrast_adjust_log(
        #     ult_charge_image, OW.ULT_ADJUST_LOG_INDEX)

        # for i in (0,1):

        #     cv2.imshow('t', ult_charge_image)
        #     cv2.waitKey(0)
        #     try:
        #         ult_charge_image_binary = ImageUtils.binary_otsu(ult_charge_image_g)

        #     except ValueError:
        #         self.ult_charge = None
        #         return
        #     ult_charge_similarities = np.zeros(11)
        #     for j in range(1 - i, 11-i):
        #         # 1st number can't be 0, 2nd number can't be empty
        #         ult_charge_ref = self.frame.game.ult_charge_numbers_ref[j - i]
        #         ult_charge_similarities[j] = ImageUtils.similarity(ult_charge_ref, ult_charge_image_binary)
        #     ult_charges[i] = np.argmax(ult_charge_similarities)
        #     print ult_charges[i]
        #     if ult_charges[i] == 10:
        #         ult_charges[i] = 0

        self.ult_charge = ult_charges[0] * 10 + ult_charges[1]
        return