Example #1
0
def _get_button_images(im):
    im_mono = extract_color(im, (0, 180), (0, 120), (0, 120))
    contours, hierarchy = cv2.findContours(im_mono, cv2.RETR_EXTERNAL,
                                           cv2.CHAIN_APPROX_SIMPLE)
    contours = [cv2.approxPolyDP(c, 6, True) for c in contours]
    midpoint_y = im.shape[1] / 2
    contours = [
        c for c in contours if len(c) == 4
        and cv2.boundingRect(c)[1] > midpoint_y and cv2.isContourConvex(c)
    ]
    button_box = sorted(contours, key=cv2.contourArea)[-1]
    button_box = button_box.reshape((4, 2))
    button_im = four_point_transform(im, button_box)

    button_im_mono = extract_color(button_im, 18, (50, 100), (175, 255))
    contours, hierarchy = cv2.findContours(button_im_mono, cv2.RETR_EXTERNAL,
                                           cv2.CHAIN_APPROX_SIMPLE)
    # There's 4 buttons, which will be the largest 4 contours
    contours = sorted(contours, key=cv2.contourArea)[-4:]
    contour_rects = [cv2.boundingRect(c) for c in contours]
    # Sort from left to right
    contour_rects = sorted(contour_rects, key=lambda rect: rect[0])

    buttons = []
    for x, y, w, h in contour_rects:
        button = four_point_transform(
            button_im,
            np.array(((x, y), (x + w, y), (x, y + h), (x + w, y + h))), -6)
        button = extract_color(button, 18, (50, 100), (175, 255))
        buttons.append(button)

    return buttons
Example #2
0
def _get_button_images(im):
    im_mono = extract_color(im, (0, 180), (0, 120), (0, 120))
    contours, hierarchy = cv2.findContours(im_mono, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    contours = [cv2.approxPolyDP(c, 6, True) for c in contours]
    midpoint_y = im.shape[1] / 2
    contours = [c for c in contours if len(c) == 4 and cv2.boundingRect(c)[1] > midpoint_y and cv2.isContourConvex(c)]
    button_box = sorted(contours, key=cv2.contourArea)[-1]
    button_box = button_box.reshape((4, 2))
    button_im = four_point_transform(im, button_box)

    button_im_mono = extract_color(button_im, 18, (50, 100), (175, 255))
    contours, hierarchy = cv2.findContours(button_im_mono, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    # There's 4 buttons, which will be the largest 4 contours
    contours = sorted(contours, key=cv2.contourArea)[-4:]
    contour_rects = [cv2.boundingRect(c) for c in contours]
    # Sort from left to right
    contour_rects = sorted(contour_rects, key=lambda rect: rect[0])

    buttons = []
    for x, y, w, h in contour_rects:
        button = four_point_transform(button_im, np.array(((x, y), (x + w, y), (x, y + h), (x + w, y + h))), -6)
        button = extract_color(button, 18, (50, 100), (175, 255))
        buttons.append(button)

    return buttons
Example #3
0
def get_screen_content(im, tesseract, debug_idx):
    # orig_im = im
    color = 110
    sensitivity = 20
    lower_bound = np.array([color - sensitivity, 0, 0])
    upper_bound = np.array([color + sensitivity, 125, 65])
    hsv = cv2.cvtColor(im, cv2.COLOR_BGR2HSV)
    im_mono = cv2.inRange(hsv, lower_bound, upper_bound)
    # show(im_mono)

    contours, hierarchy = cv2.findContours(im_mono, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    contours = [cv2.approxPolyDP(c, 0.001 * cv2.contourArea(c), True) for c in contours]
    contours = sorted([c for c in contours if _is_valid_screen_contour(im, c)], key=cv2.contourArea)
    # show(get_drawn_contours(im, contours))
    contour = contours[-1]
    contour = contour.reshape((4, 2))

    im = four_point_transform(im, contour)
    im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
    retval, im = cv2.threshold(im, 200, 255, cv2.THRESH_BINARY)

    cv2.imwrite(os.path.join(MODULE_SPECIFIC_DIR, "whos_on_first", "in_game_%i_screen.png" % debug_idx), im)
    # show(im)

    # Special case handling for the screen without anything on it.
    if im.sum() == 0:
        screen_text = ""
    else:
        tesseract.SetImage(Image.fromarray(im))
        screen_text = tesseract.GetUTF8Text().upper().strip().replace(" ", "")

    # print screen_text
    # show(get_drawn_contours(orig_im, [contour], True))

    return screen_text
Example #4
0
def extract_maze(im):
    im_gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
    ret, thresh = cv2.threshold(im_gray, 127, 255, 0)
    contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    best_contour = None
    for contour in contours:
        contour = cv2.approxPolyDP(contour, 5, True)
        if contour.shape[0] == 8 and looks_reasonable(contour, im.shape):
            if best_contour is None or has_smaller_bounding_box(contour, best_contour):
                best_contour = contour

    # show_contours = np.empty(im.shape)
    # show_contours[:, :] = [0, 0, 0]
    # cv2.drawContours(show_contours, [best_contour], -1, (0, 255, 0), 1)
    # for x, y in (tl, tr, br, bl):
    #     if y < show_contours.shape[0] and x < show_contours.shape[1]:
    #         show_contours[y, x] = [255, 255, 255]
    # show_contours = four_point_transform(show_contours, points)

    points = get_corners_from_cornerless_rect(best_contour)
    im = four_point_transform(im, points)

    # Remove 5% from the edges
    margin_y = im.shape[0] * 5 / 100
    margin_x = im.shape[1] * 5 / 100
    return im[margin_y:-margin_y, margin_x:-margin_x]
def _get_letters(text_threshold):
    # type: (np.array) -> List[np.array]
    height, width = text_threshold.shape[:2]
    contours, _ = cv2.findContours(text_threshold.copy(), cv2.RETR_EXTERNAL,
                                   cv2.CHAIN_APPROX_SIMPLE)
    contours = [c for c in contours if cv2.boundingRect(c)[3] > height / 3]
    centers = [get_center_for_contour(c) for c in contours]
    centers = sorted(centers, key=lambda x: x[0])
    distances = []
    for idx in range(len(centers) - 1):
        distances.append(centers[idx + 1][0] - centers[idx][0])
    half_avg_dist = sum(distances) / (len(distances) * 2)
    # contours = [contour_bounding_box_for_contour(c) for c in contours]
    # show(get_drawn_contours(text_threshold, contours, True))
    letters = []
    for center in centers:
        x = center[0] - half_avg_dist
        y = 0
        w = half_avg_dist * 2
        h = height
        contour = np.array([
            [x, y],
            [x + w, y],
            [x + w, y + h],
            [x, y + h],
        ]).reshape((4, 1, 2))
        letters.append(four_point_transform(text_threshold, contour))
    return letters
Example #6
0
def extract_maze(im):
    im_gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
    ret, thresh = cv2.threshold(im_gray, 127, 255, 0)
    contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE,
                                           cv2.CHAIN_APPROX_SIMPLE)
    best_contour = None
    for contour in contours:
        contour = cv2.approxPolyDP(contour, 5, True)
        if contour.shape[0] == 8 and looks_reasonable(contour, im.shape):
            if best_contour is None or has_smaller_bounding_box(
                    contour, best_contour):
                best_contour = contour

    # show_contours = np.empty(im.shape)
    # show_contours[:, :] = [0, 0, 0]
    # cv2.drawContours(show_contours, [best_contour], -1, (0, 255, 0), 1)
    # for x, y in (tl, tr, br, bl):
    #     if y < show_contours.shape[0] and x < show_contours.shape[1]:
    #         show_contours[y, x] = [255, 255, 255]
    # show_contours = four_point_transform(show_contours, points)

    points = get_corners_from_cornerless_rect(best_contour)
    im = four_point_transform(im, points)

    # Remove 5% from the edges
    margin_y = im.shape[0] * 5 / 100
    margin_x = im.shape[1] * 5 / 100
    return im[margin_y:-margin_y, margin_x:-margin_x]
Example #7
0
def _find_batteries(im):
    blue = extract_color(im, 216 / 2, (100, 255), (50, 150))
    green = extract_color(im, 105 / 2, (200, 255), (200, 255))
    color = blue + green
    structuring_element1 = cv2.getStructuringElement(cv2.MORPH_RECT, (15, 15))
    # structuring_element2 = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
    color = cv2.morphologyEx(color, cv2.MORPH_CLOSE, structuring_element1)
    # color = cv2.morphologyEx(color, cv2.MORPH_OPEN, structuring_element2)

    # color = scale(color, 0.25)
    # im = scale(im, 0.25)
    # show(color)

    contours, _ = cv2.findContours(color.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    # show(get_drawn_contours(color, contours, True))
    contours = [contour_bounding_box_for_contour(c) for c in contours]
    height, width = im.shape[:2]

    def is_large_enough(contour):
        x, y, w, h = cv2.boundingRect(contour)
        return w >= width * 0.1 and h >= height * 0.1

    contours = [c for c in contours if is_large_enough(c)]

    return [four_point_transform(im, c) for c in contours]
Example #8
0
def _get_screen_image(im):
    im_mono = extract_color(im, 76, (50, 150), (50, 150))
    # show(im_mono)
    contours, hierarchy = cv2.findContours(im_mono, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    midpoint_y = im.shape[1] * 2 / 3
    contours_filtered = []
    for contour in contours:
        # contour = cv2.approxPolyDP(contour, 2, True)
        x, y, w, h = cv2.boundingRect(contour)
        # if y + h < midpoint_y and cv2.isContourConvex(contour):
        if y + h < midpoint_y:
            contours_filtered.append(contour)

    contours = sorted(contours_filtered, key=cv2.contourArea)[-4:]
    boxes = [cv2.boundingRect(c) for c in contours]
    x1 = min(x for x, y, w, h in boxes)
    y1 = min(y for x, y, w, h in boxes)
    x2 = max(x + w for x, y, w, h in boxes)
    y2 = max(y + h for x, y, w, h in boxes)
    points = np.array(((x1, y1), (x1, y2), (x2, y1), (x2, y2)))
    screen = four_point_transform(im, points)
    screen_mono = cv2.cvtColor(screen, cv2.COLOR_BGR2GRAY)
    _, screen_mono = cv2.threshold(screen_mono, 245, 255, cv2.THRESH_BINARY)

    return screen_mono
Example #9
0
def _get_letters(text_threshold):
    # type: (np.array) -> List[np.array]
    height, width = text_threshold.shape[:2]
    contours, _ = cv2.findContours(text_threshold.copy(), cv2.RETR_EXTERNAL,
                                   cv2.CHAIN_APPROX_SIMPLE)
    contours = [c for c in contours if cv2.boundingRect(c)[3] > height / 3]
    centers = [get_center_for_contour(c) for c in contours]
    centers = sorted(centers, key=lambda x: x[0])
    distances = []
    for idx in range(len(centers) - 1):
        distances.append(centers[idx + 1][0] - centers[idx][0])
    half_avg_dist = sum(distances) / (len(distances) * 2)
    # contours = [contour_bounding_box_for_contour(c) for c in contours]
    # show(get_drawn_contours(text_threshold, contours, True))
    letters = []
    for center in centers:
        x = center[0] - half_avg_dist
        y = 0
        w = half_avg_dist * 2
        h = height
        contour = np.array([
            [x, y],
            [x + w, y],
            [x + w, y + h],
            [x, y + h],
        ]).reshape((4, 1, 2))
        letters.append(four_point_transform(text_threshold, contour))
    return letters
Example #10
0
def _get_screen_image(im):
    im_mono = extract_color(im, 76, (50, 150), (50, 150))
    # show(im_mono)
    contours, hierarchy = cv2.findContours(im_mono, cv2.RETR_EXTERNAL,
                                           cv2.CHAIN_APPROX_SIMPLE)

    midpoint_y = im.shape[1] * 2 / 3
    contours_filtered = []
    for contour in contours:
        # contour = cv2.approxPolyDP(contour, 2, True)
        x, y, w, h = cv2.boundingRect(contour)
        # if y + h < midpoint_y and cv2.isContourConvex(contour):
        if y + h < midpoint_y:
            contours_filtered.append(contour)

    contours = sorted(contours_filtered, key=cv2.contourArea)[-4:]
    boxes = [cv2.boundingRect(c) for c in contours]
    x1 = min(x for x, y, w, h in boxes)
    y1 = min(y for x, y, w, h in boxes)
    x2 = max(x + w for x, y, w, h in boxes)
    y2 = max(y + h for x, y, w, h in boxes)
    points = np.array(((x1, y1), (x1, y2), (x2, y1), (x2, y2)))
    screen = four_point_transform(im, points)
    screen_mono = cv2.cvtColor(screen, cv2.COLOR_BGR2GRAY)
    _, screen_mono = cv2.threshold(screen_mono, 245, 255, cv2.THRESH_BINARY)

    return screen_mono
Example #11
0
def get_letter_images(im):
    color = 42
    sensitivity = 10
    lower_bound = np.array([color - sensitivity, 100, 100])
    upper_bound = np.array([color + sensitivity, 255, 255])
    hsv = cv2.cvtColor(im, cv2.COLOR_BGR2HSV)
    im_mono = cv2.inRange(hsv, lower_bound, upper_bound)

    contours, hierarchy = cv2.findContours(im_mono, cv2.RETR_EXTERNAL,
                                           cv2.CHAIN_APPROX_SIMPLE)

    assert len(
        contours) == 1, "Expected single contour, got %s" % len(contours)
    contour = cv2.approxPolyDP(contours[0], 5, True)
    assert len(contour) == 4, "Expected 4 point contour, has %s" % len(contour)
    contour = contour.reshape((4, 2))

    im = four_point_transform(im, contour)
    letter_width = im.shape[1] / 5
    letters_raw = [
        im[:, i * letter_width:(i + 1) * letter_width] for i in range(5)
    ]
    letters_mono = []
    for letter in letters_raw:
        # Take another 5% off the letter boarders
        margin_height = letter.shape[0] * 5 / 100
        margin_width = letter.shape[1] * 5 / 100
        letter = letter[margin_height:-margin_height,
                        margin_width:-margin_width]
        color = 42
        sensitivity = 10
        lower_bound = np.array([color - sensitivity, 100, 100])
        upper_bound = np.array([color + sensitivity, 255, 255])
        hsv = cv2.cvtColor(letter, cv2.COLOR_BGR2HSV)
        letter_mono = cv2.inRange(hsv, lower_bound, upper_bound)
        letter_mono = 255 - letter_mono

        # Reduce the letter to its contour bounding box. For some reason I have to pass in a copy of letter_mono
        # otherwise it won't show properly (unclear if this is an issue with show or with the actual array).
        # contours, hierarchy = cv2.findContours(np.array(letter_mono), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        # flat_contours = reduce(lambda a, b: np.concatenate((a, b)), contours)
        # x, y, w, h = cv2.boundingRect(flat_contours)
        # letter_mono = letter_mono[y:y+h, x:x+w]
        letters_mono.append(letter_mono)

    return letters_mono
Example #12
0
def _extract_side(im, is_bottom):
    if is_bottom:
        color = extract_color(im, 32 / 2, (120, 255), (100, 220))
    else:
        color = extract_color(im, 32 / 2, (100, 255), (100, 255))

    structuring_element1 = cv2.getStructuringElement(cv2.MORPH_RECT, (10, 10))
    structuring_element2 = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
    color = cv2.morphologyEx(color, cv2.MORPH_CLOSE, structuring_element1)
    color = cv2.morphologyEx(color, cv2.MORPH_OPEN, structuring_element2)

    # show(im)
    # show(color)

    height, width = color.shape[:2]
    contours, _ = cv2.findContours(color.copy(), cv2.RETR_EXTERNAL,
                                   cv2.CHAIN_APPROX_SIMPLE)
    # contours = [cv2.approxPolyDP(c, 0.03 * cv2.arcLength(c, True), True) for c in contours]
    contours = [
        cv2.approxPolyDP(c, 0.015 * cv2.arcLength(c, True), True)
        for c in contours
    ]
    # show(get_drawn_contours(c2,  contours, True))
    # for c in contours:
    #     print len(c)
    #     show(get_drawn_contours(c2, [c], True))
    contours = [c for c in contours if len(c) == 4]
    contours = sorted(contours, key=cv2.contourArea, reverse=True)[:2]
    a, b = contours
    points = list(a) + list(b)

    tl = point_closest_to(points, 0, 0)
    tr = point_closest_to(points, width, 0)
    bl = point_closest_to(points, 0, height)
    br = point_closest_to(points, width, height)

    contour = np.array([tl, tr, br, bl])
    contour = contour.reshape((4, 2))

    # show(get_drawn_contours(c2, [contour], True))

    return four_point_transform(im, contour, margin_percent=5)
Example #13
0
def get_clock_time_from_full_screenshot(full_screenshot,
                                        current_module_position,
                                        screenshot_helper):
    clock_im = _get_clock_image_from_full_screenshot(full_screenshot,
                                                     current_module_position,
                                                     screenshot_helper)
    assert clock_im is not None, "Unable to find clock"
    clock_bg = extract_color(clock_im, (0, 180), (0, 255), (0, 50))

    contours = [
        c for c in simplify_contours(get_contours(clock_bg), 0.001)
        if len(c) == 4
    ]
    contour = max(contours, key=cv2.contourArea)

    display = four_point_transform(clock_im, contour)

    digits_im = extract_color(display, 0, (250, 255), (250, 255))

    digit_images = [
        get_subset(digits_im,
                   _CLOCK_DIGIT_X_PERCENTS[digit_index:digit_index + 2],
                   (0, 100))
        for digit_index in range(len(_CLOCK_DIGIT_X_PERCENTS) - 1)
    ]
    # Determine if there is a colon or period separator.
    is_colon = get_subset(digit_images[2], (0, 100), (0, 50)).any()
    if is_colon:
        minutes_images = digit_images[:2]
        seconds_images = digit_images[-2:]
    else:
        minutes_images = []
        seconds_images = digit_images[:2]

    minutes_digits = [_get_digit_from_image(im) for im in minutes_images]
    seconds_digits = [_get_digit_from_image(im) for im in seconds_images]

    if not minutes_digits:
        minutes_digits = [0]

    return minutes_digits, seconds_digits
Example #14
0
def get_letter_images(im):
    color = 42
    sensitivity = 10
    lower_bound = np.array([color - sensitivity, 100, 100])
    upper_bound = np.array([color + sensitivity, 255, 255])
    hsv = cv2.cvtColor(im, cv2.COLOR_BGR2HSV)
    im_mono = cv2.inRange(hsv, lower_bound, upper_bound)

    contours, hierarchy = cv2.findContours(im_mono, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    assert len(contours) == 1, "Expected single contour, got %s" % len(contours)
    contour = cv2.approxPolyDP(contours[0], 5, True)
    assert len(contour) == 4, "Expected 4 point contour, has %s" % len(contour)
    contour = contour.reshape((4, 2))

    im = four_point_transform(im, contour)
    letter_width = im.shape[1] / 5
    letters_raw = [im[:, i * letter_width:(i + 1) * letter_width] for i in range(5)]
    letters_mono = []
    for letter in letters_raw:
        # Take another 5% off the letter boarders
        margin_height = letter.shape[0] * 5 / 100
        margin_width = letter.shape[1] * 5 / 100
        letter = letter[margin_height:-margin_height, margin_width:-margin_width]
        color = 42
        sensitivity = 10
        lower_bound = np.array([color - sensitivity, 100, 100])
        upper_bound = np.array([color + sensitivity, 255, 255])
        hsv = cv2.cvtColor(letter, cv2.COLOR_BGR2HSV)
        letter_mono = cv2.inRange(hsv, lower_bound, upper_bound)
        letter_mono = 255 - letter_mono

        # Reduce the letter to its contour bounding box. For some reason I have to pass in a copy of letter_mono
        # otherwise it won't show properly (unclear if this is an issue with show or with the actual array).
        # contours, hierarchy = cv2.findContours(np.array(letter_mono), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        # flat_contours = reduce(lambda a, b: np.concatenate((a, b)), contours)
        # x, y, w, h = cv2.boundingRect(flat_contours)
        # letter_mono = letter_mono[y:y+h, x:x+w]
        letters_mono.append(letter_mono)

    return letters_mono
Example #15
0
def _extract_side(im, is_bottom):
    if is_bottom:
        color = extract_color(im, 32 / 2, (120, 255), (100, 220))
    else:
        color = extract_color(im, 32 / 2, (100, 255), (100, 255))

    structuring_element1 = cv2.getStructuringElement(cv2.MORPH_RECT, (10, 10))
    structuring_element2 = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
    color = cv2.morphologyEx(color, cv2.MORPH_CLOSE, structuring_element1)
    color = cv2.morphologyEx(color, cv2.MORPH_OPEN, structuring_element2)

    # show(im)
    # show(color)

    height, width = color.shape[:2]
    contours, _ = cv2.findContours(color.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    # contours = [cv2.approxPolyDP(c, 0.03 * cv2.arcLength(c, True), True) for c in contours]
    contours = [cv2.approxPolyDP(c, 0.015 * cv2.arcLength(c, True), True) for c in contours]
    # show(get_drawn_contours(c2,  contours, True))
    # for c in contours:
    #     print len(c)
    #     show(get_drawn_contours(c2, [c], True))
    contours = [c for c in contours if len(c) == 4]
    contours = sorted(contours, key=cv2.contourArea, reverse=True)[:2]
    a, b = contours
    points = list(a) + list(b)

    tl = point_closest_to(points, 0, 0)
    tr = point_closest_to(points, width, 0)
    bl = point_closest_to(points, 0, height)
    br = point_closest_to(points, width, height)

    contour = np.array([tl, tr, br, bl])
    contour = contour.reshape((4, 2))

    # show(get_drawn_contours(c2, [contour], True))

    return four_point_transform(im, contour, margin_percent=5)
Example #16
0
def get_clock_time_from_full_screenshot(full_screenshot,
                                        current_module_position,
                                        screenshot_helper):
    clock_im = _get_clock_image_from_full_screenshot(full_screenshot,
                                                     current_module_position,
                                                     screenshot_helper)
    assert clock_im is not None, "Unable to find clock"
    clock_bg = extract_color(clock_im, (0, 180), (0, 255), (0, 50))

    contours = [c for c in simplify_contours(get_contours(clock_bg), 0.001) if len(c) == 4]
    contour = max(contours, key=cv2.contourArea)

    display = four_point_transform(clock_im, contour)

    digits_im = extract_color(display, 0, (250, 255), (250, 255))

    digit_images = [
        get_subset(digits_im, _CLOCK_DIGIT_X_PERCENTS[digit_index:digit_index + 2], (0, 100))
        for digit_index in range(len(_CLOCK_DIGIT_X_PERCENTS) - 1)
    ]
    # Determine if there is a colon or period separator.
    is_colon = get_subset(digit_images[2], (0, 100), (0, 50)).any()
    if is_colon:
        minutes_images = digit_images[:2]
        seconds_images = digit_images[-2:]
    else:
        minutes_images = []
        seconds_images = digit_images[:2]

    minutes_digits = [_get_digit_from_image(im) for im in minutes_images]
    seconds_digits = [_get_digit_from_image(im) for im in seconds_images]

    if not minutes_digits:
        minutes_digits = [0]

    return minutes_digits, seconds_digits
def _get_cleaned_up_text_subsection(im):
    # type: (np.array) -> Optional[np.array]
    red1 = extract_color(im, (0, 6), (200, 255), (100, 150))
    red2 = extract_color(im, (176, 180), (200, 255), (100, 150))
    red = red1 + red2
    color = extract_color(im, 45 / 2, (20, 50), (200, 255))
    # show(red, .25)
    # show(yellow, .25)
    # im = scale(im, .25)
    # color = scale(color, .25)
    red_contour = _get_box_for_largest_rect_contour(red)
    text_contour = _get_box_for_largest_rect_contour(color)
    if red_contour is None or text_contour is None:
        # if red_contour is not None:
        #     print "RED"
        #     show(get_drawn_contours(red, [red_contour], True))
        #     show(color)
        # if text_contour is not None:
        #     print "TEXT"
        #     show(get_drawn_contours(color, [text_contour], True))
        #     show(red)

        # if not (red_contour is None and text_contour is None):
            # show(red)
            # show(color)
        # assert red_contour is None and text_contour is None, \
        #     "Error parsing serial number, didn't find one of the text or its label."
        return None
    
    red_center = get_center_for_contour(red_contour)
    text_center = get_center_for_contour(text_contour)
    text_subsection = four_point_transform(im, text_contour)
    # show(get_drawn_contours(color, text_contour, True), .25)
    # show(get_drawn_contours(red, red_contour, True), .25)
    # show(text_subsection)
    height, width = im.shape[:2]
    # Rotation logic from http://stackoverflow.com/a/5912847/3000133
    if height > width:
        # Determine if red is left or right of text
        if text_center[0] < red_center[0]:
            text_subsection = rotate_image_counter_clockwise(text_subsection)
        else:
            # Rotate clockwise 90
            text_subsection = rotate_image_clockwise(text_subsection)
    else:
        if text_center[1] > red_center[1]:
            # We're fine
            pass
        else:
            # Rotate 180
            text_subsection = rotate_image_180(text_subsection)

    # show(get_drawn_contours(im, [text_contour], True))
    # show(text_subsection)
    text_subsection_gray = cv2.cvtColor(text_subsection, cv2.COLOR_BGR2GRAY)
    # show(text_subsection_gray)
    _, text_threshold = cv2.threshold(text_subsection_gray, 50, 255, 0)
    text_threshold = 255 - text_threshold
    # show(text_threshold)
    height, width = text_threshold.shape[:2]
    text_threshold[:height / 10, :] = 0
    text_threshold[9 * height / 10:, :] = 0
    return text_threshold
Example #18
0
def _get_indicator_images_and_light_statuses(im):
    red = extract_color(im, 0, (50, 200), (50, 200))
    # show(red)
    w_total, h_total = get_dimens(im)
    w_threshold = int(_INDICATOR_WIDTH_PERCENT_THRESHOLD * w_total)
    h_threshold = int(_INDICATOR_HEIGHT_PERCENT_THRESHOLD * h_total)

    def is_indicator_big_enough(contour):
        _, _, contour_w, contour_h = cv2.boundingRect(contour)
        return contour_w > w_threshold and contour_h > h_threshold

    contours = [
        contour_bounding_box_for_contour(c) for c in get_contours(red)
        if is_indicator_big_enough(c)
    ]
    indicators = [four_point_transform(im, c) for c in contours]
    indicators_and_lights = []
    for indicator in indicators:
        w, h = get_dimens(indicator)
        if w < h:
            # Rotate 90 degrees so it's horizontal
            indicator = rotate_image_clockwise(indicator)
            w, h = get_dimens(indicator)

        # Check if light is on left or right, flip accordingly
        light_width_threshold = w * _LIGHT_WIDTH_THRESHOLD
        light_height_threshold = h * _LIGHT_HEIGHT_THRESHOLD
        light_on = extract_color(indicator, (0, 180), (0, 0), (255, 255))
        light_off = extract_color(indicator, (0, 180), (0, 40), (0, 50))

        # show(light_on)
        # show(light_off)

        def is_light_big_enough(contour):
            _, _, contour_w, contour_h = cv2.boundingRect(contour)
            return contour_w > light_width_threshold and contour_h > light_height_threshold

        light_on_contours = [
            contour_bounding_box_for_contour(c) for c in get_contours(light_on)
            if is_light_big_enough(c)
        ]
        light_off_contours = [
            contour_bounding_box_for_contour(c)
            for c in get_contours(light_off) if is_light_big_enough(c)
        ]
        assert len(light_on_contours) + len(light_off_contours) == 1, \
            "Expected to find exactly one light on the indicator"

        if light_on_contours:
            light_is_on = True
            light_contour = light_on_contours[0]
        else:
            light_is_on = False
            light_contour = light_off_contours[0]

        light_x, _ = get_center_for_contour(light_contour)
        if light_x > (w / 2.0):
            # Light is on the wrong side, need to flip 180
            indicator = rotate_image_180(indicator)

        indicators_and_lights.append((indicator, light_is_on))
    return indicators_and_lights
Example #19
0
def _get_indicator_images_and_light_statuses(im):
    red = extract_color(im, 0, (50, 200), (50, 200))
    # show(red)
    w_total, h_total = get_dimens(im)
    w_threshold = int(_INDICATOR_WIDTH_PERCENT_THRESHOLD * w_total)
    h_threshold = int(_INDICATOR_HEIGHT_PERCENT_THRESHOLD * h_total)

    def is_indicator_big_enough(contour):
        _, _, contour_w, contour_h = cv2.boundingRect(contour)
        return contour_w > w_threshold and contour_h > h_threshold

    contours = [
        contour_bounding_box_for_contour(c) for c in get_contours(red)
        if is_indicator_big_enough(c)
    ]
    indicators = [four_point_transform(im, c) for c in contours]
    indicators_and_lights = []
    for indicator in indicators:
        w, h = get_dimens(indicator)
        if w < h:
            # Rotate 90 degrees so it's horizontal
            indicator = rotate_image_clockwise(indicator)
            w, h = get_dimens(indicator)

        # Check if light is on left or right, flip accordingly
        light_width_threshold = w * _LIGHT_WIDTH_THRESHOLD
        light_height_threshold = h * _LIGHT_HEIGHT_THRESHOLD
        light_on = extract_color(indicator, (0, 180), (0, 0), (255, 255))
        light_off = extract_color(indicator, (0, 180), (0, 40), (0, 50))

        # show(light_on)
        # show(light_off)

        def is_light_big_enough(contour):
            _, _, contour_w, contour_h = cv2.boundingRect(contour)
            return contour_w > light_width_threshold and contour_h > light_height_threshold

        light_on_contours = [
            contour_bounding_box_for_contour(c) for c in get_contours(light_on)
            if is_light_big_enough(c)
        ]
        light_off_contours = [
            contour_bounding_box_for_contour(c) for c in get_contours(light_off)
            if is_light_big_enough(c)
        ]
        assert len(light_on_contours) + len(light_off_contours) == 1, \
            "Expected to find exactly one light on the indicator"

        if light_on_contours:
            light_is_on = True
            light_contour = light_on_contours[0]
        else:
            light_is_on = False
            light_contour = light_off_contours[0]

        light_x, _ = get_center_for_contour(light_contour)
        if light_x > (w / 2.0):
            # Light is on the wrong side, need to flip 180
            indicator = rotate_image_180(indicator)

        indicators_and_lights.append((indicator, light_is_on))
    return indicators_and_lights
Example #20
0
def _get_cleaned_up_text_subsection(im):
    # type: (np.array) -> Optional[np.array]
    red1 = extract_color(im, (0, 6), (200, 255), (100, 150))
    red2 = extract_color(im, (176, 180), (200, 255), (100, 150))
    red = red1 + red2
    color = extract_color(im, 45 / 2, (20, 50), (200, 255))
    # show(red, .25)
    # show(yellow, .25)
    # im = scale(im, .25)
    # color = scale(color, .25)
    red_contour = _get_box_for_largest_rect_contour(red)
    text_contour = _get_box_for_largest_rect_contour(color)
    if red_contour is None or text_contour is None:
        # if red_contour is not None:
        #     print "RED"
        #     show(get_drawn_contours(red, [red_contour], True))
        #     show(color)
        # if text_contour is not None:
        #     print "TEXT"
        #     show(get_drawn_contours(color, [text_contour], True))
        #     show(red)

        # if not (red_contour is None and text_contour is None):
        # show(red)
        # show(color)
        # assert red_contour is None and text_contour is None, \
        #     "Error parsing serial number, didn't find one of the text or its label."
        return None

    red_center = get_center_for_contour(red_contour)
    text_center = get_center_for_contour(text_contour)
    text_subsection = four_point_transform(im, text_contour)
    # show(get_drawn_contours(color, text_contour, True), .25)
    # show(get_drawn_contours(red, red_contour, True), .25)
    # show(text_subsection)
    height, width = im.shape[:2]
    # Rotation logic from http://stackoverflow.com/a/5912847/3000133
    if height > width:
        # Determine if red is left or right of text
        if text_center[0] < red_center[0]:
            text_subsection = rotate_image_counter_clockwise(text_subsection)
        else:
            # Rotate clockwise 90
            text_subsection = rotate_image_clockwise(text_subsection)
    else:
        if text_center[1] > red_center[1]:
            # We're fine
            pass
        else:
            # Rotate 180
            text_subsection = rotate_image_180(text_subsection)

    # show(get_drawn_contours(im, [text_contour], True))
    # show(text_subsection)
    text_subsection_gray = cv2.cvtColor(text_subsection, cv2.COLOR_BGR2GRAY)
    # show(text_subsection_gray)
    _, text_threshold = cv2.threshold(text_subsection_gray, 50, 255, 0)
    text_threshold = 255 - text_threshold
    # show(text_threshold)
    height, width = text_threshold.shape[:2]
    text_threshold[:height / 10, :] = 0
    text_threshold[9 * height / 10:, :] = 0
    return text_threshold