def get_has_parallel_port_for_side(side): side_w, side_h = get_dimens(side) if side_h > side_w: side = cv2.transpose(side) side_w, side_h = get_dimens(side) color = extract_color(side, 337 / 2, (75, 175), (175, 255)) contours = sorted(get_contours(color), key=cv2.contourArea) if not contours: return False contour = contours[-1] x, y, w, h = cv2.boundingRect(contour) width_percent = float(w) / side_w height_percent = float(h) / side_h return width_percent > _WIDTH_THRESHOLD and height_percent > _HEIGHT_THRESHOLD
def _get_digit_from_image(image): contours = get_contours(image, close_and_open=False) vertical_centers = [] horizontal_centers = [] for contour in contours: _, _, contour_w, contour_h = cv2.boundingRect(contour) center = get_center_for_contour(contour) if contour_w > contour_h: horizontal_centers.append(center) else: vertical_centers.append(center) w, h = get_dimens(image) segments = set() for x, y in vertical_centers: if x < w/2: if y < h/2: segments.add(Segments.TOP_LEFT) else: segments.add(Segments.BOTTOM_LEFT) else: if y < h/2: segments.add(Segments.TOP_RIGHT) else: segments.add(Segments.BOTTOM_RIGHT) for x, y in horizontal_centers: if y < h/3: segments.add(Segments.TOP_CENTER) elif h/3 < y < 2*h/3: segments.add(Segments.MIDDLE) else: segments.add(Segments.BOTTOM_CENTER) return _SEGMENTS_TO_NUMBER[tuple(sorted(segments, key=lambda seg: seg.value))]
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_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_square_positions(im, offset): colors_and_percents = ( (LitSquare.YELLOW, (0.722, 0.489)), (LitSquare.BLUE, (0.521, 0.297)), (LitSquare.RED, (0.339, 0.485)), (LitSquare.GREEN, (0.534, 0.69)), ) w, h = get_dimens(im) return { color: (offset[0] + int(x_percent * w), offset[1] + int(y_percent * h)) for color, (x_percent, y_percent) in colors_and_percents }
def _get_largest_contour_area_ratio_for_color(im, color): hue_out_of_360 = { LitSquare.YELLOW: 60, LitSquare.BLUE: 193, LitSquare.RED: 19, LitSquare.GREEN: 149, }[color] color_mat = extract_color(im, hue_out_of_360/2, (100, 255), (225, 255)) contour_areas = [cv2.contourArea(c) for c in get_contours(color_mat)] if contour_areas: largest_area = sorted(contour_areas)[-1] else: largest_area = 0 w, h = get_dimens(im) im_area = w * h area_ratio = float(largest_area) / im_area return area_ratio, color
def _get_largest_contour_area_ratio_for_color(im, color): hue_out_of_360 = { LitSquare.YELLOW: 60, LitSquare.BLUE: 193, LitSquare.RED: 19, LitSquare.GREEN: 149, }[color] color_mat = extract_color(im, hue_out_of_360 / 2, (100, 255), (225, 255)) contour_areas = [cv2.contourArea(c) for c in get_contours(color_mat)] if contour_areas: largest_area = sorted(contour_areas)[-1] else: largest_area = 0 w, h = get_dimens(im) im_area = w * h area_ratio = float(largest_area) / im_area return area_ratio, color
def get_wire_positions_and_colors(im): w, h = get_dimens(im) top = 10 * h / 100 bottom = 85 * h / 100 left = 48 * w / 100 right = 52 * w / 100 cropped = im[top:bottom, left:right, :] wires = [] wires.extend(_get_wire_positions(cropped, WireColor.black, (0, 180), (0, 255), (0, 50))) wires.extend(_get_wire_positions(cropped, WireColor.white, (0, 180), (0, 100), (200, 255))) wires.extend(_get_wire_positions(cropped, WireColor.blue, 227 / 2)) wires.extend(_get_wire_positions(cropped, WireColor.red, 7 / 2)) wires.extend(_get_wire_positions(cropped, WireColor.yellow, 55 / 2)) # Sort by height wires = sorted(wires, key=lambda ((x, y), color): y) # Add back in the top-left to the coordinates (since we cropped it out) wires = [((x + left, y + top), color) for ((x, y), color) in wires] # Separate positions and colors positions, colors = zip(*wires) return positions, colors
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_wire_positions_and_colors(im): w, h = get_dimens(im) top = 10 * h / 100 bottom = 85 * h / 100 left = 48 * w / 100 right = 52 * w / 100 cropped = im[top:bottom, left:right, :] wires = [] wires.extend( _get_wire_positions(cropped, WireColor.black, (0, 180), (0, 255), (0, 50))) wires.extend( _get_wire_positions(cropped, WireColor.white, (0, 180), (0, 100), (200, 255))) wires.extend(_get_wire_positions(cropped, WireColor.blue, 227 / 2)) wires.extend(_get_wire_positions(cropped, WireColor.red, 7 / 2)) wires.extend(_get_wire_positions(cropped, WireColor.yellow, 55 / 2)) # Sort by height wires = sorted(wires, key=lambda ((x, y), color): y) # Add back in the top-left to the coordinates (since we cropped it out) wires = [((x + left, y + top), color) for ((x, y), color) in wires] # Separate positions and colors positions, colors = zip(*wires) return positions, colors
def _get_digit_from_image(image): contours = get_contours(image, close_and_open=False) vertical_centers = [] horizontal_centers = [] for contour in contours: _, _, contour_w, contour_h = cv2.boundingRect(contour) center = get_center_for_contour(contour) if contour_w > contour_h: horizontal_centers.append(center) else: vertical_centers.append(center) w, h = get_dimens(image) segments = set() for x, y in vertical_centers: if x < w / 2: if y < h / 2: segments.add(Segments.TOP_LEFT) else: segments.add(Segments.BOTTOM_LEFT) else: if y < h / 2: segments.add(Segments.TOP_RIGHT) else: segments.add(Segments.BOTTOM_RIGHT) for x, y in horizontal_centers: if y < h / 3: segments.add(Segments.TOP_CENTER) elif h / 3 < y < 2 * h / 3: segments.add(Segments.MIDDLE) else: segments.add(Segments.BOTTOM_CENTER) return _SEGMENTS_TO_NUMBER[tuple( sorted(segments, key=lambda seg: seg.value))]
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
def _get_button_position(im): w, h = get_dimens(im) x = sum(_TEXT_X_PERCENTS) / 2.0 y = _TEXT_Y_PERCENTS[0] return int((x * w) / 100.0), int((y * h) / 100.0)