Exemplo n.º 1
0
    def initialize_ui(self):
        # clear all information
        self.txb_statistics.setText('')
        self.lbl_sample_image.setText('')
        self.btn_previous_image.setEnabled(False)
        self.btn_next_image.setEnabled(False)
        # Create text with ground truth statistics
        if self.type_bb == BBType.GROUND_TRUTH:
            stats = self.text_statistics.replace('#TYPE_BB#', 'Ground Truth')
            self.annot_obj = self.gt_annotations
        elif self.type_bb == BBType.DETECTED:
            stats = self.text_statistics.replace('#TYPE_BB#', 'Detections')
            self.annot_obj = self.det_annotations
        self.chb_det_bb.setVisible(False)
        self.chb_gt_bb.setVisible(False)
        if self.det_annotations is not None and self.det_annotations != []:
            self.chb_det_bb.setVisible(True)
        if self.gt_annotations is not None and self.gt_annotations != []:
            self.chb_gt_bb.setVisible(True)
        stats = stats.replace('#TOTAL_BB#', str(len(self.annot_obj)))
        stats = stats.replace(
            '#TOTAL_IMAGES#',
            str(BoundingBox.get_total_images(self.annot_obj)))
        stats = stats.replace(
            '#AVERAGE_AREA_BB#',
            '%.2f' % BoundingBox.get_average_area(self.annot_obj))
        # Get amount of bounding boxes per class
        self.bb_per_class = BoundingBox.get_amount_bounding_box_all_classes(
            self.annot_obj)
        amount_bb_per_class = 'No class found'
        if len(self.bb_per_class) > 0:
            amount_bb_per_class = ''
            longest_class_name = len(max(self.bb_per_class.keys(), key=len))
            for c, amount in self.bb_per_class.items():
                c = c.ljust(longest_class_name, ' ')
                amount_bb_per_class += f'   {c} : {amount}<br>'
        stats = stats.replace('#AMOUNT_BB_PER_CLASS#', amount_bb_per_class)
        self.txb_statistics.setText(stats)

        # get first image file and show it
        if os.path.isdir(self.dir_images):
            self.image_files = get_files_dir(
                self.dir_images,
                extensions=['jpg', 'jpge', 'png', 'bmp', 'tiff', 'tif'])
            if len(self.image_files) > 0:
                self.selected_image_index = 0
            else:
                self.selected_image_index = -1
        else:
            self.image_files = []
            self.selected_image_index = -1
        self.show_image()
Exemplo n.º 2
0
def cvat2bb(path):
    '''This format supports ground-truth only'''
    ret = []
    # Get annotation files in the path
    annotation_files = _get_annotation_files(path)
    # Loop through each file
    for file_path in annotation_files:
        if not validations.is_cvat_format(file_path):
            continue

        # Loop through the images
        for image_info in ET.parse(file_path).iter('image'):
            img_size = (int(image_info.attrib['width']),
                        int(image_info.attrib['height']))
            img_name = image_info.attrib['name']
            img_name = general_utils.get_file_name_only(img_name)

            # Loop through the boxes
            for box_info in image_info.iter('box'):
                x1, y1, x2, y2 = float(box_info.attrib['xtl']), float(
                    box_info.attrib['ytl']), float(
                        box_info.attrib['xbr']), float(box_info.attrib['ybr'])
                x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)

                bb = BoundingBox(image_name=img_name,
                                 class_id=box_info.attrib['label'],
                                 coordinates=(x1, y1, x2, y2),
                                 img_size=img_size,
                                 type_coordinates=CoordinatesType.ABSOLUTE,
                                 bb_type=BBType.GROUND_TRUTH,
                                 format=BBFormat.XYX2Y2)
                ret.append(bb)
    return ret
Exemplo n.º 3
0
def imagenet2bb(annotations_path):
    ret = []
    # Get annotation files in the path
    annotation_files = _get_annotation_files(annotations_path)
    # Loop through each file
    for file_path in annotation_files:
        if not validations.is_imagenet_format(file_path):
            continue
        # Open XML
        img_name = ET.parse(file_path).find('filename').text
        img_name = general_utils.get_file_name_only(img_name)
        img_width = int(ET.parse(file_path).find('size/width').text)
        img_height = int(ET.parse(file_path).find('size/height').text)
        img_size = (img_width, img_height)
        # Loop through the detections
        for box_info in ET.parse(file_path).iter('object'):
            obj_class = box_info.find('name').text
            x1 = int(float(box_info.find('bndbox/xmin').text))
            y1 = int(float(box_info.find('bndbox/ymin').text))
            x2 = int(float(box_info.find('bndbox/xmax').text))
            y2 = int(float(box_info.find('bndbox/ymax').text))
            bb = BoundingBox(image_name=img_name,
                             class_id=obj_class,
                             coordinates=(x1, y1, x2, y2),
                             img_size=img_size,
                             type_coordinates=CoordinatesType.ABSOLUTE,
                             bb_type=BBType.GROUND_TRUTH,
                             format=BBFormat.XYX2Y2)
            ret.append(bb)
    return ret
Exemplo n.º 4
0
    def __init__(self, image_path: str, waldo_bounding_box_json_file_path: str, debug: bool = False):
        logging_utils.init_logger(log_level_for_console='debug' if debug is True else 'info')
        self._logger = logging_utils.get_logger()

        self.waldo_bounding_box = BoundingBox.from_json(waldo_bounding_box_json_file_path)
        self._fail_circle_radius = int(min([self.waldo_bounding_box.right - self.waldo_bounding_box.left,
                                            self.waldo_bounding_box.bottom - self.waldo_bounding_box.top]) / 2)

        image = Image.open(image_path).transpose(Image.FLIP_TOP_BOTTOM)
        self._aspect_ratio = round(image.size[0] / image.size[1], 5)
        self.window_size: [int, int] = self._compute_initial_window_size(image.size)

        self.context: moderngl.Context = moderngl.create_standalone_context()
        self.graphic_engine = GraphicEngine(self.context, self.window_size, image)

        self.root = tk.Tk()
        self.root.title(self.WINDOW_TITLE)
        self.root.geometry(f'{self.window_size[0]}x{self.window_size[1]}')

        self.main_canvas: tk.Canvas = tk.Canvas(self.root)
        self.main_canvas.place(relwidth=1, relheight=1, anchor=tk.NW)

        self.framebuffer: TkinterFramebuffer = TkinterFramebuffer(self.context, self.window_size)
        self._add_framebuffer_image_to_canvas()

        self.root.protocol("WM_DELETE_WINDOW", self.before_closing)
        self.main_canvas.bind("<Configure>", self.on_resize)
        self.main_canvas.bind("<ButtonPress-1>", self.on_mouse_left_button_press)
        self.main_canvas.bind_all("<Key>", self.on_key_press)

        self._detections_circle_center_xy: [[float, float]] = []
def yolo2bb(annotations_path, images_dir, file_obj_names, bb_type=BBType.GROUND_TRUTH):
    ret = []
    if not os.path.isfile(file_obj_names):
        print(f'Warning: File with names of classes {file_obj_names} not found.')
        return ret
    # Load classes
    all_classes = []
    with open(file_obj_names, "r") as f:
        all_classes = [line.replace('\n', '') for line in f]
    # Get annotation files in the path
    annotation_files = _get_annotation_files(annotations_path)
    # Loop through each file
    for file_path in annotation_files:
        if not validations.is_yolo_format(file_path, bb_types=[bb_type]):
            continue
        img_name = os.path.basename(file_path)
        img_file = general_utils.find_file(images_dir, img_name, match_extension=False)
        img_resolution = general_utils.get_image_resolution(img_file)
        if img_resolution is None:
            print(f'Warning: It was not possible to find the resolution of image {img_name}')
            continue
        img_size = (img_resolution['width'], img_resolution['height'])
        # Loop through lines
        with open(file_path, "r") as f:
            for line in f:
                splitted_line = line.split(' ')
                class_id = splitted_line[0]
                if not general_utils.is_str_int(class_id):
                    print(
                        f'Warning: Class id represented in the {file_path} is not a valid integer.')
                    return []
                class_id = int(class_id)
                if class_id not in range(len(all_classes)):
                    print(
                        f'Warning: Class id represented in the {file_path} is not in the range of classes specified in the file {file_obj_names}.'
                    )
                    return []
                if bb_type == BBType.GROUND_TRUTH:
                    confidence = None
                    x1 = float(splitted_line[1])
                    y1 = float(splitted_line[2])
                    w = float(splitted_line[3])
                    h = float(splitted_line[4])
                elif bb_type == BBType.DETECTED:
                    confidence = float(splitted_line[1])
                    x1 = float(splitted_line[2])
                    y1 = float(splitted_line[3])
                    w = float(splitted_line[4])
                    h = float(splitted_line[5])
                bb = BoundingBox(image_name=general_utils.get_file_name_only(img_file),
                                 class_id=all_classes[class_id],
                                 coordinates=(x1, y1, w, h),
                                 img_size=img_size,
                                 confidence=confidence,
                                 type_coordinates=CoordinatesType.RELATIVE,
                                 bb_type=bb_type,
                                 format=BBFormat.XYWH)
                ret.append(bb)
    return ret
Exemplo n.º 6
0
def openimage2bb(annotations_path, images_dir, bb_type=BBType.GROUND_TRUTH):
    ret = []
    # Get annotation files in the path
    annotation_files = _get_annotation_files(annotations_path)
    # Loop through each file
    for file_path in annotation_files:
        if not validations.is_openimage_format(file_path):
            continue
        images_shapes = {}
        # Open csv
        csv = pd.read_csv(file_path, sep=',')
        for i, row in csv.iterrows():
            # Get image resolution if it was not loaded yet
            if row['ImageID'] not in images_shapes:
                img_name = row['ImageID']
                image_file = general_utils.find_file(images_dir, img_name)
                images_shapes[image_file] = general_utils.get_image_resolution(
                    image_file)
            if images_shapes[image_file] is None:
                print(
                    f'Warning: It was not possible to find the resolution of image {img_name}'
                )
                continue
            # Three is no bounding box for the given image
            if pd.isna(row['LabelName']) or pd.isna(row['XMin']) or pd.isna(
                    row['XMax']) or pd.isna(row['YMin']) or pd.isna(
                        row['YMax']):
                continue
                # images_shapes[image_file] = general_utils.get_image_resolution(image_file)
            img_size = (images_shapes[image_file]['width'],
                        images_shapes[image_file]['height'])
            x1, x2, y1, y2 = (row['XMin'], row['XMax'], row['YMin'],
                              row['YMax'])
            x1 = x1.replace(',', '.') if isinstance(x1, str) else x1
            x2 = x2.replace(',', '.') if isinstance(x2, str) else x2
            y1 = y1.replace(',', '.') if isinstance(y1, str) else y1
            y2 = y2.replace(',', '.') if isinstance(y2, str) else y2
            x1, x2, y1, y2 = float(x1), float(x2), float(y1), float(y2)
            confidence = None if pd.isna(row['Confidence']) else float(
                row['Confidence'])
            if bb_type == BBType.DETECTED and confidence is None:
                print(
                    f'Warning: Confidence value found in the CSV file for the image {img_name}'
                )
                return ret
            bb = BoundingBox(image_name=general_utils.get_file_name_only(
                row['ImageID']),
                             class_id=row['LabelName'],
                             coordinates=(x1, y1, x2, y2),
                             img_size=img_size,
                             confidence=confidence,
                             type_coordinates=CoordinatesType.RELATIVE,
                             bb_type=bb_type,
                             format=BBFormat.XYX2Y2)
            ret.append(bb)
    return ret
def coco2bb(path, bb_type=BBType.GROUND_TRUTH):
    ret = []
    # Get annotation files in the path
    annotation_files = _get_annotation_files(path)
    # Loop through each file
    for file_path in annotation_files:
        if not validations.is_coco_format(file_path):
            continue

        with open(file_path, "r") as f:
            json_object = json.load(f)

        # COCO json file contains basically 3 lists:
        # categories: containing the classes
        # images: containing information of the images (width, height and filename)
        # annotations: containing information of the bounding boxes (x1, y1, bb_width, bb_height)
        classes = {}
        if 'categories' in json_object:
            classes = json_object['categories']
            # into dictionary
            classes = {c['id']: c['name'] for c in classes}
        images = {}
        # into dictionary
        for i in json_object['images']:
            images[i['id']] = {
                'file_name': i['file_name'],
                'img_size': (int(i['width']), int(i['height']))
            }
        annotations = []
        if 'annotations' in json_object:
            annotations = json_object['annotations']

        for annotation in annotations:
            img_id = annotation['image_id']
            x1, y1, bb_width, bb_height = annotation['bbox']
            if bb_type == BBType.DETECTED and 'score' not in annotation.keys():
                print('Warning: Confidence not found in the JSON file!')
                return ret
            confidence = annotation[
                'score'] if bb_type == BBType.DETECTED else None
            # Make image name only the filename, without extension
            img_name = images[img_id]['file_name']
            img_name = general_utils.get_file_name_only(img_name)
            # create BoundingBox object
            bb = BoundingBox(image_name=img_name,
                             class_id=classes[annotation['category_id']],
                             coordinates=(x1, y1, bb_width, bb_height),
                             type_coordinates=CoordinatesType.ABSOLUTE,
                             img_size=images[img_id]['img_size'],
                             confidence=confidence,
                             bb_type=bb_type,
                             format=BBFormat.XYWH)
            ret.append(bb)
    return ret
Exemplo n.º 8
0
 def to_bb(index: int, annotation: AnnotatedBBox) -> BoundingBox:
     image_id = str(index)
     return BoundingBox(
         image_name=image_id,
         class_id=annotation.class_name,
         coordinates=annotation.bbox.xywh(),
         format=BBFormat.XYWH,
         bb_type=BBType.GROUND_TRUTH if annotation.type
         == AnnotationType.GROUND_TRUTH else BBType.DETECTED,
         confidence=annotation.confidence
         if annotation.type == AnnotationType.PREDICTION else None,
     )
Exemplo n.º 9
0
 def draw_bounding_boxes(self):
     # Load image to obtain a clean image (without BBs)
     img_path = os.path.join(self.dir_images,
                             self.image_files[self.selected_image_index])
     img = cv2.imread(img_path)
     img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
     # Get bounding boxes of the loaded image
     img_name = self.image_files[self.selected_image_index]
     img_name = general_utils.get_file_name_only(img_name)
     # Add bounding boxes depending if the item is checked
     if self.chb_gt_bb.isChecked() and self.gt_annotations is not None:
         bboxes = BoundingBox.get_bounding_boxes_by_image_name(
             self.gt_annotations, img_name)
         if len(bboxes) == 0:
             bboxes = BoundingBox.get_bounding_boxes_by_image_name(
                 self.gt_annotations, img_name)
         # Draw bounding boxes
         for bb in bboxes:
             img = add_bb_into_image(img,
                                     bb,
                                     color=(0, 255, 0),
                                     thickness=2,
                                     label=None)
     if self.chb_det_bb.isChecked() and self.det_annotations is not None:
         bboxes = BoundingBox.get_bounding_boxes_by_image_name(
             self.det_annotations, img_name)
         if len(bboxes) == 0:
             bboxes = BoundingBox.get_bounding_boxes_by_image_name(
                 self.det_annotations, img_name)
         # Draw bounding boxes
         for bb in bboxes:
             img = add_bb_into_image(img,
                                     bb,
                                     color=(0, 0, 255),
                                     thickness=2,
                                     label=None)
     return img
Exemplo n.º 10
0
def main():
    logging.basicConfig(filename='preproces_dateset.log', level=logging.DEBUG)

    logging.info("Scanning content of dataset")
    content = file.scan_content(config.set_path)

    logging.info("Dividing data into groups")
    divided_content = divide_dataset.divide(content)

    bounding_boxes = BoundingBox.get_bounding_boxes(config.bounding_boxes_path)
    logging.info("Starting image preprocessing")
    counter = 0
    for key in divided_content.keys():
        augment = False
        if key == "training":
            augment = True
            logging.info("Training data will be augmented.")
        database = h5py.File(config.get_convolution_datasets_path(key), 'w')
        for (cls_name, img_name) in divided_content[key]:
            counter += 1
            if counter % config.take_every_nth_sample != 0:
                continue

            if cls_name not in database.keys():
                database.create_group(cls_name)
            cls_path = file.add_folder(config.set_path, cls_name)
            if augment:
                augmented_data = augment_images(
                    load_and_preprocess_img(cls_path, img_name,
                                            bounding_boxes))
                augmented_files = [
                    file.remove_extension(img_name) + "_" + str(i)
                    for i in range(len(augmented_data))
                ]
                for img, name in zip(augmented_data, augmented_files):
                    database[cls_name].create_dataset(name, data=img)
            else:
                database[cls_name].create_dataset(
                    file.remove_extension(img_name),
                    data=load_and_preprocess_img(cls_path, img_name,
                                                 bounding_boxes))
        database.close()
    logging.info("Image loading finished")
Exemplo n.º 11
0
def labelme2bb(annotations_path):
    ret = []
    # Get annotation files in the path
    annotation_files = _get_annotation_files(annotations_path)
    # Loop through each file
    for file_path in annotation_files:
        if not validations.is_labelme_format(file_path):
            continue
        # Parse the JSON file
        with open(file_path, "r") as f:
            json_object = json.load(f)
        img_path = json_object['imagePath']
        img_path = os.path.basename(img_path)
        img_path = general_utils.get_file_name_only(img_path)
        img_size = (int(json_object['imageWidth']),
                    int(json_object['imageHeight']))
        # If there are annotated objects
        if 'shapes' in json_object:
            # Loop through bounding boxes
            for obj in json_object['shapes']:
                obj_label = obj['label']
                ((x1, y1), (x2, y2)) = obj['points']
                # If there is no bounding box annotations, bb coordinates could have been set to None
                if x1 is None and y1 is None and x2 is None and y2 is None:
                    continue
                x1, y1, x2, y2 = int(float(x1)), int(float(y1)), int(
                    float(x2)), int(float(y2))

                bb = BoundingBox(image_name=img_path,
                                 class_id=obj_label,
                                 coordinates=(x1, y1, x2, y2),
                                 img_size=img_size,
                                 confidence=None,
                                 type_coordinates=CoordinatesType.ABSOLUTE,
                                 bb_type=BBType.GROUND_TRUTH,
                                 format=BBFormat.XYX2Y2)
                ret.append(bb)
    return ret
        for photo in split_ids[group_name]['data']:
            class_name = photo[0]
            if class_name not in group_db.keys():
                group_db.create_group(class_name)
            for i in range(0, config.data_multiplication_factor):
                photo_name = photo[1] + "_" + str(i)
                group_db[class_name].create_dataset(
                    photo_name, data=features_db[class_name][photo_name])
        group_db.close()


if __name__ == "__main__":
    logging.basicConfig(filename="sift.log", level=logging.DEBUG)

    features_db = h5py.File(config.features_db_path, "w")
    bounding_boxes = BoundingBox.get_bounding_boxes(config.bounding_boxes_path)

    counter = 0
    logging.info("Starting extraction")
    for class_path in file.gen_subdir_path(config.set_path):
        class_descriptors = features_db.create_group(
            file.get_folder(class_path))
        for photo_path, photo_name in file.gen_file_path(class_path):
            counter += 1
            if counter % config.take_every_nth_sample != 0:
                continue
            # removes file extension
            photo_name_hash = file.remove_extension(photo_name)
            bb = bounding_boxes[photo_name_hash]
            photo_desc = execute_sift_extraction(photo_path, bb, 1)
            for i, pic in enumerate(photo_desc):
Exemplo n.º 13
0
def text2bb(annotations_path,
            bb_type=BBType.GROUND_TRUTH,
            bb_format=BBFormat.XYWH,
            type_coordinates=CoordinatesType.ABSOLUTE,
            img_dir=None):
    ret = []

    # Get annotation files in the path
    annotation_files = _get_annotation_files(annotations_path)
    for file_path in annotation_files:
        if type_coordinates == CoordinatesType.ABSOLUTE:
            if bb_type == BBType.GROUND_TRUTH and not validations.is_absolute_text_format(
                    file_path, num_blocks=[5], blocks_abs_values=[4]):
                continue
            if bb_type == BBType.DETECTED and not validations.is_absolute_text_format(
                    file_path, num_blocks=[6], blocks_abs_values=[4]):
                continue
        elif type_coordinates == CoordinatesType.RELATIVE:
            if bb_type == BBType.GROUND_TRUTH and not validations.is_relative_text_format(
                    file_path, num_blocks=[5], blocks_rel_values=[4]):
                continue
            if bb_type == BBType.DETECTED and not validations.is_relative_text_format(
                    file_path, num_blocks=[6], blocks_rel_values=[4]):
                continue
        # Loop through lines
        with open(file_path, "r") as f:

            img_filename = os.path.basename(file_path)
            img_filename = os.path.splitext(img_filename)[0]

            img_size = None
            # If coordinates are relative, image size must be obtained in the img_dir
            if type_coordinates == CoordinatesType.RELATIVE:
                img_path = general_utils.find_file(img_dir,
                                                   img_filename,
                                                   match_extension=False)
                if img_path is None or os.path.isfile(img_path) is False:
                    print(
                        f'Warning: Image not found in the directory {img_path}. It is required to get its dimensions'
                    )
                    return ret
                resolution = general_utils.get_image_resolution(img_path)
                img_size = (resolution['width'], resolution['height'])
            for line in f:
                if line.replace(' ', '') == '\n':
                    continue
                splitted_line = line.split(' ')
                class_id = splitted_line[0]
                if bb_type == BBType.GROUND_TRUTH:
                    confidence = None
                    x1 = float(splitted_line[1])
                    y1 = float(splitted_line[2])
                    w = float(splitted_line[3])
                    h = float(splitted_line[4])
                elif bb_type == BBType.DETECTED:
                    confidence = float(splitted_line[1])
                    x1 = float(splitted_line[2])
                    y1 = float(splitted_line[3])
                    w = float(splitted_line[4])
                    h = float(splitted_line[5])
                bb = BoundingBox(image_name=img_filename,
                                 class_id=class_id,
                                 coordinates=(x1, y1, w, h),
                                 img_size=img_size,
                                 confidence=confidence,
                                 type_coordinates=type_coordinates,
                                 bb_type=bb_type,
                                 format=bb_format)
                # If the format is correct, x,y,w,h,x2,y2 must be positive
                x, y, w, h = bb.get_absolute_bounding_box(format=BBFormat.XYWH)
                _, _, x2, y2 = bb.get_absolute_bounding_box(
                    format=BBFormat.XYX2Y2)
                if x < 0 or y < 0 or w < 0 or h < 0 or x2 < 0 or y2 < 0:
                    continue
                ret.append(bb)
    return ret
def get_pascalvoc_metrics(gt_boxes,
                          det_boxes,
                          iou_threshold=0.5,
                          method=MethodAveragePrecision.EVERY_POINT_INTERPOLATION,
                          generate_table=False):
    """Get the metrics used by the VOC Pascal 2012 challenge.
    Args:
        boundingboxes: Object of the class BoundingBoxes representing ground truth and detected
        bounding boxes;
        iou_threshold: IOU threshold indicating which detections will be considered TP or FP
        (dget_pascalvoc_metricsns:
        A dictioanry contains information and metrics of each class.
        The key represents the class and the values are:
        dict['class']: class representing the current dictionary;
        dict['precision']: array with the precision values;
        dict['recall']: array with the recall values;
        dict['AP']: average precision;
        dict['interpolated precision']: interpolated precision values;
        dict['interpolated recall']: interpolated recall values;
        dict['total positives']: total number of ground truth positives;
        dict['total TP']: total number of True Positive detections;
        dict['total FP']: total number of False Positive detections;"""
    ret = {}
    # Get classes of all bounding boxes separating them by classes
    gt_classes_only = []
    classes_bbs = {}
    for bb in gt_boxes:
        c = bb.get_class_id()
        gt_classes_only.append(c)
        classes_bbs.setdefault(c, {'gt': [], 'det': []})
        classes_bbs[c]['gt'].append(bb)
    gt_classes_only = list(set(gt_classes_only))
    for bb in det_boxes:
        c = bb.get_class_id()
        classes_bbs.setdefault(c, {'gt': [], 'det': []})
        classes_bbs[c]['det'].append(bb)

    # Precision x Recall is obtained individually by each class
    for c, v in classes_bbs.items():
        # Report results only in the classes that are in the GT
        if c not in gt_classes_only:
            continue
        npos = len(v['gt'])
        # sort detections by decreasing confidence
        dects = [a for a in sorted(v['det'], key=lambda bb: bb.get_confidence(), reverse=True)]
        TP = np.zeros(len(dects))
        FP = np.zeros(len(dects))
        # create dictionary with amount of expected detections for each image
        detected_gt_per_image = Counter([bb.get_image_name() for bb in gt_boxes])
        for key, val in detected_gt_per_image.items():
            detected_gt_per_image[key] = np.zeros(val)
        # print(f'Evaluating class: {c}')
        dict_table = {
            'image': [],
            'confidence': [],
            'TP': [],
            'FP': [],
            'acc TP': [],
            'acc FP': [],
            'precision': [],
            'recall': []
        }
        # Loop through detections
        for idx_det, det in enumerate(dects):
            img_det = det.get_image_name()

            if generate_table:
                dict_table['image'].append(img_det)
                dict_table['confidence'].append(f'{100*det.get_confidence():.2f}%')

            # Find ground truth image
            gt = [gt for gt in classes_bbs[c]['gt'] if gt.get_image_name() == img_det]
            # Get the maximum iou among all detectins in the image
            iouMax = sys.float_info.min
            # Given the detection det, find ground-truth with the highest iou
            for j, g in enumerate(gt):
                # print('Ground truth gt => %s' %
                #       str(g.get_absolute_bounding_box(format=BBFormat.XYX2Y2)))
                iou = BoundingBox.iou(det, g)
                if iou > iouMax:
                    iouMax = iou
                    id_match_gt = j
            # Assign detection as TP or FP
            if iouMax >= iou_threshold:
                # gt was not matched with any detection
                if detected_gt_per_image[img_det][id_match_gt] == 0:
                    TP[idx_det] = 1  # detection is set as true positive
                    detected_gt_per_image[img_det][
                        id_match_gt] = 1  # set flag to identify gt as already 'matched'
                    # print("TP")
                    if generate_table:
                        dict_table['TP'].append(1)
                        dict_table['FP'].append(0)
                else:
                    FP[idx_det] = 1  # detection is set as false positive
                    if generate_table:
                        dict_table['FP'].append(1)
                        dict_table['TP'].append(0)
                    # print("FP")
            # - A detected "cat" is overlaped with a GT "cat" with IOU >= iou_threshold.
            else:
                FP[idx_det] = 1  # detection is set as false positive
                if generate_table:
                    dict_table['FP'].append(1)
                    dict_table['TP'].append(0)
                # print("FP")
        # compute precision, recall and average precision
        acc_FP = np.cumsum(FP)
        acc_TP = np.cumsum(TP)
        rec = acc_TP / npos
        prec = np.divide(acc_TP, (acc_FP + acc_TP))
        if generate_table:
            dict_table['acc TP'] = list(acc_TP)
            dict_table['acc FP'] = list(acc_FP)
            dict_table['precision'] = list(prec)
            dict_table['recall'] = list(rec)
            table = pd.DataFrame(dict_table)
        else:
            table = None
        # Depending on the method, call the right implementation
        if method == MethodAveragePrecision.EVERY_POINT_INTERPOLATION:
            [ap, mpre, mrec, ii] = calculate_ap_every_point(rec, prec)
        elif method == MethodAveragePrecision.ELEVEN_POINT_INTERPOLATION:
            [ap, mpre, mrec, _] = calculate_ap_11_point_interp(rec, prec)
        else:
            Exception('method not defined')
        # add class result in the dictionary to be returned
        ret[c] = {
            'precision': prec,
            'recall': rec,
            'AP': ap,
            'interpolated precision': mpre,
            'interpolated recall': mrec,
            'total positives': npos,
            'total TP': np.sum(TP),
            'total FP': np.sum(FP),
            'method': method,
            'iou': iou_threshold,
            'table': table
        }
    # For mAP, only the classes in the gt set should be considered
    mAP = sum([v['AP'] for k, v in ret.items() if k in gt_classes_only]) / len(gt_classes_only)
    return {'per_class': ret, 'mAP': mAP}
Exemplo n.º 15
0
 def airports_within_radius(self):
     bounding_box = BoundingBox(self.point, self.radius)
     self.filter_circle(self.query.airports_inside(bounding_box.list()))