def _EvaluateIfNecessary(self, name): """Create a camera image summary if not already created.""" if self._summary is not None: return ret = tf.Summary() for sample_idx, sample in enumerate(self._sampler.samples): batch_size = sample.camera_images.shape[0] for batch_idx in range(batch_size): image = sample.camera_images[batch_idx] # [num bboxes, 8, 2]. bbox_corners = sample.bbox_corners[batch_idx] # [num_bboxes] bbox_scores = sample.bbox_scores[batch_idx] def Draw3DBoxes(fig, axes, bbox_corners=bbox_corners, bbox_scores=bbox_scores): """Draw 3d bounding boxes.""" del fig for bbox_id in range(bbox_corners.shape[0]): # Skip visualizing low-scoring boxes. bbox_score = bbox_scores[bbox_id] if bbox_score < self._bbox_score_threshold: continue bbox_data = bbox_corners[bbox_id] # Draw the score of each box. # # Turn score into an integer for better display. center_x = np.mean(bbox_data[:, 0]) center_y = np.mean(bbox_data[:, 1]) bbox_score = int(bbox_score * 100) text = axes.text(center_x, center_y, bbox_score, fontsize=12, color='red', fontweight='bold') text.set_bbox(dict(facecolor='yellow', alpha=0.4)) # The BBoxToCorners function produces the points # in a deterministic order, which we use to draw # the faces of the polygon. # # The first 4 points are the "top" of the bounding box. # The second 4 points are the "bottom" of the bounding box. # # We then draw the last 4 connecting points by choosing # two of the connecting faces in the right order. face_points = [] face_points += [[ bbox_data[0, :], bbox_data[1, :], bbox_data[2, :], bbox_data[3, :] ]] face_points += [[ bbox_data[4, :], bbox_data[5, :], bbox_data[6, :], bbox_data[7, :] ]] face_points += [[ bbox_data[1, :], bbox_data[2, :], bbox_data[6, :], bbox_data[5, :] ]] face_points += [[ bbox_data[0, :], bbox_data[3, :], bbox_data[7, :], bbox_data[4, :] ]] for face in face_points: # Each face is a list of 4 x,y points face_xy = np.array(face) axes.add_patch( matplotlib_patches.Polygon(face_xy, closed=True, edgecolor='red', facecolor='none')) def Draw2DBoxes(fig, axes, bbox_corners=bbox_corners, bbox_scores=bbox_scores): """Draw 2d boxes on the figure.""" del fig # Extract the 2D extrema of each bbox and the max score for bbox_id in range(bbox_corners.shape[0]): # Skip visualizing low-scoring boxes. bbox_score = bbox_scores[bbox_id] if bbox_score < self._bbox_score_threshold: continue bbox_data = bbox_corners[bbox_id] ymin = np.min(bbox_data[:, 1]) xmin = np.min(bbox_data[:, 0]) ymax = np.max(bbox_data[:, 1]) xmax = np.max(bbox_data[:, 0]) height = ymax - ymin width = xmax - xmin # Turn score into an integer for better display. bbox_score = int(bbox_score * 100) text = axes.text(xmin, ymin, bbox_score, fontsize=12, color='red', fontweight='bold') text.set_bbox(dict(facecolor='yellow', alpha=0.4)) axes.add_patch( matplotlib_patches.Rectangle((xmin, ymin), width, height, edgecolor='red', facecolor='none')) # For each image, draw the boxes on that image. draw_fn = Draw3DBoxes if self._draw_3d_boxes else Draw2DBoxes image_summary = plot.Image(name='{}/{}/{}'.format( name, sample_idx, batch_idx), aspect='equal', figsize=self._figsize, image=image, setter=draw_fn) ret.value.extend(image_summary.value) self._summary = ret
def _EvaluateIfNecessary(self, name): """Create a top down image summary, if not already created.""" if self._summary is not None: return tf.logging.info('Generating top down summary.') ret = tf.Summary() transform = self._top_down_transform for batch_idx, batch_sample in enumerate(self._sampler.samples): batch_size = batch_sample.labels.shape[0] visualization_labels = batch_sample.visualization_labels predicted_bboxes = batch_sample.predicted_bboxes visualization_weights = batch_sample.visualization_weights points_xyz = batch_sample.points_xyz points_padding = batch_sample.points_padding gt_bboxes_2d = batch_sample.gt_bboxes_2d gt_bboxes_2d_weights = batch_sample.gt_bboxes_2d_weights labels = batch_sample.labels difficulties = batch_sample.difficulties source_ids = batch_sample.source_ids # Create base images for entire batch that we will update. images = np.zeros( [batch_size, self._image_height, self._image_width, 3], dtype=np.uint8) # Draw lasers first, so that bboxes can be on top. self._DrawLasers(images, points_xyz, points_padding, transform) # Draw ground-truth bboxes. gt_bboxes_2d = np.where( np.expand_dims(gt_bboxes_2d_weights > 0, -1), gt_bboxes_2d, np.zeros_like(gt_bboxes_2d)) transformed_gt_bboxes_2d = summary.TransformBBoxesToTopDown( gt_bboxes_2d, transform) summary.DrawBBoxesOnImages(images, transformed_gt_bboxes_2d, gt_bboxes_2d_weights, labels, self._class_id_to_name, groundtruth=True) # Draw predicted bboxes. predicted_bboxes = np.where( np.expand_dims(visualization_weights > 0, -1), predicted_bboxes, np.zeros_like(predicted_bboxes)) transformed_predicted_bboxes = summary.TransformBBoxesToTopDown( predicted_bboxes, transform) summary.DrawBBoxesOnImages(images, transformed_predicted_bboxes, visualization_weights, visualization_labels, self._class_id_to_name, groundtruth=False) # Draw the difficulties on the image. self.DrawDifficulty(images, transformed_gt_bboxes_2d, gt_bboxes_2d_weights, difficulties) for idx in range(batch_size): source_id = source_ids[idx] def AnnotateImage(fig, axes, source_id=source_id): """Add source_id to image.""" del fig # Draw in top middle of image. text = axes.text(500, 15, source_id, fontsize=16, color='blue', fontweight='bold', horizontalalignment='center') text.set_path_effects([ path_effects.Stroke(linewidth=3, foreground='lightblue'), path_effects.Normal() ]) image_summary = plot.Image(name='{}/{}/{}'.format( name, batch_idx, idx), aspect='equal', figsize=self._figsize, image=images[idx, ...], setter=AnnotateImage) ret.value.extend(image_summary.value) tf.logging.info('Done generating top down summary.') self._summary = ret