def testTransformPoint(self):
   transform = transform_util.MakeCarToImageTransform(
       pixels_per_meter=10.0,
       image_ref_x=250,
       image_ref_y=750,
       flip_axes=False)
   tx, ty, tz = transform_util.TransformPoint(transform, 0.0, 1.0, 0.0)
   # X gets translated.
   self.assertEqual(250., tx)
   # Y gets translated and scaled by pixels_per_meter.
   self.assertEqual(760., ty)
   self.assertEqual(0., tz)
 def testCopyTransform(self):
   # Same transform as above.
   transform = transform_util.MakeCarToImageTransform(
       pixels_per_meter=10.0,
       image_ref_x=250,
       image_ref_y=750,
       flip_axes=False)
   # Test that copying the transform yields the same result.
   copy_transform = transform_util.CopyTransform(transform)
   tx, ty, tz = transform_util.TransformPoint(copy_transform, 0.0, 1.0, 0.0)
   self.assertEqual(250., tx)
   self.assertEqual(760., ty)
   self.assertEqual(0., tz)
Exemple #3
0
def DrawTopDown(lasers):
    """Draw the laser points in the top down car view."""
    # For every laser point, convert the point to a top down image.

    # Lasers is a [r, b, s*6] tensor where b is the batch size.
    # Transpose back to batch major
    lasers = np.transpose(lasers, [1, 0, 2])
    # Reshape data to get all points in the spin.
    lasers = np.reshape(lasers, [np.shape(lasers)[0], -1])

    car_to_image_transform = _CarToImageTransform()

    # Create an empty image of the appropriate size.
    batch_size = min(8, np.shape(lasers)[0])
    images = np.zeros(shape=(batch_size, 1000, 500, 3), dtype=np.uint8)

    # TODO(vrv): Slice the lasers into [b, x, y, z] matrix
    # and then do a batch_matmul on all points at once.
    max_npoints = np.shape(lasers)[1] // 6
    for b in range(batch_size):
        for i in range(max_npoints):
            index = i * 6
            x = lasers[b][index]
            y = lasers[b][index + 1]
            z = lasers[b][index + 2]

            # TODO(vrv): Use lasers_padding to filter out invalid points.
            # For now, just assume that all zeros means that the point
            # shouldn't be drawn.
            if x == 0 and y == 0 and z == 0:
                continue

            tx, ty, _ = transform_util.TransformPoint(car_to_image_transform,
                                                      x, y, z)
            # Point outside image.
            if tx < 0 or ty < 0 or tx >= images.shape[2] or ty >= images.shape[
                    1]:
                continue

            # Fill in that point in the image
            images[b, int(ty), int(tx), :] = (255, 255, 255)

    return images
    def _DrawLasers(self, images, points_xyz, points_padding, transform):
        """Draw laser points."""
        for batch_idx in range(images.shape[0]):
            for points_idx in range(points_xyz.shape[1]):
                if points_padding[batch_idx, points_idx] == 0:
                    x, y, z = points_xyz[batch_idx, points_idx, :3]
                    tx, ty, _ = transform_util.TransformPoint(
                        transform, x, y, z)
                    if tx < 0 or ty < 0 or tx >= images.shape[
                            2] or ty >= images.shape[1]:
                        continue

                    # Drop ground points from visualization.
                    if z < self._ground_removal_threshold:
                        # Brown out the color for ground points.
                        color = (64, 48, 48)
                    else:
                        color = (255, 255, 255)

                    images[batch_idx, int(ty), int(tx), :] = color
Exemple #5
0
def DrawTrajectory(image, bboxes, masks, labels, is_groundtruth):
    """Draw the trajectory of bounding boxes on 'image'.

  Args:
    image: The uint8 image array to draw on.  Assumes [1000, 500, 3] input with
      RGB value ranges.
    bboxes: A [num_steps, num_objects, 5] float array containing the bounding
      box information over a sequence of steps.  bboxes are expected to be in
      car coordinates.
    masks: A [num_steps, num_objects] integer array indicating whether the
      corresponding bbox entry in bboxes is present (1 = present).
    labels: A [num_steps, num_objects] integer label indicating which class is
      being predicted.  Used for colorizing based on labels.
    is_groundtruth: True if the scene is the groundtruth vs. the predicted.

  Returns:
    The updated image array.
  """
    image = Image.fromarray(np.uint8(image)).convert('RGB')
    draw = ImageDraw.Draw(image)

    try:
        font = ImageFont.truetype('arial.ttf', 20)
    except IOError:
        font = ImageFont.load_default()

    pixels_per_meter = 10.
    image_ref_x = 250.
    image_ref_y = 750.
    car_to_image_transform = transform_util.MakeCarToImageTransform(
        pixels_per_meter=pixels_per_meter,
        image_ref_x=image_ref_x,
        image_ref_y=image_ref_y,
        flip_axes=True)

    # Iterate over each object and produce the series of visualized trajectories
    # over time.
    for object_idx in range(bboxes.shape[1]):
        # Annotate the box with the class type
        label = labels[0, object_idx]

        # Choose a label_consistent color.
        color = PIL_COLOR_LIST[label % len(PIL_COLOR_LIST)]
        # Make predictions white.
        if not is_groundtruth:
            color = 'white'

        # Convert string color name to RGB so we can manipulate it.
        color_rgb = ImageColor.getrgb(color)

        # For each sample, extract the data, transform to image coordinates, and
        # store in centroids.
        centroids = []
        for time in range(bboxes.shape[0]):
            if masks[time, object_idx] == 0:
                continue

            center_x, center_y, width, height, heading = bboxes[time,
                                                                object_idx, :]

            # Compute the new heading.
            heading = transform_util.TransformHeading(car_to_image_transform,
                                                      heading)

            # Transform from car to image coords.
            x, y, _ = transform_util.TransformPoint(car_to_image_transform,
                                                    center_x, center_y, 0.0)

            # Hack to scale from meters to pixels.
            width *= pixels_per_meter
            height *= pixels_per_meter

            # Collect the centroids of all of the points.
            centroids.append((x, y, heading))

            # Draw the groundtruth bounding box at the first timestep.
            if is_groundtruth and time == 0:
                # Draw a rectangle
                rect = MakeRectangle(height, width, heading, offset=(x, y))
                rect += [rect[0]]
                draw.line(rect, fill=color_rgb, width=4)

                delta = 20

                # Annotate the box with the object index
                draw.text((x + delta, y + delta),
                          str(object_idx),
                          fill='white',
                          font=font)

                # Draw a callout
                draw.line([(x, y), (x + delta, y + delta)],
                          fill='white',
                          width=1)

        # Extract the point pairs from centroids and draw a line through them.
        point_pairs = []
        for (x, y, heading) in centroids:
            point_pairs.append((x, y))
        if point_pairs:
            draw.line(point_pairs, width=4, fill=color_rgb)

        # Draw the centroids.
        triangle_color_rgb = color_rgb
        for i, (x, y, heading) in enumerate(centroids):
            if i == 0:
                # Draw the heading for the first timestep.
                scale = 25 if is_groundtruth else 15
                DrawHeadingTriangle(draw, x, y, heading, triangle_color_rgb,
                                    scale)
            else:
                # Draw a circle for the centroids of other timesteps.
                outline_color = color_rgb
                circle_size = 5 if is_groundtruth else 3
                DrawCircle(draw,
                           x,
                           y,
                           fill=triangle_color_rgb,
                           outline=outline_color,
                           circle_size=circle_size)

            # Desaturate the color with every timestep.
            increment = 45  # Allow this to be modified?
            triangle_color_rgb = (triangle_color_rgb[0] - increment,
                                  triangle_color_rgb[1] - increment,
                                  triangle_color_rgb[2] - increment)

    return np.array(image)