Beispiel #1
0
def main():
    parser = argparse.ArgumentParser(
        description='Convert bounding box file(s) from one format to the other',
        usage='%(prog)s inputformat inputpath outputformat outputpath [optional arguments]',
        epilog=f'Posible formats are: {list(bbb.formats.keys())}',
    )

    parser.add_argument('inputformat', metavar='inputformat', choices=bbb.formats.keys(), help='Input format')
    parser.add_argument('inputpath', help='Bounding box file, folder or file sequence')
    parser.add_argument('outputformat', metavar='outputformat', choices=bbb.formats.keys(), help='Ouput format')
    parser.add_argument('outputpath', help='Output file or folder')
    parser.add_argument('--stride', '-s', metavar='N', type=int, default=1, help='If a sequence expression is given as input, this stride is used')
    parser.add_argument('--offset', '-o', metavar='N', type=int, default=0, help='If a sequence expression is given as input, this offset is used')
    parser.add_argument('--kwargs', '-k', metavar='KW=V', help='Keyword arguments for the parser', nargs='*', action=StoreKwargs, default={})
    args = parser.parse_args()

    # Parse arguments
    indir = os.path.split(args.inputpath)[0]
    if not os.path.exists(indir):
        sys.exit(f'Input directory {indir} does not exist')

    if os.path.splitext(args.outputpath)[1] != '':
        outdir = os.path.split(args.outputpath)[0]
    else:
        outdir = args.outputpath

    if not os.path.exists(outdir):
        os.makedirs(outdir)

    # Convert
    bbox = bbb.parse(args.inputformat, args.inputpath, stride=args.stride, offset=args.offset, **args.kwargs)
    bbb.generate(args.outputformat, bbox, args.outputpath, **args.kwargs)
    print(f'Converted {len(bbox)} files')
Beispiel #2
0
def test(weight, device, save_det):
    log.debug('Creating network')
    net = ln.models.TinyYolo(len(CLASS_LABELS), weight, CONF_THRESH, NMS_THRESH)
    net.postprocess.append(ln.data.transform.TensorToBrambox(NETWORK_SIZE, CLASS_LABELS))
    net = net.to(device)
    net.eval()

    log.debug('Creating dataset')
    loader = torch.utils.data.DataLoader(
        ln.models.DarknetDataset(TESTFILE, augment=False, input_dimension=NETWORK_SIZE, class_label_map=CLASS_LABELS),
        batch_size = MINI_BATCH,
        shuffle = False,
        drop_last = False,
        num_workers = WORKERS,
        pin_memory = PIN_MEM,
        collate_fn = ln.data.list_collate,
    )

    log.debug('Running network')
    tot_loss = []
    coord_loss = []
    conf_loss = []
    cls_loss = []
    anno, det = {}, {}
    num_det = 0

    with torch.no_grad():
        for idx, (data, box) in enumerate(tqdm(loader, total=len(loader))):
            data = data.to(device)
            output, loss = net(data, box)

            tot_loss.append(net.loss.loss_tot.item()*len(box))
            coord_loss.append(net.loss.loss_coord.item()*len(box))
            conf_loss.append(net.loss.loss_conf.item()*len(box))
            if net.loss.loss_cls is not None:
                cls_loss.append(net.loss.loss_cls.item()*len(box))

            key_val = len(anno)
            anno.update({loader.dataset.keys[key_val+k]: v for k,v in enumerate(box)})
            det.update({loader.dataset.keys[key_val+k]: v for k,v in enumerate(output)})

    log.debug('Computing statistics')

    pr = bbb.pr(det, anno)
    m_ap = bbb.ap(*pr)*100
    tot = sum(tot_loss)/len(anno)
    coord = sum(coord_loss)/len(anno)
    conf = sum(conf_loss)/len(anno)
    if len(cls_loss) > 0:
        cls = sum(cls_loss)/len(anno)
        log.test(f'{net.seen//BATCH} mAP:{m_ap:.2f}% Loss:{tot:.5f} (Coord:{coord:.2f} Conf:{conf:.2f} Cls:{cls:.2f})')
    else:
        log.test(f'{net.seen//BATCH} mAP:{m_ap:.2f}% Loss:{tot:.5f} (Coord:{coord:.2f} Conf:{conf:.2f})')

    if save_det is not None:
        # Note: These detection boxes are the coordinates for the letterboxed images,
        #       you need ln.data.transform.ReverseLetterbox to have the right ones.
        #       Alternatively, you can save the letterboxed annotations, and use those for statistics later on!
        bbb.generate('det_pickle', det, Path(arguments.save_det).with_suffix('.pkl'))
Beispiel #3
0
def process(name, verbose=True):
    config_dict = {
        'train': ('training',   TRAINSET),
        'valid': ('validation', VALIDSET),
        'test':  ('testing',    TESTSET),
    }

    name = name.lower()
    assert name in config_dict
    description, DATASET = config_dict[name]

    if len(DATASET) == 0:
        return

    print('Getting {description} annotation filenames'.format(description=description))
    dataset = []
    for (year, img_set) in DATASET:
        filename = '{ROOT}/VOCdevkit/VOC{year}/ImageSets/Main/{img_set}.txt'.format(ROOT=ROOT, year=year, img_set=img_set)
        with open(filename, 'r') as f:
            ids = f.read().strip().split()
        dataset += [
            '{ROOT}/VOCdevkit/VOC{year}/Annotations/{xml_id}.xml'.format(ROOT=ROOT, year=year, xml_id=xml_id)
            for xml_id in ids
        ]

    if verbose:
        print('\t{len} xml files'.format(
            len=len(dataset),
        ))

    print('Parsing {description} annotation files'.format(description=description))
    dataset_annos = bbb.parse('anno_pascalvoc', dataset, identify)

    print('Generating {description} annotation file'.format(description=description))
    bbb.generate('anno_pickle', dataset_annos, '{ROOT}/{name}.pkl'.format(ROOT=ROOT, name=name))

    print()
            f'{ROOT}/VOC{year}/Annotations/{xml_id}.xml' for xml_id in ids
        ]

    if DEBUG:
        print(f'\t{len(train)} xml files')

    print('Parsing training annotation files')
    train_annos = bbb.parse('anno_pascalvoc', train, identify)
    # Remove difficult for training
    for k, annos in train_annos.items():
        for i in range(len(annos) - 1, -1, -1):
            if annos[i].difficult:
                del annos[i]

    print('Generating training annotation file')
    bbb.generate('anno_pickle', train_annos, f'{ROOT}/onedet_cache/train.pkl')

    print()

    print('Getting testing annotation filenames')
    test = []
    for (year, img_set) in TESTSET:
        with open(f'{ROOT}/VOC{year}/ImageSets/Main/{img_set}.txt', 'r') as f:
            ids = f.read().strip().split()
        test += [
            f'{ROOT}/VOC{year}/Annotations/{xml_id}.xml' for xml_id in ids
        ]

    if DEBUG:
        print(f'\t{len(test)} xml files')
            ids = f.read().strip().split()
        train += [f'{ROOT}/VOC{year}/Annotations/{xml_id}.xml' for xml_id in ids]

    if DEBUG:
        print(f'\t{len(train)} xml files')

    print('Parsing training annotation files')
    train_annos = bbb.parse('anno_pascalvoc', train, identify)
    # Remove difficult for training
    for k,annos in train_annos.items():
        for i in range(len(annos)-1, -1, -1):
            if annos[i].difficult:
                del annos[i]

    print('Generating training annotation file')
    bbb.generate('anno_pickle', train_annos, f'{ROOT}/onedet_cache/train.pkl')

    print()

    print('Getting testing annotation filenames')
    test = []
    for (year, img_set) in TESTSET:
        with open(f'{ROOT}/VOC{year}/ImageSets/Main/{img_set}.txt', 'r') as f:
            ids = f.read().strip().split()
        test += [f'{ROOT}/VOC{year}/Annotations/{xml_id}.xml' for xml_id in ids]

    if DEBUG:
        print(f'\t{len(test)} xml files')

    print('Parsing testing annotation files')
    test_annos = bbb.parse('anno_pascalvoc', test, identify)
Beispiel #6
0
                ROOT=ROOT, year=year, xml_id=xml_id) for xml_id in ids
        ]

    if DEBUG:
        print('\t{length} xml files'.format(length=len(train)))

    print('Parsing training annotation files')
    train_annos = bbb.parse('anno_pascalvoc', train, identify)
    # Remove difficult for training
    for k, annos in train_annos.items():
        for i in range(len(annos) - 1, -1, -1):
            if annos[i].difficult:
                del annos[i]

    print('Generating training annotation file')
    bbb.generate('anno_pickle', train_annos,
                 '{ROOT}/train.pkl'.format(ROOT=ROOT))

    print()

    print('Getting testing annotation filenames')
    test = []
    for (year, img_set) in TESTSET:
        with open(
                '{ROOT}/VOCdevkit/VOC{year}/ImageSets/Main/{img_set}.txt'.
                format(ROOT=ROOT, year=year, img_set=img_set), 'r') as f:
            ids = f.read().strip().split()
        test += [
            '{ROOT}/VOCdevkit/VOC{year}/Annotations/{xml_id}.xml'.format(
                ROOT=ROOT, year=year, xml_id=xml_id) for xml_id in ids
        ]
Beispiel #7
0
def test(arguments):
    log.debug('Creating network')
    net = ln.models.Yolo(CLASSES, arguments.weight, CONF_THRESH, NMS_THRESH)
    net.postprocess.append(
        ln.data.transform.TensorToBrambox(NETWORK_SIZE, LABELS))

    net.eval()
    if arguments.cuda:
        net.cuda(non_blocking=PIN_MEM)

    log.debug('Creating dataset')
    loader = torch.utils.data.DataLoader(
        CustomDataset(TESTFILE, net),
        batch_size=MINI_BATCH,
        shuffle=False,
        drop_last=False,
        num_workers=WORKERS if arguments.cuda else 0,
        pin_memory=PIN_MEM if arguments.cuda else False,
        collate_fn=ln.data.list_collate,
    )

    if arguments.visdom:
        log.debug('Creating visdom visualisation wrappers')
        vis = visdom.Visdom(port=VISDOM_PORT)
        plot_pr = ln.engine.VisdomLinePlotter(vis,
                                              'pr',
                                              opts=dict(
                                                  xlabel='Recall',
                                                  ylabel='Precision',
                                                  title='Precision Recall',
                                                  xtickmin=0,
                                                  xtickmax=1,
                                                  ytickmin=0,
                                                  ytickmax=1,
                                                  showlegend=True))

    if arguments.hyperdash:
        log.debug('Creating hyperdash visualisation wrappers')
        hd = hyperdash.Experiment('YOLOv2 Test')
        hyperdash_plot_pr = ln.engine.HyperdashLinePlotter(hd)

    log.debug('Running network')
    tot_loss = []
    coord_loss = []
    conf_loss = []
    cls_loss = []
    anno, det = {}, {}

    for idx, (data, box) in enumerate(tqdm(loader, total=len(loader))):
        if arguments.cuda:
            data = data.cuda(non_blocking=PIN_MEM)
        data = torch.autograd.Variable(data).no_grad()

        output, loss = net(data, box)

        if torch.__version__.startswith('0.3'):
            data = torch.autograd.Variable(data).no_grad()
            output, loss = net(data, box)
        else:
            with torch.no_grad():
                output, loss = net(data, box)

        if torch.__version__.startswith('0.3'):
            tot_loss.append(net.loss.loss_tot.data[0] * len(box))
            coord_loss.append(net.loss.loss_coord.data[0] * len(box))
            conf_loss.append(net.loss.loss_conf.data[0] * len(box))
            if net.loss.loss_cls is not None:
                cls_loss.append(net.loss.loss_cls.data[0] * len(box))
        else:
            tot_loss.append(net.loss.loss_tot.item() * len(box))
            coord_loss.append(net.loss.loss_coord.item() * len(box))
            conf_loss.append(net.loss.loss_conf.item() * len(box))
            if net.loss.loss_cls is not None:
                cls_loss.append(net.loss.loss_cls.item() * len(box))

        key_val = len(anno)
        anno.update(
            {loader.dataset.keys[key_val + k]: v
             for k, v in enumerate(box)})
        det.update({
            loader.dataset.keys[key_val + k]: v
            for k, v in enumerate(output)
        })

    pr_dict, ap_dict, m_ap, all_key = bbb.pr_ap_dicts(det, anno, LABELS,
                                                      IGNORE)
    pr = pr_dict[all_key]

    log.info('Computed statistics')
    for label in sorted(ap_dict.keys()):
        log.info('\tLabel %r: m_ap = %0.04f' % (
            label,
            ap_dict[label],
        ))

    tot = round(sum(tot_loss) / len(anno), 5)
    coord = round(sum(coord_loss) / len(anno), 2)
    conf = round(sum(conf_loss) / len(anno), 2)
    if len(cls_loss) > 0:
        cls = round(sum(cls_loss) / len(anno), 2)
        log.test(
            '\n{seen} mAP:{m_ap}% Loss:{tot} (Coord:{coord} Conf:{conf} Cls:{cls})'
            .format(seen=net.seen // BATCH,
                    m_ap=m_ap,
                    tot=tot,
                    coord=coord,
                    conf=conf,
                    cls=cls))
    else:
        log.test('\n{seen} mAP:{m_ap}% Loss:{tot} (Coord:{coord} Conf:{conf})'.
                 format(seen=net.seen // BATCH,
                        m_ap=m_ap,
                        tot=tot,
                        coord=coord,
                        conf=conf))

    name = 'mAP: {m_ap}%'.format(m_ap=m_ap)
    if arguments.visdom:
        plot_pr(np.array(pr[0]), np.array(pr[1]), name=name)

    if arguments.hyperdash:
        now = time.time()
        re_seen = None
        for index, (re_, pr_) in enumerate(sorted(zip(pr[1], pr[0]))):
            re_ = round(re_, 2)
            if re_ != re_seen:
                re_seen = re_
                re_ = int(re_ * 100.0)
                hyperdash_plot_pr(name, pr_, now + re_, log=False)

    if arguments.save_det is not None:
        # Note: These detection boxes are the coordinates for the letterboxed images,
        #       you need ln.data.ReverseLetterbox to have the right ones.
        #       Alternatively, you can save the letterboxed annotations, and use those for statistics later on!
        bbb.generate('det_pickle', det,
                     Path(arguments.save_det).with_suffix('.pkl'))
        #bbb.generate('anno_pickle', det, Path('anno-letterboxed_'+arguments.save_det).with_suffix('.pkl'))

    if arguments.hyperdash:
        hyperdash_plot_pr.close()
Beispiel #8
0
def get_label_for_single_file(year, dataset):

    data = json.load(open(f"{ROOT}/annotations/instances_{dataset}{year}.json"))
    cate = {x['id']: x['name'] for x in data['categories']}

    # parse one json file once, may need to conbine them later?

    # hold all images
    images = {}
    for image in data["images"]:
        images[image["id"]] = {
            # add more attributes if needed
            "file_name" : image["file_name"],
            "image_size" : {
                "height": image["height"],
                "width": image["width"],
            },
            "img_id" : image["id"],
            "obj" : []
        }

    for anno in data["annotations"]:
        # attach annotations to corresponding images
        images[anno["image_id"]]["obj"].append({
            "class_label": cate[anno["category_id"]],
            "bbox": anno["bbox"]
        })

    # delete images with no annotations
    del_keys = []
    for image in images:
        if images[image]["obj"] == []:
            del_keys.append(image)
    for key in del_keys:
        del images[key]

    val_annos = {}
    for image in images:
        val_annos[f'{ROOT}/{dataset}{year}/{images[image]["file_name"]}'] = []
        for obj in images[image]["obj"]:
            tmp_obj = bbb.annotations.PascalVocAnnotation()
            tmp_obj.class_label = obj["class_label"]
            tmp_obj.x_top_left = int(max(obj["bbox"][0], 0))
            tmp_obj.y_top_left = int(max(obj["bbox"][1], 0))
            # maybe out of boundry! need to check?
            tmp_obj.width = int(obj["bbox"][2])
            tmp_obj.height = int(obj["bbox"][3])
            val_annos[f'{ROOT}/{dataset}{year}/{images[image]["file_name"]}'].append(tmp_obj)
    # this one contains categories not in VOC
    bbb.generate('anno_pickle', val_annos, f'{DST}/onedet_cache/MSCOCO{dataset}{year}.pkl')

    val_annos_fix_label = {}
    for image in val_annos:
        val_annos_fix_label[image] = []
        for anno in val_annos[image]:
            # map some coco label to voc labels
            if anno.class_label in change_list.keys():
                anno.class_label = change_list[anno.class_label]
            if anno.class_label in labels:
                val_annos_fix_label[image].append(anno)
    del_keys = []
    for image in val_annos_fix_label:
        if val_annos_fix_label[image] == []:
            del_keys.append(image)
    for key in del_keys:
        del val_annos_fix_label[key]
    print(len(val_annos_fix_label))
    # this one can run like pkl generated from VOC
    #val_annos_fix_label = dict(itertools.islice(val_annos_fix_label.items(), 512))
    bbb.generate('anno_pickle', val_annos_fix_label, f'{DST}/onedet_cache/MSCOCO{dataset}{year}_fix_label.pkl')

    # generate test file for each label
    if testing:
        main = {}
        for label in labels:
            main[label] = []
        for img in val_annos_fix_label:
            has_obj = {}
            #print(img)
            for obj in val_annos_fix_label[img]:
                #print(obj)
                has_obj[obj.class_label] = 1
            #print(has_obj)
            for label in labels:
                if label in has_obj:
                    main[label].append([img.split('/')[-1].split('.')[0], 1])
                else:
                    main[label].append([img.split('/')[-1].split('.')[0], -1])
        for label in labels:
            with open(f'{ROOT}/VOCtmp/ImageSets/Main/{label}_test.txt', 'w') as f:
                for case in main[label]:
                    f.write(case[0] + ' ' + str(case[1]) + '\n')
Beispiel #9
0
def main():
    parser = argparse.ArgumentParser(
        description='Convert bounding box file(s) from one format to the other',
        usage=
        '%(prog)s inputformat inputpath outputformat outputpath [optional arguments]',
        epilog=f'Posible formats are: {list(bbb.formats.keys())}',
    )

    parser.add_argument(
        'inputformat',
        metavar='inputformat',
        choices=bbb.formats.keys(),
        help='Input format',
    )
    parser.add_argument('inputpath',
                        help='Bounding box file, folder or file sequence')
    parser.add_argument(
        'outputformat',
        metavar='outputformat',
        choices=bbb.formats.keys(),
        help='Ouput format',
    )
    parser.add_argument('outputpath', help='Output file or folder')
    parser.add_argument(
        '--stride',
        '-s',
        metavar='N',
        type=int,
        default=1,
        help='If a sequence expression is given as input, this stride is used',
    )
    parser.add_argument(
        '--offset',
        '-o',
        metavar='N',
        type=int,
        default=0,
        help='If a sequence expression is given as input, this offset is used',
    )
    parser.add_argument(
        '--kwargs',
        '-k',
        metavar='KW=V',
        help='Keyword arguments for the parser',
        nargs='*',
        action=StoreKwargs,
        default={},
    )
    args = parser.parse_args()

    # Parse arguments
    if bbb.formats[args.outputformat].parser_type == bbb.ParserType.MULTI_FILE:
        out = Path(args.outputpath)
        if not out.is_dir() and len(out.suffixes) > 0:
            log.error(
                f'Output format [{args.outputformat}] requires a path to a directory'
            )
            sys.exit(1)
        if not out.exists():
            log.info(
                f'[{args.outputformat}] folder does not exist, creating...')
            os.makedirs(out)

    # Convert
    bbox = bbb.parse(
        args.inputformat,
        args.inputpath,
        stride=args.stride,
        offset=args.offset,
        **args.kwargs,
    )
    bbb.generate(args.outputformat, bbox, args.outputpath, **args.kwargs)
    print(f'Converted {len(bbox)} files')