def _get_wire_colors_and_positions(im): colors_and_positions = [] for i in range(len(_BOTTOM_X_BOUNDARIES) - 1): wire = get_subset(im, _BOTTOM_X_BOUNDARIES[i:i + 2], _WIRE_Y_BOUNDARIES) wire_colors_and_mats = filter(None, ( _get_wire_color_and_mat_or_none(wire, 354 / 2, (220, 255), (150, 220), WireColor.RED), _get_wire_color_and_mat_or_none(wire, 37 / 2, (0, 50), (200, 255), WireColor.WHITE), _get_wire_color_and_mat_or_none(wire, 229 / 2, (150, 200), (75, 215), WireColor.BLUE), )) if not wire_colors_and_mats: colors_and_positions.append(None) continue wire_colors, mats = zip(*wire_colors_and_mats) w, h = get_dimens(im) left = int((w * _BOTTOM_X_BOUNDARIES[i]) / 100.0) top = int((h * _WIRE_Y_BOUNDARIES[0]) / 100.0) summed_wires = sum(mats) structuring_element1 = cv2.getStructuringElement(cv2.MORPH_RECT, (15, 15)) summed_wires = cv2.morphologyEx(summed_wires, cv2.MORPH_CLOSE, structuring_element1) contour = max(get_contours(summed_wires, close_and_open=False), key=cv2.contourArea) center = get_center_for_contour(contour) center = apply_offset_to_single_location(center, (left, top)) # show(summed_wires) colors_and_positions.append((wire_colors, center)) return colors_and_positions
def _get_leds_are_lit(im): leds_are_lit = [] for i in range(len(_TOP_X_BOUNDARIES) - 1): led = get_subset(im, _TOP_X_BOUNDARIES[i:i + 2], _LED_Y_BOUNDARIES) lit_led = extract_color(led, 51 / 2, (40, 90), (220, 255)) leds_are_lit.append(lit_led.any()) # show(lit_led) return leds_are_lit
def _get_button_color(im): im = get_subset(im, _COLOR_X_PERCENTS, _COLOR_Y_PERCENTS) colors = [color for mat, color in ( (extract_color_2(im, 39, 11, 96), ButtonColor.WHITE), (extract_color_2(im, 45, 86, 85), ButtonColor.YELLOW), (extract_color_2(im, 355, 79, 81), ButtonColor.RED), (extract_color_2(im, 227, 78, 72), ButtonColor.BLUE), ) if mat.any()] assert len(colors) == 1, "Button does not look like one color" return colors[0]
def get_strip_color(im): im = get_subset(im, _STRIP_X_PERCENTS, _STRIP_Y_PERCENTS) colors = [color for mat, color in ( (extract_color(im, (0, 180), (0, 5), (190, 255)), StripColor.WHITE), (extract_color_2(im, 50, 94, 84), StripColor.YELLOW), (extract_color_2(im, 0, 82, 76), StripColor.RED), (extract_color_2(im, 218, 85, 79), StripColor.BLUE), ) if mat.any()] assert len(colors) == 1, "Strip does not look like one color" return colors[0]
def _get_has_stars(im): has_stars = [] for i in range(len(_BOTTOM_X_BOUNDARIES) - 1): star = get_subset(im, _BOTTOM_X_BOUNDARIES[i:i + 2], _STAR_Y_BOUNDARIES) has_star = extract_color(star, 33 / 2, (75, 125), (0, 70)) # show(has_star) w, h = get_dimens(star) star_ratio = float(cv2.countNonZero(has_star)) / (w * h) # print star_ratio has_stars.append(star_ratio > _STAR_RATIO_THRESHOLD) return has_stars
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_button_color(im): im = get_subset(im, _COLOR_X_PERCENTS, _COLOR_Y_PERCENTS) colors = [ color for mat, color in ( (extract_color_2(im, 39, 11, 96), ButtonColor.WHITE), (extract_color_2(im, 45, 86, 85), ButtonColor.YELLOW), (extract_color_2(im, 355, 79, 81), ButtonColor.RED), (extract_color_2(im, 227, 78, 72), ButtonColor.BLUE), ) if mat.any() ] assert len(colors) == 1, "Button does not look like one color" return colors[0]
def get_strip_color(im): im = get_subset(im, _STRIP_X_PERCENTS, _STRIP_Y_PERCENTS) colors = [ color for mat, color in ( (extract_color(im, (0, 180), (0, 5), (190, 255)), StripColor.WHITE), (extract_color_2(im, 50, 94, 84), StripColor.YELLOW), (extract_color_2(im, 0, 82, 76), StripColor.RED), (extract_color_2(im, 218, 85, 79), StripColor.BLUE), ) if mat.any() ] assert len(colors) == 1, "Strip does not look like one color" return colors[0]
def _get_button_text(im, tesseract): im = get_subset(im, _TEXT_X_PERCENTS, _TEXT_Y_PERCENTS) black_text = extract_color(im, (0, 255), (0, 255), (0, 65)) white_text = extract_color(im, (0, 255), (0, 40), (230, 255)) if black_text.any(): text_image = black_text else: assert white_text.any(), "Neither black nor white text have any pixels." text_image = white_text tesseract.SetImage(Image.fromarray(text_image)) word = tesseract.GetUTF8Text().strip() # It messes up a lot, just take the one with the closest edit distance return sorted(ButtonLabel, key=lambda s: editdistance.eval(s.value, word))[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_button_text(im, tesseract): im = get_subset(im, _TEXT_X_PERCENTS, _TEXT_Y_PERCENTS) black_text = extract_color(im, (0, 255), (0, 255), (0, 65)) white_text = extract_color(im, (0, 255), (0, 40), (230, 255)) if black_text.any(): text_image = black_text else: assert white_text.any( ), "Neither black nor white text have any pixels." text_image = white_text tesseract.SetImage(Image.fromarray(text_image)) word = tesseract.GetUTF8Text().strip() # It messes up a lot, just take the one with the closest edit distance return sorted(ButtonLabel, key=lambda s: editdistance.eval(s.value, word))[0]
def _get_clock_image_from_full_screenshot(full_screenshot, current_module_position, screenshot_helper): current_x, current_y = current_module_position left, right, top, bottom = MODULE_RECT mod_width = right - left mod_height = bottom - top for desired_x in (0, 1, 2): for desired_y in (0, 1): delta_x = (desired_x - current_x) * mod_width delta_y = (desired_y - current_y) * mod_height if delta_x == 0 and delta_y == 0: continue x_percents = (left + delta_x, right + delta_x) y_percents = (top + delta_y, bottom + delta_y) mod_im = get_subset(full_screenshot, x_percents, y_percents, 25) if screenshot_helper.classify_module(mod_im) == Type.clock: return mod_im return None
def _get_wire_colors_and_positions(im): colors_and_positions = [] for i in range(len(_BOTTOM_X_BOUNDARIES) - 1): wire = get_subset(im, _BOTTOM_X_BOUNDARIES[i:i + 2], _WIRE_Y_BOUNDARIES) wire_colors_and_mats = filter(None, ( _get_wire_color_and_mat_or_none(wire, 354 / 2, (220, 255), (150, 220), WireColor.RED), _get_wire_color_and_mat_or_none(wire, 37 / 2, (0, 50), (200, 255), WireColor.WHITE), _get_wire_color_and_mat_or_none(wire, 229 / 2, (150, 200), (75, 215), WireColor.BLUE), )) if not wire_colors_and_mats: colors_and_positions.append(None) continue wire_colors, mats = zip(*wire_colors_and_mats) w, h = get_dimens(im) left = int((w * _BOTTOM_X_BOUNDARIES[i]) / 100.0) top = int((h * _WIRE_Y_BOUNDARIES[0]) / 100.0) summed_wires = sum(mats) structuring_element1 = cv2.getStructuringElement( cv2.MORPH_RECT, (15, 15)) summed_wires = cv2.morphologyEx(summed_wires, cv2.MORPH_CLOSE, structuring_element1) contour = max(get_contours(summed_wires, close_and_open=False), key=cv2.contourArea) center = get_center_for_contour(contour) center = apply_offset_to_single_location(center, (left, top)) # show(summed_wires) colors_and_positions.append((wire_colors, center)) return colors_and_positions
def get_is_done(im): im = get_subset(im, (80, 95), (5, 20)) color = extract_color(im, 128 / 2, (225, 255), (150, 255)) return cv2.countNonZero(color) != 0
def _get_indicator_text(indicator, tesseract): indicator = get_subset(indicator, (40, 100), (0, 100)) color = extract_color(indicator, 47/2, (0, 50), (190, 240)) tesseract.SetImage(Image.fromarray(color)) return tesseract.GetUTF8Text().strip()
def get_is_done(im): im = get_subset(im, (80, 95), (5, 20)) color = extract_color(im, 128/2, (225, 255), (150, 255)) return cv2.countNonZero(color) != 0
def _get_indicator_text(indicator, tesseract): indicator = get_subset(indicator, (40, 100), (0, 100)) color = extract_color(indicator, 47 / 2, (0, 50), (190, 240)) tesseract.SetImage(Image.fromarray(color)) return tesseract.GetUTF8Text().strip()