def earth_mover(pcd1, pcd2, radius=1.0): assert pcd1.shape[1] == pcd2.shape[1] num_points = tf.cast(pcd1.shape[1], tf.float32) match = tf_approxmatch.approx_match(pcd1, pcd2) cost = tf_approxmatch.match_cost(pcd1, pcd2, match) cost = cost / radius return tf.reduce_mean(cost / num_points)
def get_emd_loss(pcd1, pcd2,radius): assert pcd1.shape[1] == pcd2.shape[1] num_points = tf.cast(pcd1.shape[1], tf.float32) match = tf_approxmatch.approx_match(pcd1, pcd2) cost = tf_approxmatch.match_cost(pcd1, pcd2, match) cost = cost/radius return tf.reduce_mean(cost / num_points)
def _compute_loss(self, prediction_tensor, target_tensor, weights): """ Args: prediction_tensor (float): A tensor of shape [batch_size, h, w, 3] target_tensor (float): A tensor of shape [batch_size, h, w, 3] weights (float): A tensor of shape [batch_size, h, w, 1] Returns: loss (float): Approximate Earth Mover's Distance """ # Multiply by valid mask valid_prediction_tensor = prediction_tensor * weights valid_target_tensor = target_tensor * weights # Reshape to (batch_size, n_points, 3) batch_size = prediction_tensor.get_shape()[0] valid_prediction_points = tf.reshape(valid_prediction_tensor, (batch_size, -1, 3)) valid_target_points = tf.reshape(valid_target_tensor, (batch_size, -1, 3)) match = tf_approxmatch.approx_match(valid_prediction_points, valid_target_points) distances = tf_approxmatch.match_cost( valid_prediction_points, valid_target_points, match) emd_distance = tf.reduce_sum(distances) / tf.cast(batch_size, tf.float32) return emd_distance
def get_loss(pred, label, end_points): """ pred: BxNx3, label: BxNx3, """ dists_forward,_,dists_backward,_ = tf_nndistance.nn_distance(pred, label) pc_loss = tf.reduce_mean(dists_forward+dists_backward) end_points['pcloss'] = pc_loss match = tf_approxmatch.approx_match(label, pred) loss = tf.reduce_mean(tf_approxmatch.match_cost(label, pred, match)) tf.summary.scalar('loss', loss) return loss, end_points
def test_emd_negative(self): """Test negative point cloud values for computing the approximate Earth Mover's Distance. """ # Create test point clouds of shape [batch_size, n_points, 3] point_cloud_1 = [[[-2., 2., -2.]]] point_cloud_2 = [[[2., 0., 2.]]] tf_point_cloud_1 = tf.constant(point_cloud_1) tf_point_cloud_2 = tf.constant(point_cloud_2) match = tf_approxmatch.approx_match(tf_point_cloud_1, tf_point_cloud_2) distance = tf.reduce_mean(tf_approxmatch.match_cost(point_cloud_1, point_cloud_2, match)) with tf.Session() as sess: match, distance = sess.run([match, distance]) np.testing.assert_almost_equal(distance, 6.0, decimal=2)
def test_emd(self): """Test for the approximate algorithm for computing the distance where loss should be zero. """ # Create test point clouds of shape [batch_size, n_points, 3] point_cloud_1 = [[[1., 1., 1.], [2., 2., 2.], [3., 3., 3.]]] point_cloud_2 = [[[1., 1., 1.], [2., 2., 2.], [3., 3., 3.]]] tf_point_cloud_1 = tf.constant(point_cloud_1) tf_point_cloud_2 = tf.constant(point_cloud_2) match = tf_approxmatch.approx_match(tf_point_cloud_1, tf_point_cloud_2) distance = tf.reduce_mean(tf_approxmatch.match_cost(point_cloud_1, point_cloud_2, match)) with tf.Session() as sess: distance = sess.run([distance]) np.testing.assert_almost_equal(distance, 0)
def test_emd_batch(self): """Tests batches for the approximate algorithm for computing the Earth Mover's Distance. """ # Create test point clouds of shape [batch_size, n_points, 3] point_cloud_1 = [[[1., 1., 1.], [2., 2., 2.], [3., 3., 3.]], [[1., 1., 1.], [2., 2., 2.], [3., 3., 3.]]] point_cloud_2 = [[[1., 0., 1.], [2., 0., 2.], [3., 0., 3.]], [[4., 4., 4.], [2., 2., 2.], [3., 3., 3.]]] tf_point_cloud_1 = tf.constant(point_cloud_1) tf_point_cloud_2 = tf.constant(point_cloud_2) match = tf_approxmatch.approx_match(tf_point_cloud_1, tf_point_cloud_2) distance = tf_approxmatch.match_cost(point_cloud_1, point_cloud_2, match) with tf.Session() as sess: match, distance = sess.run([match, distance]) np.testing.assert_almost_equal(distance, [6.0, 5.196152], decimal=2)
def test_emd_2(self): """Test for the approximate algorithm for computing the Earth Mover's Distance to see if match selects closest point, and if the loss is reasonable. """ # Create test point clouds of shape [batch_size, n_points, 3] point_cloud_1 = [[[1., 1., 1.], [2., 2., 2.], [3., 3., 3.]]] point_cloud_2 = [[[1., 0., 1.], [2., 0., 2.], [3., 0., 3.]]] tf_point_cloud_1 = tf.constant(point_cloud_1) tf_point_cloud_2 = tf.constant(point_cloud_2) match = tf_approxmatch.approx_match(tf_point_cloud_1, tf_point_cloud_2) distance = tf.reduce_mean(tf_approxmatch.match_cost(point_cloud_1, point_cloud_2, match)) with tf.Session() as sess: match, distance = sess.run([match, distance]) matched_indices = np.argmax(np.squeeze(match), axis=1) np.testing.assert_equal(matched_indices, [0, 1, 2]) np.testing.assert_almost_equal(distance, 6.0, decimal=2)