def __init__(self, coordinate_factory, robot_factory): self._coordinate_factory = coordinate_factory self._playfield_detector = PlayfieldDetector() self._robot_detector = RobotDetector(robot_factory) self._charging_station_detector = ChargingStationDetector(self._coordinate_factory) self._island_detector = IslandDetector(self._coordinate_factory) self._treasure_detector = TreasureDetector(self._coordinate_factory) self._image_straightening_angle = None self._image = None self._playfield = None self._robot = None self._charging_station = None self._islands = [] self._treasures = []
class WorldDetector(Detector): MAX_IMAGE_SIZE = Vector2(800, 600) RED_ISLAND_COLOR_RANGES = [ColorRange(Color.from_hsv(0, 100, 95), Color.from_hsv(20, 255, 255)), ColorRange(Color.from_hsv(340, 100, 100), Color.from_hsv(360, 255, 255))] YELLOW_ISLAND_COLOR_RANGE = ColorRange(Color.from_hsv(44, 170, 128), Color.from_hsv(80, 255, 255)) GREEN_ISLAND_COLOR_RANGE = ColorRange(Color.from_hsv(82, 100, 95), Color.from_hsv(168, 255, 255)) BLUE_ISLAND_COLOR_RANGE = ColorRange(Color.from_hsv(170, 100, 95), Color.from_hsv(250, 255, 255)) def __init__(self, coordinate_factory, robot_factory): self._coordinate_factory = coordinate_factory self._playfield_detector = PlayfieldDetector() self._robot_detector = RobotDetector(robot_factory) self._charging_station_detector = ChargingStationDetector(self._coordinate_factory) self._island_detector = IslandDetector(self._coordinate_factory) self._treasure_detector = TreasureDetector(self._coordinate_factory) self._image_straightening_angle = None self._image = None self._playfield = None self._robot = None self._charging_station = None self._islands = [] self._treasures = [] def detect_objects(self, image, world_object_types): self._image = image.clone() self._pre_process_image(self._image, world_object_types) if WorldObjectType.PLAYFIELD in world_object_types: self._playfield = self._detect_playfield(self._image) self._set_image_padding(self._image) if WorldObjectType.ROBOT in world_object_types and self._playfield is not None: self._robot = self._detect_robot(self._image, self._playfield) if WorldObjectType.CHARGING_STATION in world_object_types and self._playfield is not None: self._charging_station = self._detect_charging_station(self._image, self._playfield) if WorldObjectType.ISLAND in world_object_types and self._playfield is not None: self._islands = self._detect_islands(self._image, self._playfield, self._robot) if WorldObjectType.TREASURE in world_object_types and self._playfield is not None: self._treasures = self._detect_treasures(self._image, self._playfield, self._robot, self._islands) return WorldDescriptor(world_object_types, self._image, self._playfield, self._robot, self._charging_station, self._islands, self._treasures) def _pre_process_image(self, image, world_object_types): self._resize_image(image) self._straighten_image(image, world_object_types) self._set_image_brightness(image) def _resize_image(self, image): if image.size > self.MAX_IMAGE_SIZE: image.resize(image.size.shrink_to_fit(self.MAX_IMAGE_SIZE)) self._log_detection_step("Resize", image) def _straighten_image(self, image, world_object_types): if WorldObjectType.PLAYFIELD in world_object_types: self._image_straightening_angle = self._calculate_image_straightening_angle(image) image.rotate(-self._image_straightening_angle, ImageRotationMode.FIT_INNER) self._log_detection_step("Straighten", image) def _calculate_image_straightening_angle(self, image): grayscale_image = image.to_grayscale() self._log_detection_step("Convert to grayscale", grayscale_image) hough_lines = OpenCV.hough_lines(grayscale_image) return Segment.average_angle_snap_value(hough_lines) def _set_image_brightness(self, image): image.set_brightness(target_brightness_level = 150) self._log_detection_step("Brightness Adjust", image) def _detect_playfield(self, image): try: playfield = self._playfield_detector.detect(image) except DetectionError as e: Logger.get_instance().log(self, "Playfield Detection Failed", LogEntryType.DEBUG, error = e, blob_data = image) return None self._coordinate_factory.set_playfield(playfield) self._coordinate_factory.set_image_size(image.size) return playfield def _set_image_padding(self, image): if self._playfield is not None and self._playfield.rect.width > image.width: padding_value = (self._playfield.rect.width - image.width) / 2 image.pad(0, 0, padding_value, padding_value, Color.GRAY) def _detect_robot(self, image, playfield): try: return self._robot_detector.detect(image, playfield) except DetectionError as e: Logger.get_instance().log(self, "Robot Detection Failed", LogEntryType.DEBUG, error = e, blob_data = image) return None def _detect_charging_station(self, image, playfield): try: return self._charging_station_detector.detect(image, playfield) except DetectionError as e: Logger.get_instance().log(self, "Charging Station Detection Failed", LogEntryType.DEBUG, error = e, blob_data = image) return None def _detect_islands(self, image, playfield, robot): islands = [] islands.extend(self._island_detector.detect(image, playfield, self.RED_ISLAND_COLOR_RANGES, IslandColor.RED, robot)) islands.extend(self._island_detector.detect(image, playfield, self.YELLOW_ISLAND_COLOR_RANGE, IslandColor.YELLOW, robot)) islands.extend(self._island_detector.detect(image, playfield, self.GREEN_ISLAND_COLOR_RANGE, IslandColor.GREEN, robot)) islands.extend(self._island_detector.detect(image, playfield, self.BLUE_ISLAND_COLOR_RANGE, IslandColor.BLUE, robot)) return islands def _detect_treasures(self, image, playfield, robot, islands): return self._treasure_detector.detect(image, playfield, robot, islands)