def _remove_low_score_boxes(outputs, score_thresh, min_num_boxes=100, epsilon=0.0001): """remove the boxes that have an score lower than threshold. Args: outputs: Output dictionary. score_thresh: A float corresponding to score threshold. min_num_boxes: Minimum number of boxes. epsilon: A very small value. """ max_scores = tf.reduce_max( outputs[standard_fields.DetectionResultFields.objects_score], axis=1) max_score = tf.reduce_max(max_scores) score_mask = tf.greater(max_scores, tf.minimum(score_thresh, max_score - epsilon)) high_score_indices = tf.cast(tf.reshape(tf.where(score_mask), [-1]), dtype=tf.int32) top_k_indices = _get_top_k_indices(outputs=outputs, k=min_num_boxes) high_score_indices = tf.cond( tf.shape(high_score_indices)[0] > min_num_boxes, lambda: high_score_indices, lambda: top_k_indices) for tensor_name in standard_fields.get_output_object_fields(): if tensor_name in outputs and outputs[tensor_name] is not None: outputs[tensor_name] = tf.gather(outputs[tensor_name], high_score_indices)
def postprocess(inputs, outputs, is_training, apply_nms, nms_score_threshold, nms_iou_threshold, nms_max_num_predicted_boxes, use_furthest_voxel_sampling, num_furthest_voxel_samples, sampler_score_vs_distance_coef): """Post-processor function.""" if not is_training: # Squeeze voxel properties. for key in standard_fields.get_output_voxel_fields(): if key in outputs and outputs[key] is not None: outputs[key] = tf.squeeze(outputs[key], axis=0) for key in standard_fields.get_output_point_fields(): if key in outputs and outputs[key] is not None: outputs[key] = tf.squeeze(outputs[key], axis=0) for key in standard_fields.get_output_object_fields(): if key in outputs and outputs[key] is not None: outputs[key] = tf.squeeze(outputs[key], axis=0) # Mask the valid voxels mask_valid_voxels(inputs=inputs, outputs=outputs) # NMS postprocessor.postprocess( outputs=outputs, score_thresh=nms_score_threshold, iou_thresh=nms_iou_threshold, max_output_size=nms_max_num_predicted_boxes, use_furthest_voxel_sampling=use_furthest_voxel_sampling, num_furthest_voxel_samples=num_furthest_voxel_samples, sampler_score_vs_distance_coef=sampler_score_vs_distance_coef, apply_nms=apply_nms)
def fn(): for field in standard_fields.get_input_object_fields(): if field in inputs: inputs[field] = tf.boolean_mask(inputs[field], valid_mask) for field in standard_fields.get_output_object_fields(): if field in outputs: outputs[field] = tf.boolean_mask(outputs[field], valid_mask) return _box_corner_distance_loss( loss_type=loss_type, is_balanced=is_balanced, input_boxes_length=inputs[ standard_fields.InputDataFields.objects_length], input_boxes_height=inputs[ standard_fields.InputDataFields.objects_height], input_boxes_width=inputs[standard_fields.InputDataFields.objects_width], input_boxes_center=inputs[ standard_fields.InputDataFields.objects_center], input_boxes_rotation_matrix=inputs[ standard_fields.InputDataFields.objects_rotation_matrix], input_boxes_instance_id=inputs[ standard_fields.InputDataFields.objects_instance_id], output_boxes_length=outputs[ standard_fields.DetectionResultFields.objects_length], output_boxes_height=outputs[ standard_fields.DetectionResultFields.objects_height], output_boxes_width=outputs[ standard_fields.DetectionResultFields.objects_width], output_boxes_center=outputs[ standard_fields.DetectionResultFields.objects_center], output_boxes_rotation_matrix=outputs[ standard_fields.DetectionResultFields.objects_rotation_matrix], delta=delta)
def _keep_top_k_boxes(outputs, k): """Keeps the top k highest score boxes. Args: outputs: Output dictionary. k: Number of boxes. """ indices = _get_top_k_indices(outputs, k) for tensor_name in standard_fields.get_output_object_fields(): if tensor_name in outputs and outputs[tensor_name] is not None: outputs[tensor_name] = tf.gather(outputs[tensor_name], indices)
def _sample_furthest_voxels(outputs, num_furthest_voxel_samples, sampler_score_vs_distance_coef): """Samples voxels based on distance and scores.""" num_furthest_voxel_samples = tf.minimum( num_furthest_voxel_samples, tf.shape( outputs[standard_fields.DetectionResultFields.objects_center])[0]) _, seed_indices = instance_sampling_utils.sample_based_on_scores_and_distances( inputs=outputs[standard_fields.DetectionResultFields.objects_center], scores=tf.reduce_max( outputs[standard_fields.DetectionResultFields.objects_score], axis=1), num_samples=num_furthest_voxel_samples, scores_coef=sampler_score_vs_distance_coef) for tensor_name in standard_fields.get_output_object_fields(): if tensor_name in outputs and outputs[tensor_name] is not None: outputs[tensor_name] = tf.gather(outputs[tensor_name], seed_indices)
def get_batch_size_1_output_objects(outputs, b): """Returns output dictionary containing tensors with batch size of 1. Note that this function only applies its example selection to the object tensors. Args: outputs: A dictionary of tf.Tensors with the network output. b: Example index in the batch. Returns: outputs_1: A dictionary of tf.Tensors with batch size of one. """ b_1_outputs = {} for field in standard_fields.get_output_object_fields(): if field in outputs and outputs[field] is not None: b_1_outputs[field] = outputs[field][b] return b_1_outputs
def postprocess(inputs, outputs, is_training, num_furthest_voxel_samples, sampler_score_vs_distance_coef, embedding_similarity_strategy, embedding_similarity_threshold, score_threshold, apply_nms, nms_iou_threshold): """Post-processor function. Args: inputs: A dictionary containing input tensors. outputs: A dictionary containing predicted tensors. is_training: If during training stage or not. num_furthest_voxel_samples: Number of voxels to be sampled using furthest voxel sampling in the postprocessor. sampler_score_vs_distance_coef: The coefficient that balances the weight between furthest voxel sampling and highest score sampling in the postprocessor. embedding_similarity_strategy: Embedding similarity strategy. embedding_similarity_threshold: Similarity threshold used to decide if two point embedding vectors belong to the same instance. score_threshold: Instance score threshold used throughout postprocessing. apply_nms: If True, it will apply non-maximum suppression to the final predictions. nms_iou_threshold: Intersection over union threshold used in non-maximum suppression. """ if not is_training: # Squeeze output voxel properties. for key in standard_fields.get_output_voxel_fields(): if key in outputs and outputs[key] is not None: outputs[key] = tf.squeeze(outputs[key], axis=0) # Squeeze output point properties. for key in standard_fields.get_output_point_fields(): if key in outputs and outputs[key] is not None: outputs[key] = tf.squeeze(outputs[key], axis=0) # Squeeze output object properties. for key in standard_fields.get_output_object_fields(): if key in outputs and outputs[key] is not None: outputs[key] = tf.squeeze(outputs[key], axis=0) # Mask the valid voxels mask_valid_voxels(inputs=inputs, outputs=outputs) # Mask the valid points mask_valid_points(inputs=inputs, outputs=outputs) # NMS postprocessor.postprocess( outputs=outputs, num_furthest_voxel_samples=num_furthest_voxel_samples, sampler_score_vs_distance_coef=sampler_score_vs_distance_coef, embedding_similarity_strategy=embedding_similarity_strategy, embedding_similarity_threshold=embedding_similarity_threshold, apply_nms=apply_nms, nms_score_threshold=score_threshold, nms_iou_threshold=nms_iou_threshold) # Add instance segment point masks at eval time if standard_fields.InputDataFields.points_to_voxel_mapping in inputs: instance_segments_point_mask = ( voxel_utils.sparse_voxel_grid_to_pointcloud( voxel_features=tf.expand_dims(tf.transpose( outputs[standard_fields.DetectionResultFields. instance_segments_voxel_mask]), axis=0), segment_ids=inputs[standard_fields.InputDataFields. points_to_voxel_mapping], num_valid_voxels=inputs[ standard_fields.InputDataFields.num_valid_voxels], num_valid_points=inputs[ standard_fields.InputDataFields.num_valid_points])) outputs[standard_fields.DetectionResultFields. instance_segments_point_mask] = tf.transpose( tf.squeeze(instance_segments_point_mask, axis=0))