def step_impl(context, switch):
    assert switch == "on" or switch == "off"
    press(context, keys.KEY_DOWN, 1)  # to show progress bar
    cam = context.cam
    context.frame = get_frame_name(context, f"{WORK_DIR}/_frame.png")
    assert 200 == cam.get_frame(context.frame)
    region = REGION_PROGRESS_BAR
    frame = cv2.imread(context.frame)
    mp = (3, 0.8, *get_default_match_parameter()[2::]
          )  # use ccorr_normed method 0 and threshold =0.65

    if switch == "off":
        debug(f"match {playback_soft_buttons['cc off unhilite'][1]}")
        if match(frame,
                 cv2.imread(playback_soft_buttons["cc off unhilite"][1]),
                 region,
                 match_parameter=mp)[0] is True:
            debug(f"closed caption is already {switch}\n\n")
            return
    elif switch == 'on':
        debug(f"match {playback_soft_buttons['cc on unhilite'][1]}")
        if match(frame,
                 cv2.imread(playback_soft_buttons["cc on unhilite"][1]),
                 region,
                 match_parameter=mp)[0] is True:
            debug(f"closed caption is already {switch}")
            return
    debug(f"navigate_to {switch}\n\n")
    if navigate_to(context, "cc on" if switch == "off" else "cc off"):
        press(context, keys.KEY_SELECT, 1)
        # press(context, keys.KEY_UP, 1)
        press(context, keys.KEY_SELECT, 1)
        return
    assert False, f"fail to switch {switch} closed caption"
def step_impl(context):
    press(context, keys.KEY_DOWN, 1)  # to show progress bar
    cam = context.cam
    context.frame = get_frame_name(context, f"{WORK_DIR}/_frame.png")
    assert 200 == cam.get_frame(context.frame)
    frame = cv2.imread(context.frame)
    mp = (0, 0.8, *get_default_match_parameter()[2::]
          )  # use ccorr_normed method 0 and threshold =0.65

    video_quality = "None"
    result = 0.0
    assert os.path.exists(playback_soft_buttons["play off unhilitefamily"][1])
    found = match(frame,
                  cv2.imread(
                      playback_soft_buttons['family play off unhilite'][1]),
                  REGION_PROGRESS_BAR,
                  match_parameter=mp)
    if found[0] is True:
        debug(f"found family play off\n")
        return
    assert os.path.exists(playback_soft_buttons["family play on unhilite"][1])
    found = match(frame,
                  cv2.imread(
                      playback_soft_buttons['family play on unhilite'][1]),
                  REGION_PROGRESS_BAR,
                  match_parameter=mp)
    if found[0] is True:
        debug(f"found family play on\n")
        return
    debug(f"fail to find family play on the progress barn\n")
    assert False, "fail to find family play on the progress bar"
def find_video_quality_on_progress_bar(context):
    cam = context.cam
    context.frame = get_frame_name(context, f"{WORK_DIR}/_frame.png")
    assert 200 == cam.get_frame(context.frame)
    frame = cv2.imread(context.frame)
    mp = (3, 0.8, *get_default_match_parameter()[2::]
          )  # use ccorr_normed method 0 and threshold =0.65

    video_quality = None
    found_uhd = match(frame,
                      cv2.imread(playback_soft_buttons['uhd unhilite'][1]),
                      REGION_PROGRESS_BAR,
                      match_parameter=mp)[0]
    if found_uhd is True:
        video_quality = "uhd"
        debug(f"found uhd")
    found_hdx = match(frame,
                      cv2.imread(playback_soft_buttons['hdx unhilite'][1]),
                      REGION_PROGRESS_BAR,
                      match_parameter=mp)[0]
    if found_hdx is True:
        video_quality = "hdx"
        debug(f"found hdx")
    found_sd = match(frame,
                     cv2.imread(playback_soft_buttons['sd unhilite'][1]),
                     REGION_PROGRESS_BAR,
                     match_parameter=mp)[0]
    if found_sd is True:
        video_quality = "sd"
        debug(f"found sd")

    return video_quality
def detect_shoppable_ads(context):
    debug("=== detect_shoppable_ads ===")
    frame = cv2.imread(context.frame)
    ads = "./images/Roku/shoppable_ads.png"
    ads1 = "./images/Roku/shoppable_ads_1.png"
    ads2 = "./images/Roku/shoppable_ads_2.png"
    ads_region = Region(x=1000, y=400, right=1280, bottom=600)
    ads1_region = Region(x=1000, y=360, right=1280, bottom=620)
    ads2_region = Region(x=1070, y=260, right=1166, bottom=350)
    return match(frame, ads, rads_region)[0] or \
        match(frame, ads1, ads1_region)[0] or \
        match(frame, ads2, ads2_region)[0]
Esempio n. 5
0
def find_selection_text(frame,
                        left_bk,
                        right_bk=None,
                        x_offset=0,
                        y_offset=5,
                        region=Region(x=0, y=0, right=1280, bottom=720),
                        convert_to_grayscale=True,
                        match_parameter=None):
    print(f"find_selection_text: region {region}")
    debug("search for left bracket")
    if match_parameter is None:
        match_parameter = get_default_match_parameter()

    l_result = match(frame,
                     left_bk,
                     region=region,
                     match_parameter=match_parameter)
    if l_result[0] is False:
        debug("Error: fail to search left bracket")
        return None, None
    if right_bk is None:
        region = Region(x=l_result[1].x + x_offset,
                        y=l_result[1].y + y_offset,
                        right=l_result[1].right - x_offset,
                        bottom=l_result[1].bottom - y_offset)
    else:
        debug("search for right bracket")
        r_result = match(frame,
                         right_bk,
                         region=region,
                         match_parameter=match_parameter)
        if r_result[0] is False:
            debug("Error: fail to search right bracket")
            return None, None
        if l_result[1].right + x_offset > r_result[1].x - x_offset:
            return None, None
        region = Region(x=l_result[1].x + x_offset,
                        y=l_result[1].y + y_offset,
                        right=r_result[1].right - x_offset,
                        bottom=r_result[1].bottom - y_offset)
        print(f"find_selection_text: search text in {region}")
    if convert_to_grayscale is True:
        text = ocr(frame=cv2.cvtColor(
            frame[region.y:region.bottom,
                  region.x:region.right], cv2.COLOR_BGR2GRAY))

    else:
        text = ocr(frame=frame[region.y:region.bottom, region.x:region.right])
    print(f"find_selection_text: found {text} in selected region")
    return text, region
def get_current_rental_quality(context):
    cam = context.cam
    context.frame = get_frame_name(context, f"{WORK_DIR}/_frame.png")
    assert 200 == cam.get_frame(path=context.frame)
    frame = cv2.imread(context.frame)
    uhd_sym_match = is_uhd_visible(context, frame)
    hdx_sym_match = is_hdx_visible(context, frame)
    sd_sym_match = is_sd_visible(context, frame)
    uhd_set = hdx_set = sd_set = set()
    if uhd_sym_match is not None and uhd_sym_match[0] is True:
        uhd_set = set(range(uhd_sym_match[1].y, uhd_sym_match[1].bottom))
    if hdx_sym_match is not None and hdx_sym_match[0] is True:
        hdx_set = set(range(hdx_sym_match[1].y, hdx_sym_match[1].bottom))
    if sd_sym_match is not None and sd_sym_match[0] is True:
        sd_set = set(range(sd_sym_match[1].y, sd_sym_match[1].bottom))

    current_quality_match = match(frame, PURCHASE_POPUP_PRICE_20X36, region=REGION_PURCHASE_POPUP_GRID_PRICE)
    assert current_quality_match[0], "fail to find current purchase"
    curent_quality_set = set(range(current_quality_match[1].y, current_quality_match[1].bottom))

    if len(list(curent_quality_set & uhd_set)) > 0:
        current_quality = consts.QUALITY_UHD
    elif len(list(curent_quality_set & hdx_set)) > 0:
        current_quality = consts.QUALITY_HDX
    elif len(list(curent_quality_set & sd_set)) > 0:
        current_quality = consts.QUALITY_SD
    else:
        assert False, "=== cannot find selected quality ==="
    return current_quality
def step_impl(context, switch):
    press(context, keys.KEY_DOWN, 1)  # to show progress bar
    cam = context.cam
    context.frame = get_frame_name(context, f"{WORK_DIR}/_frame.png")
    assert 200 == cam.get_frame(context.frame)
    frame = cv2.imread(context.frame)
    mp = (3, 0.7, *get_default_match_parameter()[2::]
          )  # use ccorr_normed method 0 and threshold =0.65

    debug("check current switch\n")
    if switch == "off":
        debug(f"match {playback_soft_buttons['family play off unhilite'][1]}")
        if match(frame,
                 cv2.imread(
                     playback_soft_buttons["family play off unhilite"][1]),
                 REGION_PROGRESS_BAR,
                 match_parameter=mp)[0] is True:
            debug(f"family play is already {switch}\n")
            return
    elif switch == "on":
        debug(f"match {playback_soft_buttons['family play on unhilite'][1]}")
        if match(frame,
                 cv2.imread(
                     playback_soft_buttons["family play on unhilite"][1]),
                 REGION_PROGRESS_BAR,
                 match_parameter=mp)[0] is True:
            debug(f"family play is already {switch}\n")
            return
    debug(f"navigate_to family play {switch}\n")
    if navigate_to(context,
                   "family play on" if switch == "off" else "family play off"):
        press(context, keys.KEY_SELECT, 1)
        # press(context, keys.KEY_UP, 1)
        press(context, keys.KEY_SELECT, 1)

        # dismiss family play popup
        press(context, keys.KEY_SELECT, 1)
        if switch == "on":
            press(context, keys.KEY_SELECT, 1)  # dismiss family play popup

        return
Esempio n. 8
0
def step_impl(context, template, region):
    print(f"verify template file: {template}")
    if os.path.isfile(template):
        where = list(map(int, region.split(",")))
        # region = vudu_image.Region(where[0], where[1], where[2], where[3])
        region = Region(*where)
        print(f"match in region:{region}")
        match_result = vudu_image.match(cv2.imread(context.image),
                                        cv2.imread(template), region)
        context.match_result = match_result
    else:
        assert False, f"cannot find file: {template}"
def find_video_quality_on_playback_page(context):
    cam = context.cam
    context.frame = get_frame_name(context, f"{WORK_DIR}/_frame.png")
    assert 200 == cam.get_frame(context.frame)
    frame = cv2.imread(context.frame)
    mp = (3, 0.8, *get_default_match_parameter()[2::]
          )  # use ccorr_normed method 0 and threshold =0.65

    video_quality = "None"
    result = 0.0
    assert os.path.exists(playback_video_quality["uhd"])
    found = match(frame,
                  cv2.imread(playback_video_quality['uhd']),
                  REGION_PLAYBACK_PAGE_TITLE,
                  match_parameter=mp)
    if found[0] is True and found[2] > result:
        video_quality = "uhd"
        result = found[2]
        debug(f"found uhd")
    found = match(frame,
                  cv2.imread(playback_video_quality['hdx']),
                  REGION_PLAYBACK_PAGE_TITLE,
                  match_parameter=mp)
    if found[0] is True and found[2] > result:
        video_quality = "hdx"
        result = found[2]
        debug(f"found hdx")
    found = match(frame,
                  cv2.imread(playback_video_quality['sd']),
                  REGION_PLAYBACK_PAGE_TITLE,
                  match_parameter=mp)
    if found[0] is True and found[2] > result:
        video_quality = "sd"
        result = found[2]
        debug(f"found sd")
    print("\n\n")

    return video_quality
def find_current_chapters(context):
    press(context, keys.KEY_SELECT, 1)  # to show chapter grid
    cam = context.cam
    context.frame = get_frame_name(context, f"{WORK_DIR}/_frame.png")
    assert 200 == cam.get_frame(context.frame)
    frame = cv2.imread(context.frame)
    mp = (3, 0.8, *get_default_match_parameter()[2::]
          )  # use ccorr_normed method 0 and threshold =0.65
    debug(f"match {playback_chapter['chapter']}")
    result = match(frame,
                   cv2.imread(playback_chapter["chapter"]),
                   REGION_CHAPTER_GRID,
                   match_parameter=mp)
    print("\n\n")
    assert result[0] is True, f"fail to find current chapter"

    # find current chapter
    chapter_grids_width = REGION_CHAPTER_GRID.right - REGION_CHAPTER_GRID.x
    chapter_grids_height = REGION_CHAPTER_GRID.bottom - REGION_CHAPTER_GRID.top

    chapter_width = chapter_grids_width // CHAPTER_GRID_COLS
    chapter_height = chapter_grids_height // CHAPTER_GRID_ROWS
    chapters_regions = []
    for row in range(CHAPTER_GRID_ROWS):
        for col in range(CHAPTER_GRID_COLS):
            chapters_regions.append(
                Region(REGION_CHAPTER_GRID.x + col * chapter_width,
                       REGION_CHAPTER_GRID.y + row * chapter_height,
                       REGION_CHAPTER_GRID.x + (col + 1) * chapter_width,
                       REGION_CHAPTER_GRID.y + (row + 1) * chapter_height))
            # debug(f"chapter: {len(chapters_regions) + 1}, {chapters_regions[-1]}")
    found_chapters = []
    focused_chapter = 0
    focused_chapter_area = 0
    for chp in range(len(chapters_regions)):
        area = Region.intersect_area(result[1], chapters_regions[chp])
        # debug(f"intersect area {result[1]} and  {chapters_regions[chp]}, area: {area}")
        if area > 0:
            found_chapters.append((chp, area))
            debug(f"chapter {chp + 1}, area: {area}")
            if area > focused_chapter_area:
                focused_chapter = chp + 1
                focused_chapter_area = area

    return focused_chapter
def is_single_purchase_price_buy_4k_visible(context, frame):
    # focused buy
    return match(frame, PURCHASE_POPUP_BUY_4K)[0]
def is_single_purchase_price_un_focus_buy_visible(context, frame):
    # unfocused buy
    return match(frame, PURCHASE_POPUP_BUY_UH)[0]
def is_discount_price_visible(context, frame):
    """
    :return: if discount_price (orange price) is visible.
    """
    return match(frame, ORANGE_DISCOUNT_PRICE_DETAILS)
def check_discount_price(context, frame):
    """
    :return: if discount_price is visible.
   """
    return (match(frame, PURCHASE_ORANGE_DISCOUNT)[0]) or \
           (match(frame, PURCHASE_ORANGE_DISCOUNT_UH)[0])
def is_uhd_visible(context, frame):
    """
    :return: un-highlighted SD icon on screen.
   """
    return match(frame, PURCHASE_POPUP_UHD_UH, REGION_PURCHASE_POPUP_GRID_VIDEO_QAULITY)
def is_sd_visible(context, frame):
    """
    :return: SD icon on screen.
   """
    return match(frame, PURCHASE_POPUP_SD_UH, REGION_PURCHASE_POPUP_GRID_VIDEO_QAULITY)
def is_hdx_visible(context, frame):
    """
    :return: HDX icon on screen
   """
    return match(frame, PURCHASE_POPUP_HDX_UH, REGION_PURCHASE_POPUP_GRID_VIDEO_QAULITY)
def check_cancel_button_visible(context):
        cam = context.cam
        context.frame = get_frame_name(context, f"{WORK_DIR}/_frame.png")
        assert 200 == cam.get_frame(path=context.frame)
        frame = cv2.imread(context.frame)
        return match(frame, MOVIE_PURCHASE_POPUP_CANCEL_BUTTON)
def is_single_purchase_price_rent_4k_visible(context, frame):
    return match(frame, PURCHASE_POPUP_RENT_4K)[0]
def is_single_purchase_price_buy_hdx_visible(context, frame):
        return match(frame, PURCHASE_POPUP_BUY_HD)[0]
def is_single_purchase_price_rent_visible(context, frame=None):
    if frame is None:
        cam = context.cam
        context.frame = get_frame_name(context, f"{WORK_DIR}/_frame.png")
        assert 200 == cam.get_frame(path=context.frame)
    return match(context.frame, PURCHASE_POPUP_RENT)
Esempio n. 22
0
def search_by_image(context,
                    region,
                    target,
                    key_to_press,
                    max_tries,
                    interval_secs=1,
                    mp=None,
                    hist=None,
                    key_to_press_func=None,
                    focus_threshold=None):
    """
    This function is mainly used in the menu or sub-menu where direction could be horizontal or vertical.
    :param mp: the match_parameters
    :param region: narrow down the region to search
    :param target: target image
    :param key_to_press: direction to press the arrow key on the remote control
    :param max_tries: maximum number of presses
    :param mp: match parameters for image match
    :param hist: use historgram/brightness to compare the difference to avoid false positive
    :return: (bool) whether image is found.
    """
    debug(
        f" Search by image: {target}, region: {region}, max_tries: {max_tries}, mp: {mp}, hist: {hist}"
    )
    MIN_DIFFERENCE = 0.15
    ex_per_pixel = None
    ex_region = None
    found = 0
    cam = context.cam
    for tries in range(max_tries):
        path = get_frame_name(context, f"{WORK_DIR}/_frame.png")
        cam.get_frame(path)
        _frame = cv2.imread(path)
        if mp is not None:
            result = match(frame=_frame,
                           image=cv2.imread(target),
                           region=region,
                           match_parameter=mp)
        else:
            result = match(frame=_frame,
                           image=cv2.imread(target),
                           region=region)
        if result[0] is True:
            found += 1
            # if wait_until(lambda: match(image=target), timeout_secs=1):
            if hist is None:
                print("\n\n==== Found image !! returning... ====\n\n")
                return True
            else:
                print(f"\n\n==== Found image !! check hist... {tries}====\n\n")
                # copy the detected image
                found_target = _frame[result[1].y:result[1].bottom,
                                      result[1].x:result[1].right]
                debug(
                    f"frame shape{_frame.shape}, found target shape:{found_target.shape}, "
                    f"region: {result[1]}, size: {found_target.size}")
                size = found_target.shape[0] * found_target.shape[1]
                if hist != SEARCH_BY_IMAGE_USE_BRIGHTNESS:
                    total_r = total_g = total_b = 0
                    for r in (found_target):
                        for c in (r):
                            total_b += c[0]
                            total_g += c[1]
                            total_r += c[2]
                    debug(
                        f"total r, g, b: {total_r, total_g, total_b}, avg. r, g, b "
                        f"{total_r/size, total_g/size, total_b/size}")
                    if hist == SEARCH_BY_IMAGE_USE_RED_COLOR:
                        total = total_r
                        diff = 1.0 - (total_g + total_b) / 2 / total_r
                        debug(f"diff = {diff}")
                    elif hist == SEARCH_BY_IMAGE_USE_GREEN_COLOR:
                        total = total_g
                        diff = 1.0 - (total_r + total_b) / 2 / total_g
                        debug(f"diff = {diff}")
                    elif hist == SEARCH_BY_IMAGE_USE_BLUE_COLOR:
                        total = total_b
                        diff = 1.0 - (total_r + total_g) / 2 / total_b
                        debug(f"diff = {diff}")
                    per_pixel = total / size
                    threshold = 15.0 if focus_threshold is not None else focus_threshold
                else:
                    # path = f"{WORK_DIR}/_frame_{tries}_c.png"
                    # cv2.imwrite(path, found_target)
                    greyscale_found_target = cv2.cvtColor(
                        found_target, cv2.COLOR_BGR2GRAY)
                    # path = f"{WORK_DIR}/_frame_{tries}_g.png"
                    # cv2.imwrite(path, greyscale_found_target)

                    debug(
                        f"greyscale found target shape: {greyscale_found_target.shape}"
                    )
                    total = 0
                    for i in range(greyscale_found_target.shape[0]):
                        total += sum(greyscale_found_target[i])
                    per_pixel = total / size
                    threshold = 40.0 if focus_threshold is None else focus_threshold

                debug(f"total: {total}, per pixel avg: {per_pixel}")
                # continue
                if ex_per_pixel is None:
                    ex_per_pixel = per_pixel
                    ex_region = result[1]
                else:
                    debug(
                        f"=== Region.intersect: {Region.intersect(ex_region,result[1])}"
                    )
                    if Region.intersect(ex_region, result[1]) is False:
                        print(f"=== result region is changed, reset ")
                        ex_per_pixel = per_pixel
                        ex_region = result[1]
                    else:
                        debug(
                            f"ex per pixel: {ex_per_pixel}, per pixel: {per_pixel}, diff: "
                            f"{(per_pixel - ex_per_pixel)/per_pixel * 100} %")
                        if per_pixel > ex_per_pixel and (
                            (per_pixel - ex_per_pixel) / per_pixel * 100 >
                                threshold):
                            if hist == SEARCH_BY_IMAGE_USE_BRIGHTNESS:
                                print(
                                    "\n\n==== Found image in current position !! returning... ====\n\n"
                                )
                                return True
                            else:
                                # Due to the background video can introduce brightness influnce,
                                # if the difference between the other two colors are too low,
                                # we will just assume it is a false positive
                                if diff > MIN_DIFFERENCE:
                                    print(
                                        f"\n\n==== Found image in current position, diff: {diff} !! returning... "
                                        f"====\n\n")
                                    return True
                        # elif tries == 1 and per_pixel < ex_per_pixel and (
                        elif per_pixel < ex_per_pixel and (
                                # if highlight is the previous one, it is moving away instead of moving in
                            (ex_per_pixel - per_pixel) / per_pixel * 100 >
                                threshold):
                            debug(
                                "\n\n==== Found image in last position ? verifying ... ====\n\n"
                            )
                            if hist == SEARCH_BY_IMAGE_USE_BRIGHTNESS or (
                                    hist != SEARCH_BY_IMAGE_USE_BRIGHTNESS
                                    and diff > MIN_DIFFERENCE
                            ):  # diff is used to make sure the difference is not introduced by fade in effect
                                debug(
                                    "\n\n==== Found image in last position!! verified and returning... ====\n\n"
                                )
                                if key_to_press == keys.KEY_RIGHT:
                                    if not key_to_press_func:
                                        press(context, keys.KEY_LEFT)
                                    else:
                                        key_to_press_func(keys.KEY_LEFT, 2)
                                elif key_to_press == keys.KEY_LEFT:
                                    if not key_to_press_func:
                                        press(context, keys.KEY_RIGHT)
                                    else:
                                        key_to_press_func(keys.KEY_LEFT, 2)
                                elif key_to_press == keys.KEY_UP:
                                    if not key_to_press_func:
                                        press(context, keys.KEY_DOWN)
                                    else:
                                        key_to_press_func(keys.KEY_LEFT, 2)
                                elif key_to_press == keys.KEY_DOWN:
                                    if not key_to_press_func:
                                        press(context, keys.KEY_UP)
                                    else:
                                        key_to_press_func(keys.KEY_LEFT, 2)
                                else:
                                    assert_that(
                                        False,
                                        "dont know how to navigate back to previous position"
                                    )
                                return True
                        else:
                            debug(
                                f"\n\n=== Still not sure why we come here! per_pixel:{per_pixel}, ex_per_pixel{ex_per_pixel}, diff: {(ex_per_pixel - per_pixel) / per_pixel * 100 } ===\n\n"
                            )
                        ex_per_pixel = per_pixel
        stable_secs = 1.0
        if not key_to_press_func:
            press(context, key_to_press, 1)
            if interval_secs > stable_secs:
                time.sleep(interval_secs - stable_secs)
            # helper.press_key_and_wait(key_to_press, 2.0)
        else:
            key_to_press_func(context, key_to_press)

    # To Be improved. If this button is the only button, there is no actions to compare. -Henry
    if found == max_tries:
        debug("Found image but no actions detected !!  returning...")
        return True
    return False