Ejemplo n.º 1
0
 def monitor(self):
     _, SH = get_screen_size()
     lo = (30, 30, 30)
     hi = (255, 255, 255)
     self.change_event.set()
     while self.is_active:
         sc = screenshot(0, SH - 200, 200, 200)
         img = features_util.convert_to_cv2(sc)
         rgb = features_util.split_channels(img)
         if self.lights_on:
             if not features_util.color_in_range(self.pixel, rgb, lo, hi):
                 if self.bomb_exploded(rgb):  # We died :(
                     self.is_active = False
                     self.exit_after_explosion()
                 else:
                     log("Lights in the room are turned off. Pausing execution temporarily..."
                         )
                     self.lights_on = False
                     self.change_event.clear()
                     sleep(1)
         else:
             if features_util.color_in_range(self.pixel, rgb, lo, hi):
                 log("Lights in the room are turned back on. Resuming...")
                 self.change_event.set()
                 self.lights_on = True
                 sleep(1)
         sleep(0.25)
Ejemplo n.º 2
0
def get_wire_colors(img, coords):
    """
    Get a list of colors for each wire. Colors can be either:
    -1 (no wire), 0 (blue), 1 (white), 2 (red), or 3 (blue + red).
    """
    wires = [-1] * 6
    colors = config.WIRE_COLOR_RANGE[2:]
    rgb = features_util.split_channels(img)
    # Radius around each wire pixel to search for colors.
    search_radius = 9
    # Minimum threshold for number of pixels to be of a specific color.
    color_threshold = 6
    for i, (y, x) in enumerate(coords):  # Look through each wire pixel.
        valid_colors = [0] * len(colors)  # Track occurences of each color.
        for k, (lo, hi) in enumerate(colors):  # Look through possible colors.
            for m in range(y - search_radius, y +
                           search_radius):  # Look in a radius around a pixel.
                for n in range(x - search_radius, x + search_radius):
                    if features_util.color_in_range((m, n), rgb, lo, hi):
                        if valid_colors[k] < color_threshold:
                            valid_colors[k] += 1
        if valid_colors[COLOR.Blue.value] == color_threshold:  # Wire is blue.
            if valid_colors[
                    COLOR.Red.value] == color_threshold:  # Wire is also red.
                wires[i] = COLOR.Both.value  # Both colors.
            else:
                wires[i] = COLOR.Blue.value
        elif valid_colors[
                COLOR.Red.value] == color_threshold:  # Wire is just red.
            wires[i] = COLOR.Red.value
        elif valid_colors[
                COLOR.White.value] == color_threshold:  # Wire is white.
            wires[i] = COLOR.White.value
    return wires
Ejemplo n.º 3
0
def get_strip_color(img, pixel):
    colors = config.BUTTON_COLOR_RANGE
    for i, (low, high) in enumerate(colors):
        rgb = feature_util.split_channels(img)
        if feature_util.color_in_range(pixel, rgb, low, high):
            return i
    return -1
Ejemplo n.º 4
0
def get_wire_colors(img, coords):
    wires = [-1] * 6
    radius = 5
    Color = Enum("Colors", {"Blue": 0, "White": 1, "Red": 2, "Both": 3})
    colors = config.WIRE_COLOR_RANGE[2:]
    rgb = features_util.split_channels(img)
    color_threshold = 5
    for i, (y, x) in enumerate(coords):
        valid_colors = [0] * len(colors)
        for k, (lo, hi) in enumerate(colors):
            for m in range(y - radius, y + radius):
                for n in range(x - radius, x + radius):
                    if features_util.color_in_range((m, n), rgb, lo, hi):
                        if valid_colors[k] < color_threshold:
                            valid_colors[k] += 1
        if valid_colors[Color.Blue.value] == color_threshold:
            if valid_colors[Color.Red.value] == color_threshold:
                wires[i] = Color.Both.value  # Both colors.
            else:
                wires[i] = Color.Blue.value
        elif valid_colors[Color.Red.value] == color_threshold:
            wires[i] = Color.Red.value
        elif valid_colors[Color.White.value] == color_threshold:
            wires[i] = Color.White.value
    return wires
Ejemplo n.º 5
0
def get_next_color(img, sc_func, ranges, features, curr_match):
    coords = [(140, 95), (74, 155), (204, 156), (140, 216)]
    colors = ["Red", "Blue", "Green", "Yellow"]
    button_coords = []
    pause_between_blinks = 0.35
    colors_matched = 0
    timestamp = 0
    while True:
        sc, _, _ = sc_func()
        rgb = feature_util.split_channels(
            cv2.cvtColor(array(sc), cv2.COLOR_RGB2BGR))
        for i, (low, high) in enumerate(ranges):
            coord = coords[i]
            if feature_util.color_in_range(
                    coord, rgb, low,
                    high) and time() - timestamp > pause_between_blinks:
                colors_matched += 1
                press_color = get_response_color(i, features)
                button_coords.append(coords[press_color])
                timestamp = time()
                if colors_matched == curr_match:
                    log(f"Color: {colors[i]}. Press: {colors[press_color]}",
                        LOG_DEBUG, "Simon Says")
                    return button_coords
        sleep(0.1)  # Lamps are lit for 0.25 seconds.
Ejemplo n.º 6
0
def get_button_color(image):
    color_ranges = config.BUTTON_COLOR_RANGE
    pixel = 210, 120
    for i, (low, high) in enumerate(color_ranges):
        rgb = feature_util.split_channels(image)
        if feature_util.color_in_range(pixel, rgb, low, high):
            return i
    return -1
Ejemplo n.º 7
0
def get_lights(rgb):
    coords = (52, 80, 110, 142, 172, 200)
    y = 43
    lit_lo = (200, 200, 150)
    lit_hi = (255, 255, 220)
    lights = [False] * 6
    for i, x in enumerate(coords):
        pixel = (y, x)
        if features_util.color_in_range(pixel, rgb, lit_lo, lit_hi):
            lights[i] = True
    return lights
Ejemplo n.º 8
0
def get_led_states(img):
    coords = [(195, 77), (219, 94), (236, 120), (236, 179), (219, 205),
              (195, 222), (204, 57), (236, 78), (258, 112), (258, 187),
              (236, 220), (204, 242)]
    lit_low = (130, 190, 25)
    lit_high = (220, 255, 100)
    rgb = features_util.split_channels(img)
    states = []
    for y, x in coords:
        states.append(
            features_util.color_in_range((y, x), rgb, lit_low, lit_high))
    return states
Ejemplo n.º 9
0
def get_indicator_ratio(img):
    min_y, max_y = 125, 246
    x = 66
    min_rgb = config.DISCHARGE_MIN_RED
    max_rgb = config.DISCHARGE_MAX_RED
    rgb = features_util.split_channels(img)
    filled_height = 0
    for y in range(min_y, max_y):
        if features_util.color_in_range((y, x), rgb, min_rgb, max_rgb):
            filled_height += 1

    total_height = max_y - min_y
    return filled_height / total_height
Ejemplo n.º 10
0
def get_lights(rgb):
    """
    Return a boolean list that describes whether each wire has a lit LED or not.
    """
    coords = (52, 80, 110, 142, 172, 200)
    y = 43
    lit_lo = (200, 200, 150)
    lit_hi = (255, 255, 220)
    lights = [False] * 6
    for i, x in enumerate(coords):
        pixel = (y, x)
        if features_util.color_in_range(pixel, rgb, lit_lo, lit_hi):
            lights[i] = True
    return lights
Ejemplo n.º 11
0
def get_dial_orientation(img):
    dial_y_min, dial_x_min, dial_y_max, dial_x_max = 130, 118, 194, 182
    rgb = features_util.split_channels(img)
    mid_y = (dial_y_min + dial_y_max) / 2
    mid_x = (dial_x_min + dial_x_max) / 2
    offset = 16
    coords = [(mid_y - offset, mid_x), (mid_y, mid_x + offset),
              (mid_y + offset, mid_x), (mid_y, mid_x - offset)]
    red_min = (190, 30, 0)
    red_max = (255, 85, 40)
    for i, (y, x) in enumerate(coords):
        if features_util.color_in_range((int(y), int(x)), rgb, red_min,
                                        red_max):
            return i
    return -1
Ejemplo n.º 12
0
def get_start_and_end(img):
    red_l = (200, 0, 0)
    red_h = (255, 30, 40)
    white_l = (190, 190, 190)
    white_h = (255, 255, 255)
    rgb = features_util.split_channels(img)
    start_x = 17
    start_y = 16
    gap = 25
    start = None
    end = None
    for j in range(0, 6):
        y = start_y + j * gap
        for i in range(0, 6):
            x = start_x + i * gap
            pixel = (y, x)
            r, g, b = rgb
            if features_util.color_in_range(pixel, rgb, white_l, white_h):
                start = (i, j)
            elif features_util.color_in_range(pixel, rgb, red_l, red_h):
                end = (i, j)
    assert start is not None
    assert end is not None
    return start, end
Ejemplo n.º 13
0
def is_active(img):
    cropped = crop_image(img)
    h, w = cropped.shape[:2]
    y = h // 2
    step_x = w // 12
    start_x = (w // 10)
    min_red = (170, 0, 0)
    max_red = (255, 70, 70)
    rgb = features_util.split_channels(cropped)
    for i in range(1, 11):
        x = int(start_x + i * step_x)
        pixel = (y, x)
        if features_util.color_in_range(pixel, rgb, min_red, max_red):
            return True
    return False
Ejemplo n.º 14
0
def determine_alignment(image, bbox, lit):
    if lit:
        return lit
    mid_x = (bbox[2] + bbox[3]) // 2
    q = abs(bbox[3] - bbox[2]) // 4
    q1_x = (bbox[2] + q)
    q3_x = abs(bbox[2] - bbox[3]) - q + bbox[2]
    x_coords = [q1_x, mid_x, q3_x]
    y_coords = [bbox[1] - 30, bbox[1] - 60, bbox[0] + 30, bbox[0] + 60]
    for x in x_coords:
        for i, y in enumerate(y_coords):
            h, _ = image.shape[:2]
            if y >= h or y < 0:
                continue
            min_c, max_c = ((25, 25, 25), (45, 45, 45))
            rgb = features_util.split_channels(image)
            pixel = (y, x)
            if features_util.color_in_range(pixel, rgb, min_c, max_c):
                return 1 if i < 2 else -1
    return 0
Ejemplo n.º 15
0
def get_wire_colors(img):
    Colors = Enum("Colors", {"Red": 0, "Blue": 1, "Black": 2})
    coords = [  # Top to bottom.
        (91, 86), (102, 100), (102, 80), (127, 106), (138, 90), (146, 90),
        (174, 91), (173, 111), (184, 106)
    ]
    colors = [  # Red, Blue & Black.
        ((139, 0, 0), (255, 99, 71)), ((20, 20, 120), (130, 130, 255)),
        ((0, 0, 0), (10, 10, 10))
    ]
    rgb = features_util.split_channels(img)
    wires = [-1] * 3
    destinations = [-1] * 3
    coords_to_cut = [-1] * 3
    for i, pixel in enumerate(coords):
        for color, (lo, hi) in enumerate(colors):
            if features_util.color_in_range(pixel, rgb, lo, hi):
                coords_to_cut[i // 3] = coords[i]
                wires[i // 3] = color
                destinations[i // 3] = i % 3
    return wires, destinations, coords_to_cut
Ejemplo n.º 16
0
def is_solved(image):
    rgb = feature_util.split_channels(cv2.cvtColor(image, cv2.COLOR_RGB2BGR))
    pixel = (18, 270)
    lit_low = (0, 200, 0)
    lit_high = (50, 255, 50)
    return feature_util.color_in_range(pixel, rgb, lit_low, lit_high)
Ejemplo n.º 17
0
def solve(img, features):
    h, w, c = img.shape

    # Coordinates of wire endpoints.
    coords = [(40, 70), (80, 74), (118, 74), (157, 74), (198, 70), (240, 72)]
    # Colords of wires.
    color_ranges = config.WIRE_COLOR_RANGE
    Colors = Enum("Colors", {
        "Black": 0,
        "Yellow": 1,
        "Blue": 2,
        "White": 3,
        "Red": 4
    })
    num_wires = 0
    color_hist = [0, 0, 0, 0, 0]
    wire_hist = [-1, -1, -1, -1, -1, -1]
    rgb = features_util.split_channels(img)
    for i, coord in enumerate(coords):
        for j, (low, high) in enumerate(color_ranges):
            if features_util.color_in_range(coord, rgb, low, high):
                color_hist[j] += 1
                wire_hist[i] = j
                num_wires += 1
                log(f"Wire {i+1} is {Colors(j)}", LOG_DEBUG, "Wires")
                break

    serial_odd = features.get("last_serial_odd", None)
    if serial_odd is None:
        log("WARNING: Serial number information not provided", LOG_WARNING,
            "Wires")
        raise ValueError  # Something went wrong.

    if num_wires == 3:
        if color_hist[Colors.Red.value] == 0:  # There are no red wires.
            return get_nth_wire(wire_hist, 1), coords  # Cut second wire.
        last_wire = get_nth_wire(wire_hist, -1)
        if wire_hist[last_wire] == Colors.White.value:  # Last wire is white.
            return get_nth_wire(wire_hist, -1), coords  # Cut last wire
        if color_hist[Colors.Blue.value] > 1:  # More than one blue wire.
            return get_nth_wire(
                wire_hist, -1,
                Colors.Blue.value), coords  # Cut last blue wire.
        return get_nth_wire(wire_hist, -1), coords  # Cut the last wire.
    if num_wires == 4:
        if color_hist[
                Colors.Red.
                value] > 1 and serial_odd:  # More than one red wire + serial number odd.
            return get_nth_wire(wire_hist, -1,
                                Colors.Red.value), coords  # Cut last red wire.
        last_wire = get_nth_wire(wire_hist, -1)
        # Last wire is yellow + no red wires.
        if wire_hist[last_wire] == Colors.Yellow.value and color_hist[
                Colors.Red.value] == 0:
            return get_nth_wire(wire_hist, 0), coords  # Cut the first wire.
        if color_hist[Colors.Blue.value] == 1:  # Exactly one blue wire.
            return get_nth_wire(wire_hist, 0), coords  # Cut the first wire.
        if color_hist[Colors.Yellow.value] > 1:  # More than one yellow wire.
            return get_nth_wire(wire_hist, -1,
                                Colors.Red.value), coords  # Cut last red wire.
        return get_nth_wire(wire_hist, 1), coords  # Cut the second wire.
    if num_wires == 5:
        last_wire = get_nth_wire(wire_hist, -1)
        # Last wire is black + serial number odd.
        if wire_hist[last_wire] == Colors.Black.value and serial_odd:
            return get_nth_wire(wire_hist, 3), coords  # Cut the fourth wire.
        # One red wire + more than one yellow.
        if color_hist[
                Colors.Red.value] == 1 and color_hist[Colors.Yellow.value] > 1:
            return get_nth_wire(wire_hist, 0), coords  # Cut the first wire.
        if color_hist[Colors.Black.value] == 0:  # No black wires.
            return get_nth_wire(wire_hist, 1), coords  # Cut the second wire.
        return get_nth_wire(wire_hist, 0), coords  # Cut the first wire.
    if num_wires == 6:
        if color_hist[
                Colors.Yellow.
                value] == 0 and serial_odd:  # No yellow wires + serial number odd.
            return get_nth_wire(wire_hist, 2), coords  # Cut the third wire.
        # One yellow + more than one white.
        if color_hist[Colors.Yellow.
                      value] == 1 and color_hist[Colors.White.value] > 1:
            return get_nth_wire(wire_hist, 3), coords  # Cut the fourth wire.
        if color_hist[Colors.Red.value] == 0:  # No red wires.
            return get_nth_wire(wire_hist, -1), coords  # Cut last wire.
        return get_nth_wire(wire_hist, 3), coords  # Cut the fourth wire.
    log("WARNING: Invalid number of wires.", LOG_WARNING, "Wires")
    raise ValueError  # Something went wrong.
Ejemplo n.º 18
0
 def bomb_exploded(self, rgb):
     lo = (0, 0, 0)
     hi = (3, 3, 3)
     return features_util.color_in_range(self.pixel, rgb, lo, hi)
Ejemplo n.º 19
0
def solve(img, features):
    # Coordinates of wire endpoints.
    coords = [(40, 70), (80, 74), (118, 74), (157, 74), (198, 70), (240, 72)]
    # Colors of wires.
    color_ranges = config.WIRE_COLOR_RANGE
    Colors = Enum("Colors", {
        "Black": 0,
        "Yellow": 1,
        "Blue": 2,
        "White": 3,
        "Red": 4
    })
    num_wires = 0
    color_hist = [0, 0, 0, 0, 0]  # Histogram of color occurences.
    wire_colors = [-1, -1, -1, -1, -1,
                   -1]  # Color of each wire. -1 means wire is missing.
    rgb = features_util.split_channels(img)
    radius = 5

    # Look through coordinates for each wire and check if a color matches that pixel.
    for i, coord in enumerate(coords):
        valid_colors = [0] * len(color_ranges)
        max_color_index = 0
        max_color_count = 0

        for j, (low, high) in enumerate(
                color_ranges):  # Run through each possible color range.
            for m in range(coord[0] - radius, coord[0] +
                           radius):  # Look in a 5px radius around pixel.
                for n in range(coord[1] - radius, coord[1] + radius):
                    if features_util.color_in_range((m, n), rgb, low,
                                                    high):  # Color detected.
                        valid_colors[
                            j] += 1  # Record occurence of current color.
                        if valid_colors[
                                j] > max_color_count:  # Track most seen color.
                            max_color_count = valid_colors[j]
                            max_color_index = j

        if max_color_count > 10:  # Assume no wire is present if too few pixels matched a color.
            color_hist[max_color_index] += 1  # Record occurence of wire color.
            wire_colors[
                i] = max_color_index  # Record what color the ith wire is.
            num_wires += 1
            log(f"Wire {i+1} is {Colors(max_color_index)}", LOG_DEBUG, "Wires")

    serial_odd = features.get("last_serial_odd", None)
    if num_wires > 3 and serial_odd is None:
        # Serial number was not previous detected correctly.
        # If we depend on this info to solve wires, raise an error.
        log("WARNING: Serial number information not provided", LOG_WARNING,
            "Wires")
        raise ValueError

    if num_wires == 3:
        if color_hist[Colors.Red.value] == 0:  # There are no red wires.
            return get_nth_wire(wire_colors, 1), coords  # Cut second wire.
        last_wire = get_nth_wire(wire_colors, -1)
        if wire_colors[last_wire] == Colors.White.value:  # Last wire is white.
            return get_nth_wire(wire_colors, -1), coords  # Cut last wire
        if color_hist[Colors.Blue.value] > 1:  # More than one blue wire.
            return get_nth_wire(
                wire_colors, -1,
                Colors.Blue.value), coords  # Cut last blue wire.
        return get_nth_wire(wire_colors, -1), coords  # Cut the last wire.
    if num_wires == 4:
        if color_hist[
                Colors.Red.
                value] > 1 and serial_odd:  # More than one red wire + serial number odd.
            return get_nth_wire(wire_colors, -1,
                                Colors.Red.value), coords  # Cut last red wire.
        last_wire = get_nth_wire(wire_colors, -1)
        # Last wire is yellow + no red wires.
        if wire_colors[last_wire] == Colors.Yellow.value and color_hist[
                Colors.Red.value] == 0:
            return get_nth_wire(wire_colors, 0), coords  # Cut the first wire.
        if color_hist[Colors.Blue.value] == 1:  # Exactly one blue wire.
            return get_nth_wire(wire_colors, 0), coords  # Cut the first wire.
        if color_hist[Colors.Yellow.value] > 1:  # More than one yellow wire.
            return get_nth_wire(wire_colors, -1,
                                Colors.Red.value), coords  # Cut last red wire.
        return get_nth_wire(wire_colors, 1), coords  # Cut the second wire.
    if num_wires == 5:
        last_wire = get_nth_wire(wire_colors, -1)
        # Last wire is black + serial number odd.
        if wire_colors[last_wire] == Colors.Black.value and serial_odd:
            return get_nth_wire(wire_colors, 3), coords  # Cut the fourth wire.
        # One red wire + more than one yellow.
        if color_hist[
                Colors.Red.value] == 1 and color_hist[Colors.Yellow.value] > 1:
            return get_nth_wire(wire_colors, 0), coords  # Cut the first wire.
        if color_hist[Colors.Black.value] == 0:  # No black wires.
            return get_nth_wire(wire_colors, 1), coords  # Cut the second wire.
        return get_nth_wire(wire_colors, 0), coords  # Cut the first wire.
    if num_wires == 6:
        if color_hist[
                Colors.Yellow.
                value] == 0 and serial_odd:  # No yellow wires + serial number odd.
            return get_nth_wire(wire_colors, 2), coords  # Cut the third wire.
        # One yellow + more than one white.
        if color_hist[Colors.Yellow.
                      value] == 1 and color_hist[Colors.White.value] > 1:
            return get_nth_wire(wire_colors, 3), coords  # Cut the fourth wire.
        if color_hist[Colors.Red.value] == 0:  # No red wires.
            return get_nth_wire(wire_colors, -1), coords  # Cut last wire.
        return get_nth_wire(wire_colors, 3), coords  # Cut the fourth wire.
    log("WARNING: Invalid number of wires.", LOG_WARNING, "Wires")
    raise ValueError  # Something went wrong.
Ejemplo n.º 20
0
def is_lit(pixel, rgb):
    lit_low = (180, 180, 40)
    lit_high = (255, 255, 100)
    return features_util.color_in_range(pixel, rgb, lit_low, lit_high)