Example #1
0
 def testBox2DCornerAxisAligned(self):
   # Center at 1., 1., width of 1. and length of 2.
   #
   # The heading of 0. indicates the heading of the 'long'
   # side of the box, so it is longer in the positive y direction.
   box = transform_util.Box2D(1.0, 1.0, 2., 1., 0.)
   self.assertAllClose(box.corners,
                       [[0.5, 2.], [1.5, 2.], [1.5, 0.], [0.5, 0.]])
Example #2
0
def DrawBoundingBoxOnImage(image,
                           box,
                           display_str,
                           color='red',
                           thickness=4,
                           text_loc='BOTTOM'):
    """Draw bounding box on the input image."""
    original_image = image
    image = Image.fromarray(np.uint8(original_image)).convert('RGB')
    draw = ImageDraw.Draw(image)

    center_x, center_y, width, height, heading = box
    box2d = transform_util.Box2D(center_x, center_y, width, height, heading)
    corners = list(box2d.corners.reshape(-1, 2))
    points = [tuple(c) for c in corners]
    points += [points[0]]
    draw.line(points, fill=color, width=thickness)

    # Draw heading.
    max_dim = max(width, height) / 2.
    end_heading_point = (center_x + max_dim * math.cos(heading),
                         center_y + max_dim * math.sin(heading))
    start_heading_point = ((end_heading_point[0] - center_x) / 2 + center_x,
                           (end_heading_point[1] - center_y) / 2 + center_y)

    heading_points = [start_heading_point, end_heading_point]
    draw.line(heading_points, fill=color, width=thickness)

    # Compute extremes so we can anchor the labels to them.
    xs = [x[0] for x in points]
    ys = [x[1] for x in points]
    left = np.min(xs)
    bottom = np.min(ys)
    top = np.max(ys)

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

    text_width, text_height = font.getsize(display_str)
    margin = np.ceil(0.05 * text_height)
    if text_loc == 'TOP':
        text_bottom = top
    else:
        text_bottom = bottom + text_height

    draw.rectangle([(left, text_bottom - text_height - 2 * margin),
                    (left + text_width, text_bottom)],
                   fill=color)
    draw.text((left + margin, text_bottom - text_height - margin),
              display_str,
              fill='black',
              font=font)
    np.copyto(original_image, np.array(image))
Example #3
0
def TransformBBoxesToTopDown(bboxes, car_to_image_transform=None):
    """Convert bounding boxes from car coordinates to top down pixel coordinates.

  Args:
    bboxes: A (batch, nbboxes, 4 or 5) np.float32 tensor containing bounding box
      xywhh in car coordinates (smooth adjusted by car pose).
    car_to_image_transform: An optional Transform object. If None, this will be
      created using _CarToImageTransform.

  Returns:
    np.array of shape (batch, nbboxes) containing the bounding boxes in top down
    image space.
  """
    if car_to_image_transform is None:
        car_to_image_transform = _CarToImageTransform()

    batch_size = np.shape(bboxes)[0]
    nbboxes = np.shape(bboxes)[1]
    transformed_boxes = np.zeros_like(bboxes)

    for batch_id in range(batch_size):
        for box_id in range(nbboxes):
            # TODO(vrv): When we predict heading, we should assert
            # that the length of bbox_data is 5.
            bbox_data = np.squeeze(bboxes[batch_id, box_id, :])

            x, y, width, height = (bbox_data[0], bbox_data[1], bbox_data[2],
                                   bbox_data[3])

            if len(bbox_data) == 5:
                heading = bbox_data[4]
            else:
                heading = 0.0

            # Skip boxes that cannot be visualized.
            if width <= 0 or height <= 0:
                continue
            if any([np.isnan(c) or np.isinf(c) for c in bbox_data]):
                continue

            # Bounding boxes are in car coordinates (smooth adjusted by car pose).
            # Transform from car coordinates to new coordinates.
            bbox_car = transform_util.Box2D(x, y, width, height, heading)
            bbox_transformed = bbox_car.Apply(car_to_image_transform)
            bbox_values = bbox_transformed.AsNumpy()
            if len(bbox_data) == 4:
                bbox_values = bbox_values[:-1]
            transformed_boxes[batch_id, box_id, :] = bbox_values

    return transformed_boxes
Example #4
0
  def testBox2DTransform(self):
    # Take the box from above and apply a car-image transform.
    box = transform_util.Box2D(1.0, 1.0, 2., 1., 0.)
    transform = transform_util.MakeCarToImageTransform(
        pixels_per_meter=10.0, image_ref_x=250, image_ref_y=750, flip_axes=True)
    new_box = box.Apply(transform)

    # The center flips across the x=y axis to -1, -1.  After the scaling and
    # translation, the box should be centered (240, 740).  Because the box flips
    # across the axis, the width and length get flipped from 2, 1 to [10, 20].
    #
    # The flip axes should cause the heading to go from 0. to -pi/2.
    self.assertAllClose([240., 740., 10., 20., -np.pi / 2.], new_box.AsNumpy())

    # Check ymin/xmin/ymax/xmax: the rectangle is now longer in the y-dimension
    # than the x-dimension.
    self.assertAllClose((730., 235., 750., 245.), new_box.Extrema())
Example #5
0
def DrawBBoxesOnImages(images, bboxes, box_weights, labels, class_id_to_name,
                       groundtruth):
    """Draw ground truth boxes on top down image.

  Args:
    images: A 4D uint8 array (batch, height, width, depth) of images to draw on
      top of.
    bboxes: A (batch, nbboxes, 4 or 5) np.float32 tensor containing bounding box
      xywhh to draw specified in top down pixel values.
    box_weights: A (batch, nbboxes) float matrix indicating the predicted score
      of the box.  If the score is 0.0, no box is drawn.
    labels: A (batch, nbboxes) integer matrix indicating the true or predicted
      label indices.
    class_id_to_name: Dictionary mapping from class id to name.
    groundtruth: Boolean indicating whether bounding boxes are ground truth.

  Returns:
    'images' with the bboxes drawn on top.
  """
    # Assert 4d shape.
    assert len(np.shape(images)) == 4

    if np.shape(images)[3] == 1:
        # Convert from grayscale to RGB.
        images = np.tile(images, (1, 1, 1, 3))

    # Assert channel dimension is 3 dimensional.
    assert np.shape(images)[3] == 3

    batch_size = np.shape(images)[0]
    nbboxes = np.shape(bboxes)[1]

    for batch_id in range(batch_size):
        image = images[batch_id, :, :, :]
        # Draw a box for each box and label if weights is 1.

        transformed_boxes = []
        box_scores = []
        label_ids = []

        for box_id in range(nbboxes):
            box_weight = box_weights[batch_id, box_id]
            # If there is no box to draw, continue.
            if box_weight == 0.0:
                continue

            # TODO(vrv): When we predict heading, we should assert
            # that the length of bbox_data is 5.
            bbox_data = np.squeeze(bboxes[batch_id, box_id, :])
            if len(bbox_data) == 5:
                x, y, width, length, heading = bbox_data
            else:
                x, y, width, length = bbox_data
                heading = 0.0

            # Check whether we can draw the box.
            bbox = transform_util.Box2D(x, y, width, length, heading)
            ymin, xmin, ymax, xmax = bbox.Extrema()

            if ymin == 0 and xmin == 0 and ymax == 0 and xmax == 0:
                continue

            # TODO(vrv): Support drawing boxes on the edge of the
            # image.
            if (xmin < 0 or ymin < 0 or xmax >= image.shape[1]
                    or ymax >= image.shape[0]):
                continue

            # We can draw a box on the image, so fill in the score, the boxes,
            # and the label.
            transformed_boxes.append([x, y, width, length, heading])
            box_scores.append(box_weight)
            label_ids.append(labels[batch_id, box_id])

        if transformed_boxes:
            transformed_boxes = np.stack(transformed_boxes, axis=0)
            scores = None if groundtruth else np.array(box_scores)
            text_loc = 'TOP' if groundtruth else 'BOTTOM'
            VisualizeBoxes(image=image,
                           boxes=transformed_boxes,
                           classes=label_ids,
                           scores=scores,
                           class_id_to_name=class_id_to_name,
                           groundtruth_box_visualization_color='cyan',
                           skip_scores=groundtruth,
                           skip_labels=False,
                           text_loc=text_loc)
    return images
Example #6
0
 def testBox2DCornerRotated(self):
   # Like above but rotated 90 degrees; the order is important.
   box = transform_util.Box2D(1.0, 1.0, 2., 1., np.pi / 2.)
   self.assertAllClose(box.corners,
                       [[0., 0.5], [0., 1.5], [2., 1.5], [2., 0.5]])