pysot 中的异步多进程切图

孪生网络算法对数据需求量较大,训练一般使用多个数据集。检测数据集普遍图大目标多,pysot 第一步准备数据,屏蔽了不同数据集的差异,也提升了数据加载效率。网络设定的模板大小为 127 × 127 127\times 127 127×127,搜索区域大约为 255 × 255 255\times 255 255×255。为给数据增强留有余地,数据切图大小为 511 × 511 511\times 511 511×511。下面以 COCO 数据集为例进行介绍。

par_crop.py

    since = time.time()
    main(int(sys.argv[1]), int(sys.argv[2]))
    time_elapsed = time.time() - since
    print('Total complete in {:.0f}m {:.0f}s'.format(
        time_elapsed // 60, time_elapsed % 60))

main

创建切图路径。

    dataDir = '.'
    crop_path = './crop{:d}'.format(instanc_size)
    if not isdir(crop_path): mkdir(crop_path)

对于训练集和验证集,根据标注文件实例化 pycocotools.coco.COCO

concurrent.futures.Executor 是一个抽象类,提供异步执行调用的方法。要通过它的子类调用,而不是直接调用。
concurrent.futures.Executor.submit 调度可调用对象fn,以fn(*args **kwargs)方式执行并返回代表可调用对象的执行的 Future 对像。
concurrent.futures.ProcessPoolExecutorExecutor 的子类,使用最多max_workers个进程的进程池异步执行调用。如果 max_workersNone或未给出,则默认为计算机上的处理器数。 如果max_workers低于或等于0,则会引发 ValueError。在 Windows 上,max_workers必须小于等于61.如果不是,则会引发 ValueError。如果max_workersNone,那么即使有更多的处理器可用,默认值也最多为61。mp_context可以是一个多进程上下文或是None。 用它来启动工作者。如果mp_contextNone或未给出,将使用默认的多进程上下文。
initializer是一个可选的 callable,在每个 worker 进程的开头调用; initargs是传递给初始化器的参数元组。如果初始化程序引发异常,则所有当前挂起的作业以及向池中提交更多作业的任何尝试都将引发 BrokenProcessPool

crop_img 从图上根据目标框
loadImgs 加载指定 ID 的图片。
loadAnns 加载指定 ID 的注释。
getAnnIds 获取满足给定过滤条件的标注 ID。默认跳过该过滤器。
printProgress 打印进程状态。

    for dataType in ['val2017', 'train2017']:
        set_crop_base_path = join(crop_path, dataType)
        set_img_base_path = join(dataDir, dataType)

        annFile = '{}/annotations/instances_{}.json'.format(dataDir,dataType)
        coco = COCO(annFile)
        n_imgs = len(coco.imgs)
        with futures.ProcessPoolExecutor(max_workers=num_threads) as executor:
            fs = [executor.submit(crop_img, coco.loadImgs(id)[0],
                                  coco.loadAnns(coco.getAnnIds(imgIds=id, iscrowd=None)),
                                  set_crop_base_path, set_img_base_path, instanc_size) for id in coco.imgs]
            for i, f in enumerate(futures.as_completed(fs)):
                # Write progress to error so that it can be seen
                printProgress(i, n_imgs, prefix=dataType, suffix='Done ', barLength=40)
    print('done')

crop_img

crop_img
crop_like_SiamFC

img['file_name']读取文件名。以该名称创建文件夹。
读取图像,根据每个目标框截取后保存。
crop_like_SiamFC 像 SiamFC 那样截取,即外扩截取后缩放到指定大小。

    frame_crop_base_path = join(set_crop_base_path, img['file_name'].split('/')[-1].split('.')[0])
    if not isdir(frame_crop_base_path): makedirs(frame_crop_base_path)

    im = cv2.imread('{}/{}'.format(set_img_base_path, img['file_name']))
    avg_chans = np.mean(im, axis=(0, 1))
    for trackid, ann in enumerate(anns):
        rect = ann['bbox']
        bbox = [rect[0], rect[1], rect[0] + rect[2], rect[1] + rect[3]]
        if rect[2] <= 0 or rect[3] <=0:
            continue
        z, x = crop_like_SiamFC(im, bbox, instanc_size=instanc_size, padding=avg_chans)
        cv2.imwrite(join(frame_crop_base_path, '{:06d}.{:02d}.z.jpg'.format(0, trackid)), z)
        cv2.imwrite(join(frame_crop_base_path, '{:06d}.{:02d}.x.jpg'.format(0, trackid)), x)

crop_like_SiamFC

crop_like_SiamFC
crop_hwc

[x1, y1, x2, y2]的框得到中心和大小。
pos_s_2_bbox 根据中心位置和大小解码出框。
crop_hwc 截取图像块并缩放为指定大小。

    target_pos = [(bbox[2]+bbox[0])/2., (bbox[3]+bbox[1])/2.]
    target_size = [bbox[2]-bbox[0], bbox[3]-bbox[1]]
    wc_z = target_size[1] + context_amount * sum(target_size)
    hc_z = target_size[0] + context_amount * sum(target_size)
    s_z = np.sqrt(wc_z * hc_z)
    scale_z = exemplar_size / s_z
    d_search = (instanc_size - exemplar_size) / 2
    pad = d_search / scale_z
    s_x = s_z + 2 * pad

    z = crop_hwc(image, pos_s_2_bbox(target_pos, s_z), exemplar_size, padding)
    x = crop_hwc(image, pos_s_2_bbox(target_pos, s_x), instanc_size, padding)
    return z, x

crop_hwc

ab分别为宽高的比例系数。
cd分别为宽高方向的平移量。

    a = (out_sz-1) / (bbox[2]-bbox[0])
    b = (out_sz-1) / (bbox[3]-bbox[1])
    c = -a * bbox[0]
    d = -b * bbox[1]
    mapping = np.array([[a, 0, c],
                        [0, b, d]]).astype(np.float)
    crop = cv2.warpAffine(image, mapping, (out_sz, out_sz), borderMode=cv2.BORDER_CONSTANT, borderValue=padding)
    return crop

printProgress

    """
    Call in a loop to create terminal progress bar
    @params:
        iteration   - Required  : current iteration (Int)
        total       - Required  : total iterations (Int)
        prefix      - Optional  : prefix string (Str)
        suffix      - Optional  : suffix string (Str)
        decimals    - Optional  : positive number of decimals in percent complete (Int)
        barLength   - Optional  : character length of bar (Int)
    """
    formatStr       = "{0:." + str(decimals) + "f}"
    percents        = formatStr.format(100 * (iteration / float(total)))
    filledLength    = int(round(barLength * iteration / float(total)))
    bar             = '' * filledLength + '-' * (barLength - filledLength)
    sys.stdout.write('\r%s |%s| %s%s %s' % (prefix, bar, percents, '%', suffix)),
    if iteration == total:
        sys.stdout.write('\x1b[2K\r')
    sys.stdout.flush()

参考资料:

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 15
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值