o  i C@s`dZddlmZddlmZmZddlZdgZ  d d!ddZ d"ddZ d#ddZ d$ddZ dS)%a This script is almost same with https://github.com/MIC-DKFZ/nnDetection/blob/main/nndet/evaluator/detection/matching.py The changes include 1) code reformatting, 2) docstrings, 3) allow input args gt_ignore to be optional. (If so, no GT boxes will be ignored.) ) annotations)CallableSequenceNmatching_batchdiou_fn.Callable[[np.ndarray, np.ndarray], np.ndarray]iou_thresholdsSequence[float] pred_boxesSequence[np.ndarray] pred_classes pred_scoresgt_boxes gt_classes gt_ignore6Sequence[Sequence[bool]] | Sequence[np.ndarray] | Nonemax_detectionsintreturn&list[dict[int, dict[str, np.ndarray]]]c  Csg} |dur dd|D}t||||||D]X\} } } } }}t| |}i}|D]@}| |k}||k}t|sCt|| ||d||<q(t|sSt|||d||<q(t|| || || |||||d||<q(| |q| S)a! Match boxes of a batch to corresponding ground truth for each category independently. Args: iou_fn: compute overlap for each pair iou_thresholds: defined which IoU thresholds should be evaluated pred_boxes: predicted boxes from single batch; List[[D, dim * 2]], D number of predictions pred_classes: predicted classes from a single batch; List[[D]], D number of predictions pred_scores: predicted score for each bounding box; List[[D]], D number of predictions gt_boxes: ground truth boxes; List[[G, dim * 2]], G number of ground truth gt_classes: ground truth classes; List[[G]], G number of ground truth gt_ignore: specified if which ground truth boxes are not counted as true positives. If not given, when use all the gt_boxes. (detections which match theses boxes are not counted as false positives either); List[[G]], G number of ground truth max_detections: maximum number of detections which should be evaluated Returns: List[Dict[int, Dict[str, np.ndarray]]], each Dict[str, np.ndarray] corresponds to an image. Dict has the following keys. - `dtMatches`: matched detections [T, D], where T = number of thresholds, D = number of detections - `gtMatches`: matched ground truth boxes [T, G], where T = number of thresholds, G = number of ground truth - `dtScores`: prediction scores [D] detection scores - `gtIgnore`: ground truth boxes which should be ignored [G] indicate whether ground truth should be ignored - `dtIgnore`: detections which should be ignored [T, D], indicate which detections should be ignored Example: .. code-block:: python from monai.data.box_utils import box_iou from monai.apps.detection.metrics.coco import COCOMetric from monai.apps.detection.metrics.matching import matching_batch # 3D example outputs of one image from detector val_outputs_all = [ {"boxes": torch.tensor([[1,1,1,3,4,5]],dtype=torch.float16), "labels": torch.randint(3,(1,)), "scores": torch.randn((1,)).absolute()}, ] val_targets_all = [ {"boxes": torch.tensor([[1,1,1,2,6,4]],dtype=torch.float16), "labels": torch.randint(3,(1,))}, ] coco_metric = COCOMetric( classes=['c0','c1','c2'], iou_list=[0.1], max_detection=[10] ) results_metric = matching_batch( iou_fn=box_iou, iou_thresholds=coco_metric.iou_thresholds, pred_boxes=[val_data_i["boxes"].numpy() for val_data_i in val_outputs_all], pred_classes=[val_data_i["labels"].numpy() for val_data_i in val_outputs_all], pred_scores=[val_data_i["scores"].numpy() for val_data_i in val_outputs_all], gt_boxes=[val_data_i["boxes"].numpy() for val_data_i in val_targets_all], gt_classes=[val_data_i["labels"].numpy() for val_data_i in val_targets_all], ) val_metric_dict = coco_metric(results_metric) print(val_metric_dict) NcSsg|]}t|dqS)F)np full_like).0Zgt_crg/home/dell461/cl/sdc2/last_ska_mid/HISourceFinder-master-l/src/monai/apps/detection/metrics/matching.py sz"matching_batch..)r rr)r r)rr rrrrr )ziprunion1dany_matching_no_gt_matching_no_pred#_matching_single_image_single_classappend)rr r r rrrrrresultsZpboxesZpclassesZpscoresZgboxesZgclassesZgignoreZ img_classesresultcZ pred_maskZgt_maskrrrrJs8P       np.ndarraydict[str, np.ndarray]c Cstj| dd}|d|}||}t|}tggt|}tt||f}tt||f}|||tgd|dS)a Matching result with not ground truth in image Args: iou_thresholds: defined which IoU thresholds should be evaluated dt_scores: predicted scores max_detections: maximum number of allowed detections per image. This functions uses this parameter to stay consistent with the actual matching function which needs this limit. Returns: computed matching, a Dict[str, np.ndarray] - `dtMatches`: matched detections [T, D], where T = number of thresholds, D = number of detections - `gtMatches`: matched ground truth boxes [T, G], where T = number of thresholds, G = number of ground truth - `dtScores`: prediction scores [D] detection scores - `gtIgnore`: ground truth boxes which should be ignored [G] indicate whether ground truth should be ignored - `dtIgnore`: detections which should be ignored [T, D], indicate which detections should be ignored mergesortkindN dtMatchesZ gtMatchesdtScoresgtIgnoredtIgnore)rargsortlenarrayzerosreshape) r rrdt_ind dt_scores num_predsgt_matchdt_match dt_ignorerrrr s r cCsrtg}tggt|}tggt|}|jdkr dn|jd}tt||f}||||d|dS)a Matching result with no predictions Args: iou_thresholds: defined which IoU thresholds should be evaluated gt_ignore: specified if which ground truth boxes are not counted as true positives (detections which match theses boxes are not counted as false positives either); [G], G number of ground truth Returns: dict: computed matching - `dtMatches`: matched detections [T, D], where T = number of thresholds, D = number of detections - `gtMatches`: matched ground truth boxes [T, G], where T = number of thresholds, G = number of ground truth - `dtScores`: prediction scores [D] detection scores - `gtIgnore`: ground truth boxes which should be ignored [G] indicate whether ground truth should be ignored - `dtIgnore`: detections which should be ignored [T, D], indicate which detections should be ignored rr,r-)rr4r3sizeshaper5r6)r rr8r;r<Zn_gtr:rrrr!s r!cCstj| dd}|d|}||}||}tj|dd}||}||}|||} | jd| jd} } tt|| f} tt|| f} tt|| f}t|D]e\}}t|D]\\}}t|dg}d}t|D]0\}}| ||fdkryql|dkr||dkr||dkrn| ||f|krql| ||f}|}ql|dkrq\t|||||f<d| ||f<d| ||f<q\qT| | ||d|dS) a Adapted from https://github.com/cocodataset/cocoapi/blob/master/PythonAPI/pycocotools/cocoeval.py Args: iou_fn: compute overlap for each pair iou_thresholds: defined which IoU thresholds should be evaluated pred_boxes: predicted boxes from single batch; [D, dim * 2], D number of predictions pred_scores: predicted score for each bounding box; [D], D number of predictions gt_boxes: ground truth boxes; [G, dim * 2], G number of ground truth gt_ignore: specified if which ground truth boxes are not counted as true positives (detections which match theses boxes are not counted as false positives either); [G], G number of ground truth max_detections: maximum number of detections which should be evaluated Returns: dict: computed matching - `dtMatches`: matched detections [T, D], where T = number of thresholds, D = number of detections - `gtMatches`: matched ground truth boxes [T, G], where T = number of thresholds, G = number of ground truth - `dtScores`: prediction scores [D] detection scores - `gtIgnore`: ground truth boxes which should be ignored [G] indicate whether ground truth should be ignored - `dtIgnore`: detections which should be ignored [T, D], indicate which detections should be ignored r)r*NrgA?r,r-) rr2r>r5r3 enumerateminrr6)rr rrrrr r7Zgt_indZiousr9Znum_gtsr:r;r<ZtindtZdind_dioumZgind_grrrr"sJ'       r")Nr)rrr r r r r r rr rr rr rrrrrr)r r rr'rrrr()r r rr'rr()rrr r'rr'rr'rr'rrr r rr() __doc__ __future__rcollections.abcrrnumpyr__all__rr r!r"rrrrs:   r -'