ModuleNotFoundError: No module named ‘podm.metrics‘报错等解决方法

ModuleNotFoundError: No module named 'podm.metrics’报错等解决方法

podm.metrics

在运行时报错:

ModuleNotFoundError: No module named ‘podm.metrics’

安装了podm后还是报错
解决方法:

查看安装位置

查看podm的安装位置,并打开到该位置(ctrl+点击位置):

pip show podm

在这里插入图片描述

新建metrics文件

在该位置下找到podm文件夹,发现其中没有metrics.py文件,故新建该文件

在这里插入图片描述
并将一下代码粘贴在文件中:

import sys
from collections import Counter, defaultdict
from enum import Enum
from typing import List, Dict, Any, Tuple

import numpy as np

from podm import box
from podm.coco import PCOCOObjectDetectionDataset, PCOCOBoundingBox, PCOCOSegments


class BoundingBox(box.Box):
    """
    image: image.
    category: category.
    xtl: the X top-left coordinate of the bounding box.
    ytl: the Y top-left coordinate of the bounding box.
    xbr: the X bottom-right coordinate of the bounding box.
    ybr: the Y bottom-right coordinate of the bounding box.
    score: (optional) the confidence of the detected class.
    """
    def __init__(self):
        super(BoundingBox, self).__init__()
        self.image = None
        self.category = None
        self.score = None  # type: float or None

    @classmethod
    def of_bbox(cls, image, category, xtl: float, ytl: float, xbr: float, ybr: float, score: float = None) \
            -> 'BoundingBox':
        bbox = BoundingBox()
        bbox.xtl = xtl
        bbox.ytl = ytl
        bbox.xbr = xbr
        bbox.ybr = ybr
        bbox.image = image
        bbox.score = score
        bbox.category = category
        return bbox


def get_bounding_boxes(dataset: PCOCOObjectDetectionDataset, use_name: bool = True) -> List[BoundingBox]:
    bboxes = []
    for ann in dataset.annotations:
        if isinstance(ann, PCOCOBoundingBox):
            bb = BoundingBox.of_bbox(ann.image_id, ann.category_id, ann.xtl, ann.ytl, ann.xbr, ann.ybr, ann.score)
        elif isinstance(ann, PCOCOSegments):
            bb = BoundingBox.of_bbox(ann.image_id, ann.category_id,
                                     ann.bbox.xtl, ann.bbox.ytl, ann.bbox.xbr, ann.bbox.ybr, ann.score)
        else:
            raise TypeError
        if use_name:
            bb.image = dataset.get_image(id=ann.image_id).file_name
            bb.category = dataset.get_category(id=ann.category_id).name
        bboxes.append(bb)
    return bboxes


class MethodAveragePrecision(Enum):
    """
    Class representing if the coordinates are relative to the
    image size or are absolute values.

        Developed by: Rafael Padilla
        Last modification: Apr 28 2018
    """
    AllPointsInterpolation = 1
    ElevenPointsInterpolation = 2


class MetricPerClass:
    def __init__(self):
        self.label = None
        self.precision = None
        self.recall = None
        self.ap = None
        self.interpolated_precision = None  # type: None or np.ndarray
        self.interpolated_recall = None  # type: None or np.ndarray
        self.num_groundtruth = None
        self.num_detection = None
        self.tp = None
        self.fp = None

    @staticmethod
    def mAP(results: Dict[Any, 'MetricPerClass']):
        return np.average([m.ap for m in results.values() if m.num_groundtruth > 0])


def get_pascal_voc_metrics(gold_standard: List[BoundingBox],
                           predictions: List[BoundingBox],
                           iou_threshold: float = 0.5,
                           method: MethodAveragePrecision = MethodAveragePrecision.AllPointsInterpolation
                           ) -> Dict[str, MetricPerClass]:
    """Get the metrics used by the VOC Pascal 2012 challenge.

    Args:
        gold_standard: ground truth bounding boxes;
        predictions: detected bounding boxes;
        iou_threshold: IOU threshold indicating which detections will be considered TP or FP (default value = 0.5);
        method: It can be calculated as the implementation in the official PASCAL VOC toolkit (EveryPointInterpolation),
            or applying the 11-point interpolation as described in the paper "The PASCAL Visual Object Classes(VOC)
            Challenge" or AllPointsInterpolation" (ElevenPointInterpolation);
    Returns:
        A dictionary containing metrics of each class.
    """
    ret = {}  # list containing metrics (precision, recall, average precision) of each class

    # Get all classes
    categories = sorted(set(b.category for b in gold_standard + predictions))

    # Precision x Recall is obtained individually by each class
    # Loop through by classes
    for category in categories:
        preds = [b for b in predictions if b.category == category]  # type: List[BoundingBox]
        golds = [b for b in gold_standard if b.category == category]  # type: List[BoundingBox]
        npos = len(golds)

        # sort detections by decreasing confidence
        preds = sorted(preds, key=lambda b: b.score, reverse=True)
        tps = np.zeros(len(preds))
        fps = np.zeros(len(preds))

        # create dictionary with amount of gts for each image
        counter = Counter([cc.image for cc in golds])
        for key, val in counter.items():
            counter[key] = np.zeros(val)

        # Pre-processing groundtruths of the some image
        image_name2gt = defaultdict(list)
        for b in golds:
            image_name2gt[b.image].append(b)

        # Loop through detections
        for i in range(len(preds)):
            # Find ground truth image
            gt = image_name2gt[preds[i].image]
            max_iou = sys.float_info.min
            mas_idx = -1
            for j in range(len(gt)):
                iou = box.intersection_over_union(preds[i], gt[j])
                if iou > max_iou:
                    max_iou = iou
                    mas_idx = j
            # Assign detection as true positive/don't care/false positive
            if max_iou >= iou_threshold:
                if counter[preds[i].image][mas_idx] == 0:
                    tps[i] = 1  # count as true positive
                    counter[preds[i].image][mas_idx] = 1  # flag as already 'seen'
                else:
                    # - A detected "cat" is overlaped with a GT "cat" with IOU >= IOUThreshold.
                    fps[i] = 1  # count as false positive
            else:
                fps[i] = 1  # count as false positive
        # compute precision, recall and average precision
        cumulative_fps = np.cumsum(fps)
        cumulative_tps = np.cumsum(tps)
        recalls = np.divide(cumulative_tps, npos, out=np.full_like(cumulative_tps, np.nan), where=npos != 0)
        precisions = np.divide(cumulative_tps, (cumulative_fps + cumulative_tps))
        # Depending on the method, call the right implementation
        if method == MethodAveragePrecision.AllPointsInterpolation:
            ap, mrec, mpre, _ = calculate_all_points_average_precision(recalls, precisions)
        else:
            ap, mrec, mpre = calculate_11_points_average_precision(recalls, precisions)
        # add class result in the dictionary to be returned
        r = MetricPerClass()
        r.label = category
        r.precision = precisions
        r.recall = recalls
        r.ap = ap
        r.interpolated_recall = np.array(mrec)
        r.interpolated_precision = np.array(mpre)
        r.tp = np.sum(tps)
        r.fp = np.sum(fps)
        r.num_groundtruth = len(golds)
        r.num_detection = len(preds)
        ret[category] = r
    return ret


def calculate_all_points_average_precision(recall: List[float], precision: List[float]) \
        -> Tuple[float, List[float], List[float], List[int]]:
    """
    All-point interpolated average precision

    Returns:
        average precision
        interpolated recall
        interpolated precision
        interpolated points
    """
    mrec = [0.0] + [e for e in recall] + [1.0]
    mpre = [0.0] + [e for e in precision] + [0]
    for i in range(len(mpre) - 1, 0, -1):
        mpre[i - 1] = max(mpre[i - 1], mpre[i])
    ii = []
    for i in range(len(mrec) - 1):
        if mrec[i + 1] != mrec[i]:
            ii.append(i + 1)
    ap = 0
    for i in ii:
        ap = ap + np.sum((mrec[i] - mrec[i - 1]) * mpre[i])
    return ap, mrec[0:len(mpre) - 1], mpre[0:len(mpre) - 1], ii


def calculate_11_points_average_precision(recall: List[float], precision: List[float]) -> Tuple[float, List[float], List[float]]:
    """
    11-point interpolated average precision. This is done by segmenting the recalls evenly into 11 parts:
        {0,0.1,0.2,...,0.9,1}.

    Args:
        recall: recall list
        precision: precision list

    Returns:
        average precision, interpolated recall, interpolated precision

    """
    mrec = [e for e in recall]
    mpre = [e for e in precision]
    recall_values = np.linspace(0, 1, 11)
    recall_values = list(recall_values[::-1])
    rho_interp = []
    recall_valid = []
    # For each recallValues (0, 0.1, 0.2, ... , 1)
    for r in recall_values:
        # Obtain all recall values higher or equal than r
        arg_greater_recalls = np.argwhere(mrec[:] >= r)
        pmax = 0
        # If there are recalls above r
        if arg_greater_recalls.size != 0:
            pmax = max(mpre[arg_greater_recalls.min():])
        recall_valid.append(r)
        rho_interp.append(pmax)
    # By definition AP = sum(max(precision whose recall is above r))/11
    ap = sum(rho_interp) / 11
    # Generating values for the plot
    rvals = [recall_valid[0]] + [e for e in recall_valid] + [0]
    pvals = [0] + [e for e in rho_interp] + [0]
    # rhoInterp = rhoInterp[::-1]
    cc = []
    for i in range(len(rvals)):
        p = (rvals[i], pvals[i - 1])
        if p not in cc:
            cc.append(p)
        p = (rvals[i], pvals[i])
        if p not in cc:
            cc.append(p)
    recall_values = [i[0] for i in reversed(cc)]
    precision_values = [i[1] for i in reversed(cc)]
    return ap, recall_values, precision_values

podm.box

报错:

ModuleNotFoundError: No module named ‘podm.coco’

新建coco.py文件,并添加以下内容:

from enum import Enum
from typing import Tuple


class Box:
    """
                0,0 ------> x (width)
         |
         |  (Left,Top)
         |      *_________
         |      |         |
                |         |
         y      |_________|
      (height)            *
                    (Right,Bottom)

    xtl: the X top-left coordinate of the bounding box.
    ytl: the Y top-left coordinate of the bounding box.
    xbr: the X bottom-right coordinate of the bounding box.
    ybr: the Y bottom-right coordinate of the bounding box.
    """
    def __init__(self):
        self.xtl = None  # type: float or None
        self.ytl = None  # type: float or None
        self.xbr = None  # type: float or None
        self.ybr = None  # type: float or None

    @classmethod
    def of_box(cls, xtl: float, ytl: float, xbr: float, ybr: float) -> 'Box':
        """
        :param xtl: the X top-left coordinate of the bounding box.
        :param ytl: the Y top-left coordinate of the bounding box.
        :param xbr: the X bottom-right coordinate of the bounding box.
        :param ybr: the Y bottom-right coordinate of the bounding box.
        """
        box = Box()
        box.xtl = xtl
        box.ytl = ytl
        box.xbr = xbr
        box.ybr = ybr
        box.verify()
        return box

    def set_box(self, box: 'Box'):
        self.xtl = box.xtl
        self.ytl = box.ytl
        self.xbr = box.xbr
        self.ybr = box.ybr

    def verify(self):
        assert self.xtl <= self.xbr, f'xtl < xbr: xtl:{self.xtl}, xbr:{self.xbr}'
        assert self.ytl <= self.ybr, f'ytl < ybr: ytl:{self.ytl}, xbr:{self.ybr}'

    @property
    def segment(self):
        return [self.xtl, self.ytl, self.xtl, self.ybr, self.xbr, self.ybr, self.xbr, self.ytl]

    @property
    def width(self) -> float:
        return self.xbr - self.xtl

    @property
    def height(self) -> float:
        return self.ybr - self.ytl

    @property
    def area(self) -> float:
        return (self.xbr - self.xtl) * (self.ybr - self.ytl)

    @property
    def center(self) -> Tuple[float, float]:
        return (self.xbr + self.xtl) / 2, (self.ybr + self.ytl) / 2

    def __contains__(self, item):
        if not type(item) == list and not type(item) == tuple:
            raise TypeError('Has to be a list or a tuple: %s' % type(item))
        if len(item) == 2:
            return self.xtl <= item[0] < self.xbr and self.ytl <= item[1] < self.ybr
        else:
            raise ValueError('Only support a point')

    def __str__(self):
        return 'Box[xtl={},ytl={},xbr={},ybr={}]'.format(self.xtl, self.ytl, self.xbr, self.ybr)

    def __eq__(self, other):
        if not isinstance(other, Box):
            return False
        return self.xtl == other.xtl and self.ytl == other.ytl and self.xbr == other.xbr and self.ybr == other.ybr


def intersection_over_union(box1: 'Box', box2: 'Box') -> float:
    """
    Intersection Over Union (IOU) is measure based on Jaccard Index that evaluates the overlap between
    two bounding boxes.
    """
    # if boxes dont intersect
    if not is_intersecting(box1, box2):
        return 0
    intersection_area = intersection(box1, box2).area
    union = union_areas(box1, box2, intersection_area=intersection_area)
    # intersection over union
    iou = intersection_area / union
    assert iou >= 0, '{} = {} / {}, box1={}, box2={}'.format(iou, intersection, union, box1, box2)
    return iou


def is_intersecting(box1: 'Box', box2: 'Box') -> bool:
    if box1.xtl > box2.xbr:
        return False  # boxA is right of boxB
    if box2.xtl > box1.xbr:
        return False  # boxA is left of boxB
    if box1.ybr < box2.ytl:
        return False  # boxA is above boxB
    if box1.ytl > box2.ybr:
        return False  # boxA is below boxB
    return True


def union_areas(box1: 'Box', box2: 'Box', intersection_area: float = None) -> float:
    if intersection_area is None:
        intersection_area = intersection(box1, box2).area
    return box1.area + box2.area - intersection_area


def union(box1: 'Box', box2: 'Box'):
    xtl = min(box1.xtl, box2.xtl)
    ytl = min(box1.ytl, box2.ytl)
    xbr = max(box1.xbr, box2.xbr)
    ybr = max(box1.ybr, box2.ybr)
    return Box.of_box(xtl, ytl, xbr, ybr)


def intersection(box1: 'Box', box2: 'Box'):
    xtl = max(box1.xtl, box2.xtl)
    ytl = max(box1.ytl, box2.ytl)
    xbr = min(box1.xbr, box2.xbr)
    ybr = min(box1.ybr, box2.ybr)
    return Box.of_box(xtl, ytl, xbr, ybr)


class BBFormat(Enum):
    """
    Class representing the format of a bounding box.
    It can be (X,Y,width,height) => XYWH
    or (X1,Y1,X2,Y2) => XYX2Y2

        Developed by: Rafael Padilla
        Last modification: May 24 2018
    """
    XYWH = 1
    X1Y1X2Y2 = 2


# class BoundingBox(Box):
#     def __init__(self):
#         """Constructor.
#         Args:
#             image: image.
#             category: category.
#             xtl: the X top-left coordinate of the bounding box.
#             ytl: the Y top-left coordinate of the bounding box.
#             xbr: the X bottom-right coordinate of the bounding box.
#             ybr: the Y bottom-right coordinate of the bounding box.
#             score: (optional) the confidence of the detected class.
#         """
#         super(BoundingBox, self).__init__()
#         self.image = None
#         self.category = None
#         self.score = None  # type: float or None
#
#     @classmethod
#     def of_bbox(cls, image, category, xtl: float, ytl: float, xbr: float, ybr: float, score: float = None) \
#             -> 'BoundingBox':
#         bbox = BoundingBox()
#         bbox.xtl = xtl
#         bbox.ytl = ytl
#         bbox.xbr = xbr
#         bbox.ybr = ybr
#         bbox.image = image
#         bbox.score = score
#         bbox.category = category
#         return bbox

podm.coco_decoder

新建coco_decoder.py文件,并添加代码:

import copy
import json
from typing import Dict

from podm.coco import PCOCOLicense, PCOCOInfo, PCOCOImage, PCOCOCategory, PCOCOBoundingBox, PCOCOSegments, \
    PCOCOObjectDetectionDataset


def parse_infon(obj: Dict) -> PCOCOInfo:
    info = PCOCOInfo()
    info.contributor = obj['contributor']
    info.description = obj['description']
    info.url = obj['url']
    info.date_created = obj['date_created']
    info.version = obj['version']
    info.year = obj['year']
    return info


def parse_license(obj: Dict) -> PCOCOLicense:
    lic = PCOCOLicense()
    lic.id = obj['id']
    lic.name = obj['name']
    lic.url = obj['url']
    return lic


def parse_image(obj: Dict) -> PCOCOImage:
    img = PCOCOImage()
    img.id = obj['id']
    img.height = obj['height']
    img.width = obj['width']
    img.file_name = obj['file_name']
    img.flickr_url = obj['flickr_url']
    img.coco_url = obj['coco_url']
    img.date_captured = obj['date_captured']
    img.license = obj['license']
    return img


def parse_bounding_box(obj: Dict) -> PCOCOBoundingBox:
    ann = PCOCOBoundingBox()
    ann.id = obj['id']
    ann.category_id = obj['category_id']
    ann.image_id = obj['image_id']
    ann.xtl = obj['bbox'][0]
    ann.ytl = obj['bbox'][1]
    ann.xbr = ann.xtl + obj['bbox'][2]
    ann.ybr = ann.ytl + obj['bbox'][3]
    if 'contributor' in obj:
        ann.contributor = obj['contributor']
    if 'score' in obj:
        ann.score = obj['score']
    if 'attributes' in obj:
        ann.attributes = obj['attributes']
    return ann


def parse_segments(obj: Dict) -> PCOCOSegments:
    ann = PCOCOSegments()
    ann.id = obj['id']
    ann.category_id = obj['category_id']
    ann.image_id = obj['image_id']
    ann.iscrowd = obj['iscrowd']
    ann.segmentation = obj['segmentation']
    if 'score' in obj:
        ann.score = obj['score']
    if 'contributor' in obj:
        ann.contributor = obj['contributor']
    if 'attributes' in obj:
        ann.attributes = obj['attributes']
    return ann


def parse_category(obj: Dict) -> PCOCOCategory:
    cat = PCOCOCategory()
    cat.id = obj['id']
    cat.name = obj['name']
    cat.supercategory = obj['supercategory']
    return cat


def parse_object_detection_dataset(coco_obj: Dict) -> PCOCOObjectDetectionDataset:
    dataset = PCOCOObjectDetectionDataset()
    dataset.info = parse_infon(coco_obj['info'])

    for lic_obj in coco_obj['licenses']:
        lic = parse_license(lic_obj)
        dataset.licenses.append(lic)

    for img_obj in coco_obj['images']:
        img = parse_image(img_obj)
        dataset.images.append(img)

    for ann_obj in coco_obj['annotations']:
        if 'segmentation' in ann_obj and len(ann_obj['segmentation']) > 0:
            ann = parse_segments(ann_obj)
        else:
            ann = parse_bounding_box(ann_obj)
        dataset.add_annotation(ann)

    for cat_obj in coco_obj['categories']:
        cat = parse_category(cat_obj)
        dataset.categories.append(cat)

    return dataset


def load_true_object_detection_dataset(fp, **kwargs) -> PCOCOObjectDetectionDataset:
    coco_obj = json.load(fp, **kwargs)
    return parse_object_detection_dataset(coco_obj)


def load_pred_object_detection_dataset(fp, dataset: PCOCOObjectDetectionDataset, **kwargs) \
        -> PCOCOObjectDetectionDataset:
    new_dataset = PCOCOObjectDetectionDataset()
    new_dataset.info = copy.deepcopy(dataset.info)
    new_dataset.licenses = copy.deepcopy(dataset.licenses)
    new_dataset.images = copy.deepcopy(dataset.images)
    new_dataset.categories = copy.deepcopy(dataset.categories)
    # check annotation
    coco_obj = json.load(fp, **kwargs)
    annotations = []
    for obj in coco_obj:
        ann = parse_bounding_box(obj)
        if new_dataset.get_image(id=ann.image_id) is None:
            print('%s: Cannot find image' % ann.image_id)
        if new_dataset.get_category(id=ann.category_id) is None:
            print('%s: Cannot find category' % ann.category_id)
        annotations.append(ann)
    new_dataset.annotations = annotations
    return new_dataset

podm.coco_encoder

新建coco_encoder.py文件,并添加以下代码:


import json
from typing import Union, TextIO, Dict, List

from podm.coco import PCOCOImage, PCOCOLicense, PCOCOInfo, \
    PCOCOCategory, PCOCOBoundingBox, \
    PCOCOSegments, PCOCOObjectDetectionDataset

PCOCO_OBJ = Union[
    PCOCOImage, PCOCOLicense, PCOCOInfo,
    PCOCOCategory,
    PCOCOObjectDetectionDataset,
    List[PCOCOBoundingBox],
]


class PCOCOJSONEncoder(json.JSONEncoder):
    """
    Extensible BioC JSON encoder for BioC data structures.
    """

    def default(self, o):
        # print('xxxxxxxxxxxxxxxxxxxx')
        # print(type(o))
        # print(isinstance(o, PCOCOObjectDetectionDataset))
        # print(repr(o.__class__), repr(PCOCOObjectDetectionResult))
        if isinstance(o, PCOCOImage):
            return {
                "width": o.width,
                "height": o.height,
                "flickr_url": o.flickr_url,
                "coco_url": o.coco_url,
                "file_name": o.file_name,
                "date_captured": o.date_captured,
                "license": o.license,
                "id": o.id,
            }
        if isinstance(o, PCOCOLicense):
            return {
                "id": o.id,
                "name": o.name,
                "url": o.url,
            }
        if isinstance(o, PCOCOInfo):
            return {
                "year": o.year,
                "version": o.version,
                "description": o.description,
                "contributor": o.contributor,
                "url": o.url,
                "date_created": o.date_created,
            }
        if isinstance(o, PCOCOCategory):
            return {
                "id": o.id,
                "name": o.name,
                "supercategory": o.supercategory,
            }
        if isinstance(o, PCOCOBoundingBox):
            return {
                "id": o.id,
                "image_id": o.image_id,
                "category_id": o.category_id,
                "bbox": [o.xtl, o.ytl, o.width, o.height],
                "score": o.score,
                "contributor": o.contributor,
                "attributes": json.dumps(o.attributes)
            }
        if isinstance(o, PCOCOSegments):
            bb = o.bbox
            return {
                "id": o.id,
                "image_id": o.image_id,
                "category_id": o.category_id,
                "segmentation": o.segmentation,
                "bbox": [bb.xtl, bb.ytl, bb.width, bb.height],
                "area": bb.area,
                "iscrowd": o.iscrowd,
                "score": o.score,
                "contributor": o.contributor,
                "attributes": json.dumps(o.attributes)
            }
        if isinstance(o, PCOCOObjectDetectionDataset):
            return {
                "info": self.default(o.info),
                'images': [self.default(img) for img in o.images],
                "licenses": [self.default(l) for l in o.licenses],
                'annotations': [self.default(ann) for ann in o.annotations],
                'categories': [self.default(cat) for cat in o.categories],
            }
        # Let the base class default method raise the TypeError
        return json.JSONEncoder.default(self, o)


def toJSON(o) -> Dict:
    """
    Convert a pcoco obj to a Python `dict`
    """
    return PCOCOJSONEncoder().default(o)


def dumps(obj: PCOCO_OBJ, **kwargs) -> str:
    """
    Serialize a BioC ``obj`` to a JSON formatted ``str``. kwargs are passed to json.
    """
    return json.dumps(obj, cls=PCOCOJSONEncoder, indent=2, **kwargs)


def dump(obj: PCOCO_OBJ, fp: TextIO, **kwargs):
    """
    Serialize ``obj`` as a JSON formatted stream to ``fp``
    (a ``.write()``-supporting file-like object). kwargs are passed to json.
    """
    return json.dump(obj, fp, cls=PCOCOJSONEncoder, indent=2, **kwargs)
    ```
    
    ## podm.coco
    新建`coco.py`文件,并添加:
    ```python
    import copy
from abc import ABC
from typing import List, Tuple, Set, Collection
from datetime import date, datetime
from shapely.geometry import Polygon, Point
from podm import box


class PCOCOInfo:
    def __init__(self):
        self.year = date.today().year  # type:int
        self.version = ''  # type: str
        self.description = ''  # type: str
        self.contributor = ''  # type: str
        self.url = ''  # type: str
        self.date_created = datetime.now().strftime('%m/%d/%Y')  # type:str


class PCOCOAnnotation(ABC):
    def __init__(self):
        self.id = None  # type:int or None
        self.image_id = None  # type:int or None
        self.score = None  # type:float or None
        self.contributor = ''  # type: str
        self.attributes = {}  # type: dict


class PCOCOImage:
    def __init__(self):
        self.id = None  # type:int or None
        self.width = 0  # type:int
        self.height = 0  # type:int
        self.file_name = ''  # type:str
        self.license = None  # type:int or None
        self.flickr_url = ''  # type:str
        self.coco_url = ''  # type:str
        self.date_captured = datetime.now().strftime('%m/%d/%Y')  # type:str


class PCOCOLicense:
    def __init__(self):
        self.id = None  # type:int or None
        self.name = ''  # type:str
        self.url = ''  # type:str


class PCOCOCategory:
    def __init__(self):
        self.id = None  # type:int or None
        self.name = ''  # type:str
        self.supercategory = ''  # type:str


class PCOCODataset(ABC):
    def __init__(self):
        self.info = PCOCOInfo()  # type: PCOCOInfo or None
        self.images = []  # type: List[PCOCOImage]
        self.licenses = []  # type: List[PCOCOLicense]

    def add_license(self, license: PCOCOLicense):
        for lic in self.licenses:
            if lic.id == license.id or lic.name == license.name:
                raise KeyError('%s: License exists' % lic.id)
        self.licenses.append(license)

    def add_image(self, image: PCOCOImage):
        for img in self.images:
            if img.id == image.id or img.file_name == image.file_name:
                raise KeyError('%s: Image exists' % img.id)
        self.images.append(image)

    def get_image(self, id: int = None, file_name: str = None, default=None) -> PCOCOImage:
        if id is None and file_name is None:
            raise KeyError('%s %s: Cannot set both to None' % (id, file_name))
        if id is not None and file_name is not None:
            raise KeyError('%s %s: Cannot set both' % (id, file_name))

        imgs = self.images
        if id is not None:
            imgs = [img for img in imgs if img.id == id]
            if len(imgs) == 0:
                return default
            elif len(imgs) == 1:
                return next(iter(imgs))
            else:
                raise KeyError('%s: more than one image with the same id' % id)

        if file_name is not None:
            imgs = [img for img in imgs if img.file_name == file_name]
            if len(imgs) == 0:
                return default
            elif len(imgs) == 1:
                return next(iter(imgs))
            else:
                raise KeyError('%s: more than one image with the same name' % file_name)

        raise Exception('Should not be here')

    def get_images(self, ids: Collection[int] = None) -> List[PCOCOImage]:
        """
        Load anns with the specified ids.
        :param ids: integer ids specifying img
        :return: imgs: loaded img objects
        """
        return [img for img in self.images if img.id in ids]


##############################################################################
# object detection
##############################################################################


class PCOCOBoundingBox(PCOCOAnnotation, box.Box):
    def __init__(self):
        super(PCOCOBoundingBox, self).__init__()
        self.category_id = None  # type:int or None


class PCOCOSegments(PCOCOAnnotation):
    def __init__(self):
        super(PCOCOSegments, self).__init__()
        self.category_id = None  # type:int or None
        self.segmentation = []  # type: List[List[float]]
        self.iscrowd = False  # type:bool

    def add_box(self, box: box.Box):
        self.add_segmentation(box.segment)

    def add_segmentation(self, segmentation: List[float]):
        self.segmentation.append(segmentation)

    def __contains__(self, item):
        if not type(item) == list and not type(item) == tuple:
            raise TypeError('Has to be a list or a tuple: %s' % type(item))
        if len(item) == 2:
            point = Point(item[0], item[1])
            for p in self.polygons:
                if p.contains(point):
                    return True
            return False
        else:
            raise ValueError('Only support a point')

    @property
    def polygons(self) -> List[Polygon]:
        return [Polygon([(seg[i], seg[i+1]) for i in range(0, len(seg), 2)]) for seg in self.segmentation]

    @property
    def bbox(self) -> 'box.Box' or None:
        if len(self.segmentation) == 0:
            return None
        else:
            b = self.box_polygon(self.segmentation[0])
            for polygon in self.segmentation[1:]:
                b = box.union(b, self.box_polygon(polygon))
            return b

    @classmethod
    def box_polygon(cls, polygon: List[float]) -> 'box.Box':
        xtl = min(polygon[i] for i in range(0, len(polygon), 2))
        ytl = min(polygon[i] for i in range(1, len(polygon), 2))
        xbr = max(polygon[i] for i in range(0, len(polygon), 2))
        ybr = max(polygon[i] for i in range(1, len(polygon), 2))
        return box.Box.of_box(xtl, ytl, xbr, ybr)


class PCOCOImageCaptioning(PCOCOAnnotation):
    def __init__(self):
        super(PCOCOImageCaptioning, self).__init__()
        self.caption = None  # type:str or None


class PCOCOObjectDetectionDataset(PCOCODataset):
    def __init__(self):
        super(PCOCOObjectDetectionDataset, self).__init__()
        self.annotations = []  # type: List[PCOCOBoundingBox or PCOCOSegments]
        self.categories = []  # type: List[PCOCOCategory]

    def add_annotation(self, annotation: 'PCOCOBoundingBox' or 'PCOCOSegments'):
        for ann in self.annotations:
            if ann.id == annotation.id:
                raise KeyError('%s: Annotation exists' % ann.id)
        self.annotations.append(annotation)

    def add_category(self, category: PCOCOCategory):
        for cat in self.categories:
            if cat.id == category.id or cat.name == category.name:
                raise KeyError('%s: Category exists' % cat.id)
        self.categories.append(category)

    def get_max_category_id(self):
        return max(cat.id for cat in self.categories)

    def get_category(self, id: int = None, name: str = None, default=None) -> PCOCOCategory:
        if id is None and name is None:
            raise KeyError('%s %s: Cannot set both to None' % (id, name))
        if id is not None and name is not None:
            raise KeyError('%s %s: Cannot set both' % (id, name))

        cats = self.categories
        if id is not None:
            cats = [cat for cat in cats if cat.id == id]
            if len(cats) == 0:
                return default
            elif len(cats) == 1:
                return next(iter(cats))
            else:
                raise KeyError('%s: more than one category with the same id' % id)

        if name is not None:
            cats = [cat for cat in cats if cat.name == name]
            if len(cats) == 0:
                return default
            elif len(cats) == 1:
                return next(iter(cats))
            else:
                raise KeyError('%s: more than one category with the same name' % name)

        raise Exception('Should not be here')

    def get_annotation(self, id: int, default=None) -> PCOCOAnnotation:
        anns = [ann for ann in self.annotations if ann.id == id]
        if len(anns) == 0:
            return default
        elif len(anns) == 1:
            return next(iter(anns))
        else:
            raise KeyError('%s: more than one annotation' % id)

    def get_new_dataset(self, annotations: Collection[PCOCOBoundingBox or PCOCOSegments]):
        new_dataset = PCOCOObjectDetectionDataset()
        new_dataset.info = copy.deepcopy(self.info)
        new_dataset.licenses = copy.deepcopy(self.licenses)
        new_dataset.images = copy.deepcopy(self.images)
        new_dataset.categories = copy.deepcopy(self.categories)
        for ann in annotations:
            new_dataset.add_annotation(ann)
        return new_dataset

    def get_category_ids(self, category_names: Collection[str] = None,
                         supercategory_names: Collection[str] = None) -> Collection[int]:
        """
        filtering parameters. default skips that filter.
        :param category_names: get cats for given cat names
        :param supercategory_names: get cats for given supercategory names
        :return: integer array of cat ids
        """
        itr = iter(self.categories)
        if category_names is not None:
            itr = filter(lambda x: x.name in category_names, itr)
        if supercategory_names is not None:
            itr = filter(lambda x: x.supercategory in supercategory_names, itr)
        return [cat.id for cat in itr]

    def get_annotation_ids(self, image_ids: Collection[int] = None,
                           category_ids: Collection[int] = None,
                           area_range: Tuple[float, float] = None) -> Collection[int]:
        """
        Get ann ids that satisfy given filter conditions. default skips that filter
        :param image_ids: get anns for given imgs
        :param category_ids: get anns for given cats
        :param area_range: get anns for given area range (e.g. [0 inf])
        :return: integer array of ann ids
        """
        # image_ids = convert_array_argument(image_ids)
        # category_ids = convert_array_argument(category_ids)
        # area_range = convert_array_argument(area_range)

        itr = iter(self.annotations)
        if image_ids is not None:
            itr = filter(lambda x: x.image_id in image_ids, itr)
        if category_ids is not None:
            itr = filter(lambda x: x.category_id in category_ids, itr)
        if area_range is not None:
            itr = filter(lambda x: area_range[0] <= x.area <= area_range[1], itr)
        return [ann.id for ann in itr]

    def get_image_ids(self, category_ids: Collection[int] = None) -> Collection[int]:
        """
        Get img ids that satisfy given filter conditions.
        :param category_ids: get imgs with all given cats
        :return: ids: integer array of img ids
        """
        ids = set(img.id for img in self.images)
        for i, cat_id in enumerate(category_ids):
            if i == 0 and len(ids) == 0:
                ids = set(ann.image_id for ann in self.annotations if ann.category_id == cat_id)
            else:
                ids &= set(ann.image_id for ann in self.annotations if ann.category_id == cat_id)
        return list(ids)

    def get_annotations(self, ids: Collection[int] = None) -> Collection[PCOCOAnnotation]:
        """
        Load anns with the specified ids.
        :param ids: integer ids specifying anns
        :return: anns: loaded ann objects
        """
        return [ann for ann in self.annotations if ann.id in ids]

    def get_categories(self, ids: Collection[int] = None) -> Collection[PCOCOCategory]:
        """
        Load cats with the specified ids.
        :param ids: integer ids specifying cats
        :return: cats: loaded cat objects
        """
        return [cat for cat in self.categories if cat.id in ids]

podm.coco2labelme

新建coco2labelme.py文件,并添加代码:

from podm.coco import PCOCOObjectDetectionDataset, PCOCOBoundingBox, PCOCOSegments


def coco2labelme(cocodataset: PCOCOObjectDetectionDataset):
    objs = []
    for img in cocodataset.images:
        obj = {
            "version": "5.0.1",
            "flags": {},
            "imagePath": img.file_name,
            "imageData": None,
            "imageHeight": img.height,
            "imageWidth": img.width,
            "shapes": []
        }
        for annid in cocodataset.get_annotation_ids(image_ids=[img.id]):
            ann = cocodataset.get_annotation(annid)
            if isinstance(ann, PCOCOBoundingBox):
                shape = {
                    "label": ann.attributes['ID'],
                    "points": [[ann.xtl, ann.ytl], [ann.xbr, ann.ybr]],
                    "group_id": None,
                    "shape_type": "rectangle",
                    "flags": {}
                }
            elif isinstance(ann, PCOCOSegments):
                shape = {
                    "label": ann.attributes['ID'],
                    "points": [[ann.segmentation[0][i], ann.segmentation[0][i+1]]
                               for i in range(0, len(ann.segmentation[0]), 2)],
                    "group_id": None,
                    "shape_type": "polygon",
                    "flags": {}
                }
            else:
                raise TypeError
            obj['shapes'].append(shape)

        objs.append(obj)

    return objs

podm.pascal2coco

新建pascal2coco.py文件,并添加以下代码:

"""
Convert from a PASCAL VOC zip file to a COCO file.

Usage:
    pascal2coco gold --gold=<file> --output-gold=<file>
    pascal2coco pred --gold=<file> --pred=<file> --output-gold=<file> --output-pred=<file>

Options:
    --gold=<file>           PASCAL VOC groundtruths zip file
    --pred=<file>           PASCAL VOC predictions zip file
    --output-gold=<file>    Groundtruths JSON file
    --output-pred=<file>    Predictions JSON file
"""
import json
import zipfile
import io
import warnings

import docopt
import tqdm
import pandas as pd
from podm import coco_encoder
from podm.box import BBFormat, Box
from podm.coco import PCOCOObjectDetectionDataset, PCOCOImage, PCOCOCategory, PCOCOBoundingBox


def convert_pascal_to_df(src):
    rows = []
    with zipfile.ZipFile(src, 'r') as myzip:
        namelist = myzip.namelist()
        for name in tqdm.tqdm(namelist):
            if not name.endswith('.txt'):
                continue
            with myzip.open(name, 'r') as fp:
                name = name[name.find('/') + 1:]
                items_file = io.TextIOWrapper(fp)
                for line in items_file:
                    toks = line.strip().split(' ')
                    if len(toks) == 5:
                        row = {
                            'name': name,
                            'label': toks[0],
                            'xtl': int(toks[1]),
                            'ytl': int(toks[2]),
                            'xbr': int(toks[3]),
                            'ybr': int(toks[4])
                        }
                    elif len(toks) == 6:
                        row = {
                            'name': name,
                            'label': toks[0],
                            'score': float(toks[1]),
                            'xtl': int(toks[2]),
                            'ytl': int(toks[3]),
                            'xbr': int(toks[4]),
                            'ybr': int(toks[5])
                        }
                    else:
                        raise ValueError
                    rows.append(row)
    return pd.DataFrame(rows)


class PascalVoc2COCO:
    def __init__(self, format: BBFormat = BBFormat.X1Y1X2Y2):
        self.format = format

    def convert_gold(self, src) -> PCOCOObjectDetectionDataset:
        df = convert_pascal_to_df(src)

        dataset = PCOCOObjectDetectionDataset()
        # add image
        for i, name in enumerate(df['name'].unique()):
            img = PCOCOImage()
            img.id = i
            img.file_name = name
            dataset.add_image(img)
        # add category
        for i, label in enumerate(df['label'].unique()):
            cat = PCOCOCategory()
            cat.id = i
            cat.name = label
            dataset.add_category(cat)
        # add annotation
        for i, row in tqdm.tqdm(df.iterrows(), total=len(df)):
            box = Box.of_box(row['xtl'], row['ytl'], row['xbr'], row['ybr'])
            if self.format == BBFormat.XYWH:
                box.xbr += box.xtl
                box.ybr += box.ytl
            ann = PCOCOBoundingBox()
            ann.image_id = dataset.get_image(file_name=row['name']).id
            ann.id = i
            ann.category_id = dataset.get_category(name=row['label']).id
            ann.set_box(box)
            dataset.add_annotation(ann)
        return dataset

    def convert_gold_file(self, src, dest):
        dataset = self.convert_gold(src)
        with open(dest, 'w') as fp:
            coco_encoder.dump(dataset, fp)

    def convert_gold_pred(self, src_gold, src_pred):
        gold_dataset = self.convert_gold(src_gold)

        df = convert_pascal_to_df(src_pred)
        # check cat
        subrows = []
        for i, row in tqdm.tqdm(df.iterrows(), total=len(df)):
            if gold_dataset.get_category(name=row['label']) is None:
                warnings.warn('%s: Category does not exist' % row['label'])
                continue
            if gold_dataset.get_image(file_name=row['name']) is None:
                warnings.warn('%s: Image does not exist' % row['name'])
                continue
            subrows.append(row)
        if len(subrows) < len(df):
            warnings.warn('Remove %s rows' % (len(df) - len(subrows)))

        annotations = []
        for i, row in tqdm.tqdm(enumerate(subrows), total=len(subrows)):
            box = Box.of_box(row['xtl'], row['ytl'], row['xbr'], row['ybr'])
            if self.format == BBFormat.XYWH:
                box.xbr += box.xtl
                box.ybr += box.ytl
            ann = PCOCOBoundingBox()
            ann.image_id = gold_dataset.get_image(file_name=row['name']).id
            ann.id = i
            ann.category_id = gold_dataset.get_category(name=row['label']).id
            ann.score = row['score']
            ann.set_box(box)
            annotations.append(ann)

        pred_dataset = gold_dataset.get_new_dataset(annotations)
        return gold_dataset, pred_dataset

    def convert_gold_pred_file(self, src_gold, src_pred, dest_gold, dest_pred):
        gold_dataset, pred_dataset = self.convert_gold_pred(src_gold, src_pred)
        with open(dest_gold, 'w') as fp:
            coco_encoder.dump(gold_dataset, fp)

        with open(dest_pred, 'w') as fp:
            json.dump(pred_dataset.annotations, fp, cls=coco_encoder.PCOCOJSONEncoder, indent=2)


def main():
    argv = docopt.docopt(__doc__)
    converter = PascalVoc2COCO(BBFormat.X1Y1X2Y2)
    if argv['gold']:
        converter.convert_gold_file(argv['--gold'], argv['--output-gold'])
    if argv['pred']:
        converter.convert_gold_pred_file(argv['--gold'], argv['--pred'], argv['--output-gold'], argv['--output-pred'])


if __name__ == '__main__':
    main()

最终文件夹内容

最终文件夹中内容如下:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/952075.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HDFS异构存储和存储策略

一、HDFS异构存储类型 1.1 冷、热、温、冻数据 通常&#xff0c;公司或者组织总是有相当多的历史数据占用昂贵的存储空间。典型的数据使用模式是新传入的数据被应用程序大量使用&#xff0c;从而该数据被标记为"热"数据。随着时间的推移&#xff0c;存储的数据每周…

sklearn-逻辑回归-制作评分卡

目录 数据集处理 分箱 分多少个箱子合适 分箱要达成什么样的效果 对一个特征进行分箱的步骤 分箱的实现 封装计算 WOE 值和 IV值函数 画IV曲线&#xff0c;判断最佳分箱数量 结论 pd.qcut 执行报错 功能函数封装 判断分箱个数 在银行借贷场景中&#xff0c;评分卡是…

中学综合素质笔记3

第一章职业理念 第三节 教师观 考情提示&#xff1a; 单选题材料分析题 学习要求&#xff1a; 理解、 识记、 运用 &#xff08;一&#xff09;教师职业角色的转变&#xff08;单选材料分析&#xff09; 从教师与学生的关系看——对学生 新课程要求教师应该是学生学习的引…

【Linux】设备驱动中的ioctl详解

在Linux设备驱动开发中&#xff0c;ioctl&#xff08;输入输出控制&#xff09;是一个非常重要的接口&#xff0c;用于用户空间应用程序与内核空间设备驱动之间进行通信。通过ioctl&#xff0c;应用程序可以发送命令给设备驱动&#xff0c;控制设备的行为或获取设备的状态信息。…

linux上使用cmake编译的方法

一、hello 例程仅基于一个cpp文件 C文件或工程进行编译时可以使用g指令&#xff08;需要对每一个程序和源文件分别使用g指令编译&#xff09;&#xff0c;当程序变大时&#xff0c;一个工程文件往往会包含很文件夹和源文件&#xff0c;这时我们需要的编译指令将越来越长&#…

(vue)el-table-column type=“selection“表格选框怎么根据条件添加禁选

(vue)el-table-column type"selection"表格选框怎么根据条件添加禁选 html <el-table:data"tableData"style"width: 100%"><el-table-columntype"selection"width"55":selectable"checkSelectable">…

linux nginx 安装后,发现SSL模块未安装,如何处理?

&#x1f468;‍⚕ 主页&#xff1a; gis分享者 &#x1f468;‍⚕ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕ 收录于专栏&#xff1a;运维工程师 文章目录 前言SSL模块安装 前言 nginx 安装后&#xff0c;发现SSL模块未安装&…

kubeneters-循序渐进Cilium网络(二)

文章目录 概要IP 地址配置接口配置解析结论 概要 接续前一章节&#xff0c;我们还是以这张图继续深入Cilium网络世界 IP 地址配置 通过检查 Kubernetes 集群的当前环境&#xff0c;可以获取实际的 IP 地址和配置信息。这些信息将被补充到之前的网络示意图中&#xff0c;以使…

虚拟机使用MQ及介绍

mq官网&#xff1a;https://www.rabbitmq.com 一、虚拟机与 MQ 的结合优势 隔离与安全&#xff1a;虚拟机为 MQ 的运行提供了一个独立的环境&#xff0c;与宿主机以及其他虚拟机相互隔离。这意味着即使 MQ 所在的虚拟机出现故障或遭受安全威胁&#xff0c;也不会直接影响到宿主…

比亚迪夏直插家用MPV腹地,“迪王”开启全面销冠新征程

文/王俣祺 导语&#xff1a;比亚迪前脚刚收获2024年的全面成功&#xff0c;后脚立刻就开始布局2025年的产品矩阵了。比亚迪夏的横空出世&#xff0c;看来家用MPV市场也要感受“迪王”的恐怖如斯了。 家用MPV市场的“意外之喜” 1月8日&#xff0c;比亚迪夏终于在万众瞩目之下…

c++入门之 命名空间与输入输出

1、命名空间 1.1使用命名空间的原因 先看一个例子&#xff1a; #include <iostream>int round 0;int main() {printf("%d", round);return 0; }请问&#xff0c;这个程序能跑起来吗&#xff1f; 答案是否定的 原因是&#xff0c;当我们想创建一个全局变量 …

php 使用simplexml_load_string转换xml数据格式失败

本文介绍如何使用php函数解析xml数据为数组。 <?php$a <xml><ToUserName><![CDATA[ww8b77afac71336111]]></ToUserName><FromUserName><![CDATA[sys]]></FromUserName><CreateTime>1736328669</CreateTime><Ms…

12 USART串口通讯

1 串口物理层 两个设备的“DB9接口”之间通过串口信号建立连接&#xff0c;串口信号线中使用“RS232标准”传输数据信号。由于RS232电平标准的信号不能直接被控制器直接识别&#xff0c;所以这些信号会经过“电平转换芯片”转换成控制器能识别的“TTL校准”的电平信号&#xff…

FreePBX 17 on ubuntu24 with Asterisk 20

版本配置&#xff1a; FreePBX 17&#xff08;最新&#xff09; Asterisk 20&#xff08;最新Asterisk 22&#xff0c;但是FreePBX 17最新只支持Asterisk 21&#xff0c;但是21非LTS版本&#xff0c;所以选择Asterisk 20&#xff09; PHP 8.2 Maria DB (v10.11) Node J…

搜广推面经五

饿了么推荐算法 一、介绍InfoNCE Loss、InfoNCE温度系数的作用 InfoNCE Loss&#xff08;Information Noise Contrastive Estimation Loss&#xff09;是一种常用于自监督学习和对比学习中的损失函数&#xff0c;特别是在信息论和无监督学习中有广泛应用。 它的核心思想是通过…

机器学习免费使用的数据集及网站链接

机器学习领域存在许多可以免费使用的数据集&#xff0c;这些数据集来自于学习、研究、比赛等目的。 一、综合性数据集平台 1.Kaggle 网址&#xff1a;Kaggle 数据集https://www.kaggle.com/datasets Kaggle是一个数据科学竞赛和社区平台&#xff0c;提供了大量的数据集供用…

浅尝Appium自动化框架

浅尝Appium自动化框架 Appium自动化框架介绍Appium原理Appium使用安装平台驱动实战 坑 Appium自动化框架介绍 Appium 是一个开源的自动化测试框架&#xff0c;最初设计用于移动应用的测试&#xff0c;但现在它也扩展了对桌面端应用的支持。Appium 使得自动化测试变得更加简单&…

ubuntu 20.04 安装docker--小白学习之路

更新包 sudo apt-get update # 安装需要的软件包以使apt能够通过HTTPS使用仓库 sudo apt-get install ca-certificates curl gnupg lsb-release 使用清华大学源 # 添加Docker官方的GPG密钥 curl -fsSL https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu/gpg | sudo…

MMDetection框架下的常见目标检测与分割模型综述与实践指南

目录 综述与实践指南 SSD (Single Shot MultiBox Detector) 基本配置和使用代码 RetinaNet 基本配置和使用代码 Faster R-CNN 基本配置和使用代码 Mask R-CNN 基本配置和使用代码 Cascade R-CNN 基本配置和使用代码 总结 综述与实践指南 MMDetection是一个基于Py…

语音机器人外呼的缺点

也许是因为经济形式变差&#xff0c;大部分都是消费降级的策略。企业也一样&#xff0c;开源不行就只能重点节流。以前10个人做的工作&#xff0c;希望能用2个语音机器人就能完成。确实语音机器人是可以大幅提升外呼效率的&#xff0c;节约成本也很明显&#xff0c;但是今天不说…