Beispiel #1
0
 def __init__(self):
     self._rect_finder = RectFinder()
     self._image = None
     self._contour_filter = ContourFilter(min_size_scale = 0.7, max_size_scale = 1.25, min_aspect_ratio = 0.75, max_aspect_ratio = 2.25)
Beispiel #2
0
class PlayfieldDetector(Detector):
    LEFT_MASK_AREA_WIDTH = 5
    RELATIVE_PLAYFIELD_AREA_SIZE = Vector2(0.95, 0.65)

    def __init__(self):
        self._rect_finder = RectFinder()
        self._image = None
        self._contour_filter = ContourFilter(min_size_scale = 0.7, max_size_scale = 1.25, min_aspect_ratio = 0.75, max_aspect_ratio = 2.25)

    def detect(self, image):
        self._image = image
        self._contour_filter.target_size = image.size * self.RELATIVE_PLAYFIELD_AREA_SIZE
        return self._perform_detection(image)

    def _perform_detection(self, image):
        playfield_mask = self._create_playfield_mask(image)
        playfield_contour = self._find_playfield_contour(playfield_mask, image)
        playfield_rect, detected_corners = self._find_rect_corners(playfield_contour)
        self._adjust_playfield_width(image, playfield_rect)
        return Playfield(playfield_rect)

    def _create_playfield_mask(self, image):
        mask = self._create_mask(image, ColorRange(Color.from_hsv(0, 0, 0), Color.from_hsv(360, 255, 75)), closure_kernel_size = 14)
        mask.invert()
        self._draw_left_exclusion_area(mask, image)
        self._draw_right_exclusion_area(mask, image)
        return mask

    def _draw_left_exclusion_area(self, mask, image):
        OpenCV.fill_rectangle(mask, Rect.from_size(Vector2(self.LEFT_MASK_AREA_WIDTH, image.height)), Color.BLACK)

    def _draw_right_exclusion_area(self, mask, image):
        charging_station_area_width = ChargingStation.PHYSICAL_SIZE_CM.width / Playfield.PHYSICAL_SIZE_CM.width * image.width
        OpenCV.fill_rectangle(mask, Rect(Vector2(image.width - charging_station_area_width, 0), Vector2(charging_station_area_width, image.height)), Color.BLACK)

    def _find_playfield_contour(self, playfield_mask, image):
        contours = self._find_contours(playfield_mask, image)
        playfield_contours = self._contour_filter.filter_contours(contours)
        self._log_contour_detection_step("Playfield Contours", playfield_contours, self._image)
        if len(playfield_contours) != 1:
            raise DetectionError("Playfield detection failed. Detected contours: {0}.".format(len(playfield_contours)))
        return playfield_contours[0]

    def _find_rect_corners(self, playfield_contour):
        table_rect, detected_corners =  self._rect_finder.find_rectangle(playfield_contour)
        self._log_rect_corners_detection_step(table_rect, detected_corners)
        return table_rect, detected_corners

    def _adjust_playfield_width(self, image, playfield_rect):
        playfield_rect.left = 0
        playfield_rect.width = playfield_rect.height * Playfield.PHYSICAL_SIZE_CM.aspect_ratio

    # Logging

    def _log_rect_corners_detection_step(self, table_rect, detected_corners):
        if Logger.get_instance().save_blob_data:
            self._image.save_state()
            OpenCV.draw_rectangle(self._image, table_rect, Color.YELLOW, thickness = 3)
            for corner in detected_corners:
                OpenCV.draw_circle(self._image, Vector2(corner[0], corner[1]), radius = 10, color = Color.RED, thickness = 3)
            self._log_detection_step("Playfield Rect Corners", self._image)
            self._image.restore_state()

    def _log_playfield_detection_step(self, image, playfield_rect):
       if Logger.get_instance().save_blob_data:
            self._image.save_state()
            image.crop(playfield_rect)
            self._log_detection_step("Playfield", image)
            self._image.restore_state()