U Ph C @sdZddlmZddlmZmZddlZdgZdddd d d d d d d d d ddZ ddd ddddZ ddddddZ dddddd dddddZ 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_batchdz.Callable[[np.ndarray, np.ndarray], np.ndarray]zSequence[float]zSequence[np.ndarray]z6Sequence[Sequence[bool]] | Sequence[np.ndarray] | Noneintz&list[dict[int, dict[str, np.ndarray]]]) iou_fniou_thresholds pred_boxes pred_classes pred_scoresgt_boxes gt_classes gt_ignoremax_detectionsreturnc  Csg} |dkrdd|D}t||||||D]\} } } } }}t| |}i}|D]}| |k}||k}t|st|| ||d||<qPt|st|||d||<qPt|| || || |||||d||<qP| |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_crZ/home/dell461/cl/sdc2/HISourceFinder-master-l/src/monai/apps/detection/metrics/matching.py sz"matching_batch..)r r r)r r)rr r r rrr )ziprunion1dany_matching_no_gt_matching_no_pred#_matching_single_image_single_classappend)rr r r r r rrrresultsZpboxesZpclassesZpscoresZgboxesZgclassesZgignoreZ img_classesresultcZ pred_maskZgt_maskrrrrJsFP     z np.ndarrayzdict[str, np.ndarray])r r rrc 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 r rdt_ind dt_scores num_predsgt_matchdt_match dt_ignorerrrrs r)r rrcCsrtg}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&)rr-r,sizeshaper.r/)r rr1r4r5Zn_gtr3rrrrs r)rr r r rrr rcCstj| dd}|d|}||}||}tj|dd}||}||}|||} | jd| jd} } tt|| f} tt|| f} tt|| f}t|D]\}}t|D]\}}t|dg}d}t|D]j\}}| ||fdkrq|dkr||dkr||dkrqD| ||f|kr2q| ||f}|}q|dkrRqqt|||||f<d| ||f<d| ||f<qq| | ||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&) rr+r7r.r, enumerateminrr/)rr r r rrr r0Zgt_indZiousr2Znum_gtsr3r4r5ZtindtZdind_dioumZgind_grrrrsH'   &   r)Nr) __doc__ __future__rcollections.abcrrnumpyr__all__rrrrrrrr;s  "r-'