code: def calc_detection_voc_prec_rec(
      pred_bboxes,
      pred_labels,
      pred_scores,
      gt_bboxes,
      gt_labels,
      gt_difficults=None,
      iou_thresh=0.5,
  ):
      """Calculate precision and recall based on evaluation code of PASCAL VOC.
  
      This function calculates precision and recall of
      predicted bounding boxes obtained from a dataset which has :math:`N`
      images.
      The code is based on the evaluation code used in PASCAL VOC Challenge.
  
      Args:
          pred_bboxes (iterable of numpy.ndarray): See the table in
              :func:`chainercv.evaluations.eval_detection_voc`.
          pred_labels (iterable of numpy.ndarray): See the table in
              :func:`chainercv.evaluations.eval_detection_voc`.
          pred_scores (iterable of numpy.ndarray): See the table in
              :func:`chainercv.evaluations.eval_detection_voc`.
          gt_bboxes (iterable of numpy.ndarray): See the table in
              :func:`chainercv.evaluations.eval_detection_voc`.
          gt_labels (iterable of numpy.ndarray): See the table in
              :func:`chainercv.evaluations.eval_detection_voc`.
          gt_difficults (iterable of numpy.ndarray): See the table in
              :func:`chainercv.evaluations.eval_detection_voc`.
              By default, this is :obj:`None`. In that case, this function
              considers all bounding boxes to be not difficult.
          iou_thresh (float): A prediction is correct if its Intersection over
              Union with the ground truth is above this value..
  
      Returns:
          tuple of two lists:
          This function returns two lists: :obj:`prec` and :obj:`rec`.
  
          * :obj:`prec`: A list of arrays. :obj:`prec[l]` is precision \
              for class :math:`l`. If class :math:`l` does not exist in \
              either :obj:`pred_labels` or :obj:`gt_labels`, :obj:`prec[l]` is \
              set to :obj:`None`.
          * :obj:`rec`: A list of arrays. :obj:`rec[l]` is recall \
              for class :math:`l`. If class :math:`l` that is not marked as \
              difficult does not exist in \
              :obj:`gt_labels`, :obj:`rec[l]` is \
              set to :obj:`None`.
  
      """
  
      pred_bboxes = iter(pred_bboxes)
      pred_labels = iter(pred_labels)
      pred_scores = iter(pred_scores)
      gt_bboxes = iter(gt_bboxes)
      gt_labels = iter(gt_labels)
      if gt_difficults is None:
          gt_difficults = itertools.repeat(None)
      else:
          gt_difficults = iter(gt_difficults)
  
      n_pos = defaultdict(int)
      score = defaultdict(list)
      match = defaultdict(list)
  
      for (
          pred_bbox,
          pred_label,
          pred_score,
          gt_bbox,
          gt_label,
          gt_difficult,
      ) in six.moves.zip(
          pred_bboxes,
          pred_labels,
          pred_scores,
          gt_bboxes,
          gt_labels,
          gt_difficults,
      ):
          if gt_difficult is None:
              gt_difficult = np.zeros(gt_bbox.shape[0], dtype=bool)
  
          for l in np.unique(
              np.concatenate((pred_label, gt_label)).astype(int)
          ):
              pred_mask_l = pred_label == l
              pred_bbox_l = pred_bbox[pred_mask_l]
              pred_score_l = pred_score[pred_mask_l]
              # sort by score
              order = pred_score_l.argsort()[::-1]
              pred_bbox_l = pred_bbox_l[order]
              pred_score_l = pred_score_l[order]
  
              gt_mask_l = gt_label == l
              gt_bbox_l = gt_bbox[gt_mask_l]
              gt_difficult_l = gt_difficult[gt_mask_l]
  
              n_pos[l] += np.logical_not(gt_difficult_l).sum()
              score[l].extend(pred_score_l)
  
              if len(pred_bbox_l) == 0:
                  continue
              if len(gt_bbox_l) == 0:
                  match[l].extend((0,) * pred_bbox_l.shape[0])
                  continue
  
              # VOC evaluation follows integer typed bounding boxes.
              pred_bbox_l = pred_bbox_l.copy()
              pred_bbox_l[:, 2:] += 1
              gt_bbox_l = gt_bbox_l.copy()
              gt_bbox_l[:, 2:] += 1
  
              iou = bbox_iou(pred_bbox_l, gt_bbox_l)
              gt_index = iou.argmax(axis=1)
              # set -1 if there is no matching ground truth
              gt_index[iou.max(axis=1) < iou_thresh] = -1
              del iou
  
              selec = np.zeros(gt_bbox_l.shape[0], dtype=bool)
              for gt_idx in gt_index:
                  if gt_idx >= 0:
                      if gt_difficult_l[gt_idx]:
                          match[l].append(-1)
                      else:
                          if not selec[gt_idx]:
                              match[l].append(1)
                          else:
                              match[l].append(0)
                      selec[gt_idx] = True
                  else:
                      match[l].append(0)
  
      for iter_ in (
          pred_bboxes,
          pred_labels,
          pred_scores,
          gt_bboxes,
          gt_labels,
          gt_difficults,
      ):
          if next(iter_, None) is not None:
              raise ValueError(
                  "Length of input iterables need to be same."
              )
  
      n_fg_class = max(n_pos.keys()) + 1
      prec = [None] * n_fg_class
      rec = [None] * n_fg_class
  
      for l in n_pos.keys():
          score_l = np.array(score[l])
          match_l = np.array(match[l], dtype=np.int8)
  
          order = score_l.argsort()[::-1]
          match_l = match_l[order]
  
          tp = np.cumsum(match_l == 1)
          fp = np.cumsum(match_l == 0)
  
          # If an element of fp + tp is 0,
          # the corresponding element of prec[l] is nan.
          prec[l] = tp / (fp + tp)
          # If n_pos[l] is 0, rec[l] is None.
          if n_pos[l] > 0:
              rec[l] = tp / n_pos[l]
  
      return prec, rec
  
file_path: chainercv/chainercv/evaluations/eval_detection_voc.py
imports: from __future__ import division
  from collections import defaultdict
  import itertools
  import numpy
  import six
  from chainercv.utils.bbox.bbox_iou import bbox_iou
label_desc: Use image node_id 2 for calling a global function with example usage: calc_detection_voc_prec_rec(pred_bboxes, pred_labels, pred_scores, gt_bboxes, gt_labels, gt_difficults, iou_thresh) and returns: prec,  rec