Exemplo n.º 1
0
 def _PointIsCloseToPreviousCorners(self, point):
     """True if the point is close to the previous corners."""
     max_dist = self.MAX_INTERFRAME_MOTION
     if cv_util.SqDistance(self._prev_corners[0], point) <= max_dist or \
        cv_util.SqDistance(self._prev_corners[1], point) <= max_dist or \
        cv_util.SqDistance(self._prev_corners[2], point) <= max_dist or \
        cv_util.SqDistance(self._prev_corners[3], point) <= max_dist:
         return True
     return False
Exemplo n.º 2
0
    def _GetTransform(self, corners, border):
        """Gets the perspective transform of the screen.

    Args:
      corners: The corners of the detected screen.
      border: The number of pixels of border to crop along with the screen.

    Returns:
      A perspective transform and the width and height of the target
      transform.

    Raises:
      ScreenNotFoundError: Something went wrong in detecting the screen."""
        if self._screen_size is None:
            w = np.sqrt(cv_util.SqDistance(corners[1], corners[0]))
            h = np.sqrt(cv_util.SqDistance(corners[1], corners[2]))
            if w < 1 or h < 1:
                raise self.ScreenNotFoundError(
                    'Screen detected improperly (bad corners)')
            if min(w, h) < self.MIN_SCREEN_WIDTH:
                raise self.ScreenNotFoundError(
                    'Detected screen was too small.')

            self._screen_size = (w, h)
            # Extend min line length, if we can, to reduce the number of extraneous
            # lines the line finder finds.
            self._min_line_length = max(self._min_line_length,
                                        min(w, h) / 1.75)
        w = self._screen_size[0]
        h = self._screen_size[1]

        target = np.zeros((4, 2), np.float32)
        width = w + border
        height = h + border
        target[0] = np.asfarray((width, border))
        target[1] = np.asfarray((border, border))
        target[2] = np.asfarray((border, height))
        target[3] = np.asfarray((width, height))
        transform_w = width + border
        transform_h = height + border
        transform = cv2.getPerspectiveTransform(corners, target)
        return transform, transform_w, transform_h
Exemplo n.º 3
0
    def _PointConnectsToCorners(self, corners, point_info, tolerance=1):
        """Checks if the lines of an intersection intersect with corners.

    This is useful to check if the point is part of a rectangle specified by
    |corners|.

    Args:
      point_info: A tuple of (point, line, line) representing an intersection
          of two lines.
      corners: corners that (hopefully) make up a rectangle.
      tolerance: The tolerance (approximately in pixels) of the distance
          between the corners and the lines for detecting if the point is on
          the line.

    Returns:
      True if each of the two lines that make up the intersection where the
      point is located connect the point to other corners."""
        line1_connected = False
        line2_connected = False
        point, line1, line2 = point_info
        for corner in corners:
            if corner is None:
                continue

            # Filter out points that are too close to one another to be different
            # corners.
            sqdist = cv_util.SqDistance(corner, point)
            if sqdist < self.MIN_SCREEN_WIDTH * self.MIN_SCREEN_WIDTH:
                continue

            line1_connected = line1_connected or \
                cv_util.IsPointApproxOnLine(corner, line1, tolerance)
            line2_connected = line2_connected or \
                cv_util.IsPointApproxOnLine(corner, line2, tolerance)
        if line1_connected and line2_connected:
            return True
        return False
Exemplo n.º 4
0
    def _NewScreenLocation(self, new_corners, missing_corners, intersections):
        """Computes the new screen location with best effort.

    Creates the final list of corners that represents the best effort attempt
    to find the new screen location. Handles degenerate cases where 3 or fewer
    new corners are present, using previous corner and intersection data.

    Args:
      new_corners: The corners found by our search for corners.
      missing_corners: The count of how many corners we're missing.
      intersections: The intersections of straight lines found in the current
          frame.

    Returns:
      An array of 4 new_corners hopefully representing the screen, or throws
      an error if this is not possible.

    Raises:
      ValueError: Finding the screen location was not possible."""
        screen_corners = copy.copy(new_corners)
        if missing_corners == 0:
            self._lost_corner_frames = 0
            self._lost_corners = [False, False, False, False]
            return screen_corners
        if self._prev_corners is None:
            raise self.ScreenNotFoundError(
                'Could not locate screen on frame %d' %
                self._frame_generator.CurrentFrameNumber)

        self._lost_corner_frames += 1
        if missing_corners > 1:
            logging.info(
                'Unable to properly detect screen corners, making '
                'potentially false assumptions on frame %d',
                self._frame_generator.CurrentFrameNumber)
        # Replace missing new_corners with either nearest intersection to previous
        # corner, or previous corner if no intersections are found.
        for i in xrange(0, 4):
            if not np.isnan(new_corners[i][0]):
                self._lost_corners[i] = False
                continue
            self._lost_corners[i] = True
            min_dist = self.MAX_INTERFRAME_MOTION
            min_corner = None

            for isection in intersections:
                dist = cv_util.SqDistance(isection[0], self._prev_corners[i])
                if dist >= min_dist:
                    continue
                if missing_corners == 1:
                    # We know in this case that we have 3 corners present, meaning
                    # all 4 screen lines, and therefore intersections near screen
                    # corners present, so our new corner must connect to these
                    # other corners.
                    if not self._PointConnectsToCorners(
                            new_corners, isection, 3):
                        continue
                min_corner = isection[0]
                min_dist = dist
            screen_corners[i] = min_corner if min_corner is not None else \
                self._prev_corners[i]

        return screen_corners