docstr: Generates boxes from predictions
  
  Parameters
  ----------
  dataset :
      Must provide a class2size method and a class2angle method that return the angle and size
      for a given object class and residual value
  apply_nms: bool
      If True then we apply non max suppression before returning the boxes
  duplicate_boxes: bool
      If True then we duplicate predicted boxes accross all classes. Else we assign the box to the
      most likely class
  
  Returns
  -------
  List[List[BoxData]] contains the list of predicted boxes for each batch
docstr_tok: ["Generates","boxes","from","predictions","Parameters","--","--","--","--","--","dataset",":","Must","provide","a","class2size","method","and","a","class2angle","method","that","return","the","angle","and","size","for","a","given","object","class","and","residual","value","apply_nms",":","bool","If","True","then","we","apply","non","max","suppression","before","returning","the","boxes","duplicate_boxes",":","bool","If","True","then","we","duplicate","predicted","boxes","accross","all","classes",".","Else","we","assign","the","box","to","the","most","likely","class","Returns","--","--","--","-","List","[","List","[","BoxData","]","]","contains","the","list","of","predicted","boxes","for","each","batch"]
code: def get_boxes(
      self,
      dataset,
      apply_nms=False,
      objectness_threshold=0.05,
      duplicate_boxes=False,
  ) -> List[List[BoxData]]:
      """Generates boxes from predictions
  
      Parameters
      ----------
      dataset :
          Must provide a class2size method and a class2angle method that return the angle and size
          for a given object class and residual value
      apply_nms: bool
          If True then we apply non max suppression before returning the boxes
      duplicate_boxes: bool
          If True then we duplicate predicted boxes accross all classes. Else we assign the box to the
          most likely class
  
      Returns
      -------
      List[List[BoxData]] contains the list of predicted boxes for each batch
      """
  
      # Size and Heading prediciton
      pred_heading_class = torch.argmax(
          self.heading_scores, -1
      )  # B,num_proposal
      pred_heading_residual = torch.gather(
          self.heading_residuals, 2, pred_heading_class.unsqueeze(-1)
      )  # B,num_proposal,1
      pred_size_class = torch.argmax(
          self.size_scores, -1
      )  # B,num_proposal
      pred_size_residual = torch.gather(
          self.size_residuals,
          2,
          pred_size_class.unsqueeze(-1)
          .unsqueeze(-1)
          .repeat(1, 1, 1, 3),
      ).squeeze(
          2
      )  # B,num_proposal,3
  
      # Generate box corners
      pred_corners_3d = torch.zeros(
          (self.batch_size, self.num_proposal, 8, 3)
      )
      for i in range(self.batch_size):
          for j in range(self.num_proposal):
              heading_angle = dataset.class2angle(
                  pred_heading_class[i, j], pred_heading_residual[i, j]
              )
              box_size = dataset.class2size(
                  pred_size_class[i, j], pred_size_residual[i, j]
              )
              corners_3d = box_corners_from_param(
                  box_size, heading_angle, self.center[i, j, :].cpu()
              )
              pred_corners_3d[i, j] = corners_3d
  
      # Objectness and class
      pred_obj = torch.nn.functional.softmax(
          self.objectness_scores, -1
      )[
          :, :, 1
      ]  # B,num_proposal
      pred_sem_cls = torch.argmax(
          self.sem_cls_scores, -1
      )  # B,num_proposal
      sem_cls_proba = torch.softmax(self.sem_cls_scores, -1)
  
      # Apply nms if required
      if apply_nms:
          mask = self._nms_mask(pred_corners_3d, pred_obj, pred_sem_cls)
      else:
          mask = np.ones((self.batch_size, self.num_proposal), dtype=np.bool)  # type: ignore
  
      detected_boxes = []
      for i in range(self.batch_size):
          corners = pred_corners_3d[i, mask[i]]
          objectness = pred_obj[i, mask[i]]
          sem_cls_scores = sem_cls_proba[i, mask[i]]
          clsname = pred_sem_cls[i, mask[i]]
  
          # Build box data for each detected object and add it to the list
          batch_detection = []
          for j in range(len(corners)):
              if objectness[j] > objectness_threshold:
                  if duplicate_boxes and self.has_class:
                      for classname in range(sem_cls_proba.shape[-1]):
                          batch_detection.append(
                              BoxData(
                                  classname,
                                  corners[j],
                                  score=objectness[j]
                                  * sem_cls_scores[j, classname],
                              )
                          )
                  else:
                      batch_detection.append(
                          BoxData(
                              clsname[j],
                              corners[j],
                              score=objectness[j],
                          )
                      )
  
          detected_boxes.append(batch_detection)
  
      return detected_boxes
  
file_path: torch-points3d/torch_points3d/modules/VoteNet/votenet_results.py
imports: import torch
  from torch_geometric.data import Data
  import numpy
  from typing import List
  from torch_points3d.core.losses.huber_loss import nn_distance
  from torch_points3d.utils.box_utils import box_corners_from_param, nms_samecls
  from torch_points3d.datasets.object_detection.box_data import BoxData
label_desc: Use image node_id 5 for calling the VoteNetResults obj's underlying member method code with example usage: obj.get_boxes(dataset, apply_nms, objectness_threshold, duplicate_boxes) and returns: detected_boxes