Esempio n. 1
0
 def testTransformBBoxes3DConsistentWithPoints(self):
   num_boxes, num_points = 20, 100
   points = tf.random_uniform((num_points, 3))
   bboxes_3d = tf.random_uniform((num_boxes, 7))
   in_bboxes = geometry.IsWithinBBox3D(points, bboxes_3d)
   transforms = self._MakeTransformTestTranslationMatrices(1)[0]
   points_transformed = geometry.TransformPoints(points, transforms)
   bboxes_3d_transformed = geometry.TransformBBoxes3D(bboxes_3d, transforms)
   in_bboxes_transformed = geometry.IsWithinBBox3D(points_transformed,
                                                   bboxes_3d_transformed)
   with self.session() as sess:
     actual_in_bboxes, actual_in_bboxes_transformed = sess.run(
         (in_bboxes, in_bboxes_transformed))
   self.assertAllEqual(actual_in_bboxes, actual_in_bboxes_transformed)
Esempio n. 2
0
    def add_labels(self, feature, labels, points_xyz):
        """Add 3d bounding box labels into the output feature map.

    Args:
      feature: A tf.Example feature map.
      labels: A repeated car.open_dataset.Label proto.
      points_xyz: A numpy array of shape [-1, 3] with the pointcloud. This is
        used to calculate the number of points in each 3D bounding box.
    """
        label_classes = []
        label_ids = []
        detection_difficulty_levels = []
        tracking_difficulty_levels = []
        bboxes = []
        label_md = []

        for label in labels:
            box = label.box
            bbox_3d = [
                box.center_x, box.center_y, box.center_z, box.length,
                box.width, box.height, box.heading
            ]
            md = [
                label.metadata.speed_x, label.metadata.speed_y,
                label.metadata.accel_x, label.metadata.accel_y
            ]
            label_md += md
            bboxes += bbox_3d
            label_classes += [label.type]
            label_ids += [tf.compat.as_bytes(label.id)]
            detection_difficulty_levels += [label.detection_difficulty_level]
            tracking_difficulty_levels += [label.tracking_difficulty_level]

        # Calculate the number of points in each ground truth box which are needed
        # to fill in difficulty levels for each ground truth and to filter boxes
        # with less points than a configurable minimum.
        points_xyz = tf.convert_to_tensor(points_xyz, dtype=tf.float32)
        bboxes_3d = tf.convert_to_tensor(np.array(bboxes).reshape(-1, 7),
                                         dtype=tf.float32)
        points_in_bboxes_mask = geometry.IsWithinBBox3D(points_xyz, bboxes_3d)
        bboxes_3d_num_points = tf.reduce_sum(tf.cast(points_in_bboxes_mask,
                                                     tf.int32),
                                             axis=0,
                                             keepdims=False)
        bboxes_3d_num_points = bboxes_3d_num_points.numpy().reshape([-1])

        bboxes = np.array(bboxes).reshape(-1)
        label_md = np.array(label_md).reshape(-1)
        feature['labels'].int64_list.value[:] = label_classes
        feature['label_ids'].bytes_list.value[:] = label_ids
        feature['detection_difficulties'].int64_list.value[:] = (
            detection_difficulty_levels)
        feature['tracking_difficulties'].int64_list.value[:] = (
            tracking_difficulty_levels)
        feature['bboxes_3d'].float_list.value[:] = list(bboxes)
        feature['label_metadata'].float_list.value[:] = list(label_md)
        feature['bboxes_3d_num_points'].int64_list.value[:] = list(
            bboxes_3d_num_points)
def _GetFilteredBoundingBoxData(kitti_data):
    """Given a single batch element of data, process it for writing.

  Args:
    kitti_data: A NestedMap of KITTI input generator returned data with a batch
      size of 1.

  Returns:
    A NestedMap of all the output data we need to write per bounding box
    cropped pointclouds.
  """
    points = kitti_data.lasers.points_xyz
    points_feature = kitti_data.lasers.points_feature
    bboxes_3d = kitti_data.labels.bboxes_3d
    bboxes_3d_mask = kitti_data.labels.bboxes_3d_mask
    bboxes_3d = tf.boolean_mask(bboxes_3d, bboxes_3d_mask)

    if 'points_padding' in kitti_data.lasers:
        points_validity_mask = tf.cast(kitti_data.lasers.points_padding - 1,
                                       tf.bool)
        points = tf.boolean_mask(points, points_validity_mask)
        points_feature = tf.boolean_mask(points_feature, points_validity_mask)

    points_in_bboxes_mask = geometry.IsWithinBBox3D(points, bboxes_3d)

    output_map = py_utils.NestedMap()
    # Points and features contain the whole pointcloud, which we will use
    # per box boolean masks later in _ToTFExampleProto to subselect data per box.
    output_map.points = points
    output_map.points_feature = points_feature
    output_map.points_in_bboxes_mask = points_in_bboxes_mask

    output_map.source_id = kitti_data.labels.source_id

    # Add additional data
    output_keys = [
        'bboxes_3d',
        'labels',
        'texts',
        'occlusion',
        'difficulties',
        'truncation',
    ]
    for key in output_keys:
        output_map[key] = tf.boolean_mask(kitti_data.labels[key],
                                          kitti_data.labels.bboxes_3d_mask)
    return output_map
Esempio n. 4
0
    def testIsWithinBBox3D(self):
        num_points, num_bboxes = 19, 4
        # rotate the first box by pi / 2 so dim_x and dim_y are swapped.
        # The last box is a cube rotated by 45 degrees.
        bboxes = tf.constant([[1.0, 2.0, 3.0, 6.0, 0.4, 6.0, np.pi / 2],
                              [4.0, 5.0, 6.0, 7.0, 0.8, 7.0, 0.0],
                              [0.4, 0.3, 0.2, 0.1, 0.1, 0.2, 0.0],
                              [-10., -10., -10., 3., 3., 3., np.pi / 4]],
                             dtype=tf.float32)
        points = tf.constant(
            [
                [1.0, 2.0, 3.0],  # box 0 (centroid)
                [0.8, 2.0, 3.0],  # box 0 (below x)
                [1.1, 2.0, 3.0],  # box 0 (above x)
                [1.3, 2.0, 3.0],  # box 0 (too far x)
                [0.7, 2.0, 3.0],  # box 0 (too far x)
                [4.0, 5.0, 6.0],  # box 1 (centroid)
                [4.0, 4.6, 6.0],  # box 1 (below y)
                [4.0, 5.4, 6.0],  # box 1 (above y)
                [4.0, 4.5, 6.0],  # box 1 (too far y)
                [4.0, 5.5, 6.0],  # box 1 (too far y)
                [0.4, 0.3, 0.2],  # box 2 (centroid)
                [0.4, 0.3, 0.1],  # box 2 (below z)
                [0.4, 0.3, 0.3],  # box 2 (above z)
                [0.4, 0.3, 0.0],  # box 2 (too far z)
                [0.4, 0.3, 0.4],  # box 2 (too far z)
                [5.0, 7.0, 8.0],  # none
                [1.0, 5.0, 3.6],  # box0, box1
                [-11.6, -10., -10.],  # box3 (rotated corner point).
                [-11.4, -11.4, -10.],  # not in box3, would be if not rotated.
            ],
            dtype=tf.float32)
        expected_is_inside = np.array([
            [True, False, False, False],
            [True, False, False, False],
            [True, False, False, False],
            [False, False, False, False],
            [False, False, False, False],
            [False, True, False, False],
            [False, True, False, False],
            [False, True, False, False],
            [False, False, False, False],
            [False, False, False, False],
            [False, False, True, False],
            [False, False, True, False],
            [False, False, True, False],
            [False, False, False, False],
            [False, False, False, False],
            [False, False, False, False],
            [True, True, False, False],
            [False, False, False, True],
            [False, False, False, False],
        ])
        assert points.shape[0] == num_points
        assert bboxes.shape[0] == num_bboxes
        assert expected_is_inside.shape[0] == num_points
        assert expected_is_inside.shape[1] == num_bboxes

        with self.session() as sess:
            is_inside = sess.run(geometry.IsWithinBBox3D(points, bboxes))
            self.assertAllEqual([num_points, num_bboxes], is_inside.shape)
            self.assertAllEqual(expected_is_inside, is_inside)
Esempio n. 5
0
    def testIsWithinBBox3D(self):
        num_points, num_bboxes = 19, 4
        # rotate the first box by pi / 2 so dim_x and dim_y are swapped.
        # The last box is a cube rotated by 45 degrees.
        bboxes = tf.constant([[1.0, 2.0, 3.0, 6.0, 0.4, 6.0, np.pi / 2],
                              [4.0, 5.0, 6.0, 7.0, 0.8, 7.0, 0.0],
                              [0.4, 0.3, 0.2, 0.1, 0.1, 0.2, 0.0],
                              [-10., -10., -10., 3., 3., 3., np.pi / 4]],
                             dtype=tf.float32)
        points = tf.constant(
            [
                [1.0, 2.0, 3.0],  # box 0 (centroid)
                [0.8, 2.0, 3.0],  # box 0 (below x)
                [1.1, 2.0, 3.0],  # box 0 (above x)
                [1.3, 2.0, 3.0],  # box 0 (too far x)
                [0.7, 2.0, 3.0],  # box 0 (too far x)
                [4.0, 5.0, 6.0],  # box 1 (centroid)
                [4.0, 4.6, 6.0],  # box 1 (below y)
                [4.0, 5.4, 6.0],  # box 1 (above y)
                [4.0, 4.5, 6.0],  # box 1 (too far y)
                [4.0, 5.5, 6.0],  # box 1 (too far y)
                [0.4, 0.3, 0.2],  # box 2 (centroid)
                [0.4, 0.3, 0.1],  # box 2 (below z)
                [0.4, 0.3, 0.3],  # box 2 (above z)
                [0.4, 0.3, 0.0],  # box 2 (too far z)
                [0.4, 0.3, 0.4],  # box 2 (too far z)
                [5.0, 7.0, 8.0],  # none
                [1.0, 5.0, 3.6],  # box0, box1
                [-11.6, -10., -10.],  # box3 (rotated corner point).
                [-11.4, -11.4, -10.],  # not in box3, would be if not rotated.
            ],
            dtype=tf.float32)
        expected_is_inside = np.array([
            [True, False, False, False],
            [True, False, False, False],
            [True, False, False, False],
            [False, False, False, False],
            [False, False, False, False],
            [False, True, False, False],
            [False, True, False, False],
            [False, True, False, False],
            [False, False, False, False],
            [False, False, False, False],
            [False, False, True, False],
            [False, False, True, False],
            [False, False, True, False],
            [False, False, False, False],
            [False, False, False, False],
            [False, False, False, False],
            [True, True, False, False],
            [False, False, False, True],
            [False, False, False, False],
        ])
        assert points.shape[0] == num_points
        assert bboxes.shape[0] == num_bboxes
        assert expected_is_inside.shape[0] == num_points
        assert expected_is_inside.shape[1] == num_bboxes

        with self.session():
            is_inside = self.evaluate(geometry.IsWithinBBox3D(points, bboxes))
            self.assertAllEqual([num_points, num_bboxes], is_inside.shape)
            self.assertAllEqual(expected_is_inside, is_inside)

        # Add a batch dimension to the data and see that it still works
        # as expected.
        batch_size = 3
        points = tf.tile(points[tf.newaxis, ...], [batch_size, 1, 1])
        bboxes = tf.tile(bboxes[tf.newaxis, ...], [batch_size, 1, 1])
        with self.session():
            is_inside = self.evaluate(geometry.IsWithinBBox3D(points, bboxes))
            self.assertAllEqual([batch_size, num_points, num_bboxes],
                                is_inside.shape)
            for batch_idx in range(batch_size):
                self.assertAllEqual(expected_is_inside, is_inside[batch_idx])