예제 #1
0
def crop_face(args):
    assert osp.exists(args.data_dir), "The input dir not exist"
    root_folder_name = args.data_dir.split('/')[-1]
    dst_folder = args.data_dir.replace(root_folder_name, root_folder_name + '_OPPOFaces')
    lz.mkdir_p(dst_folder, delete=False)
    mtcnn = MTCNN()
    ind = 0
    all_img = []
    for imgfn in itertools.chain(
            glob.glob(args.data_dir + '/**/*.jpg', recursive=True),
            glob.glob(args.data_dir + '/**/*.JPEG', recursive=True)):
        ind += 1
        if ind % 10 == 0:
            print(f'proc {ind}, {imgfn}')
        dstimgfn = imgfn.replace(root_folder_name, root_folder_name + '_OPPOFaces')
        dst_folder = osp.dirname(dstimgfn)
        lz.mkdir_p(dst_folder, delete=False)
        img = cvb.read_img(imgfn)  # bgr
        img1 = Image.fromarray(img)
        face = mtcnn.align_best(img1, limit=None, min_face_size=16, imgfn=imgfn)
        face = np.asarray(face)  # bgr
        # face = cvb.bgr2rgb(face)  # rgb
        cvb.write_img(face, dstimgfn)
        all_img.append( dstimgfn)
    logging.info(f'finish crop all {ind} imgs')
    lz.msgpack_dump(all_img, dst_folder + '/' + 'all_imgs.pk')
    del mtcnn
    torch.cuda.empty_cache()
예제 #2
0
def extract_ms1m_info():
    self = edict()
    path_ms1m = lz.share_path2 + 'faces_ms1m_112x112/'
    path_imgrec = lz.share_path2 + 'faces_ms1m_112x112/train.rec'
    path_imgidx = path_imgrec[0:-4] + ".idx"
    self.imgrec = recordio.MXIndexedRecordIO(path_imgidx, path_imgrec, 'r')
    s = self.imgrec.read_idx(0)
    header, _ = recordio.unpack(s)
    self.header0 = (int(header.label[0]), int(header.label[1]))
    # assert(header.flag==1)
    self.imgidx = list(range(1, int(header.label[0])))
    id2range = dict()
    self.seq_identity = list(range(int(header.label[0]), int(header.label[1])))
    for identity in self.seq_identity:
        s = self.imgrec.read_idx(identity)
        header, _ = recordio.unpack(s)
        a, b = int(header.label[0]), int(header.label[1])
        id2range[(identity - 3804847)] = (a, b)
        count = b - a
    self.seq = self.imgidx
    self.seq_identity = [int(t) - 3804847 for t in self.seq_identity]
    lz.msgpack_dump([self.imgidx, self.seq_identity, id2range],
                    path_ms1m + '/info.pk')
예제 #3
0
        img = img.copy()[..., ::-1].reshape(112, 112, 3)
        img = Image.fromarray(img)
        mirror = transforms.functional.hflip(img)
        with torch.no_grad():
            fea = learner.model(conf.test_transform(img).cuda().unsqueeze(0))
            fea_mirror = learner.model(conf.test_transform(mirror).cuda().unsqueeze(0))
            fea = l2_norm(fea + fea_mirror).cpu().numpy().reshape(512)

        return fea


    def extract_fea(res):
        res3 = {}
        for path, img in res.items():
            res3[path] = extract_fea_from_img(img)
        return res3


    # res, res2 = lz.msgpack_load(lz.work_path + '/yy.yy2.pk')
    # res3 = extract_fea(res)
    # res4 = extract_fea(res2)
    # lz.msgpack_dump([res3, res4], lz.work_path + 'yy.yy2.fea.pk')

    imgs = pims.ImageSequence(lz.work_path + 'face.yy2/gallery/*.png', process_func=cvb.rgb2bgr)
    res = {}
    for img, path in zip(imgs, imgs._filepaths):
        print(path)
        fea = extract_fea_from_img(img)
        res[path] = fea
    lz.msgpack_dump(res, lz.work_path + '/face.yy2/gallery/gallery.pk')
def crop_face(args):
    for k, v in default_args.items():
        setattr(args, k, v)
    assert osp.exists(args.data_dir), "The input dir not exist"
    root_folder_name = args.data_dir.split('/')[-1]
    src_folder = args.data_dir
    dst_folder = args.data_dir.replace(root_folder_name, root_folder_name + '_OPPOFaces')
    lz.mkdir_p(dst_folder, delete=False)
    ds = TestData(src_folder)
    loader = torch.utils.data.DataLoader(ds, batch_size=args.batch_size,
                                         num_workers=args.num_workers,
                                         shuffle=False,
                                         pin_memory=True,
                                         drop_last=False
                                         )
    # 1. load pre-tained model
    checkpoint_fp = 'models/phase1_wpdc_vdc.pth.tar'
    arch = 'mobilenet_1'
    
    checkpoint = torch.load(checkpoint_fp, map_location=lambda storage, loc: storage)['state_dict']
    model = getattr(mobilenet_v1, arch)(num_classes=62)  # 62 = 12(pose) + 40(shape) +10(expression)
    
    model_dict = model.state_dict()
    # because the model is trained by multiple gpus, prefix module should be removed
    for k in checkpoint.keys():
        model_dict[k.replace('module.', '')] = checkpoint[k]
    model.load_state_dict(model_dict)
    if args.mode == 'gpu':
        cudnn.benchmark = True
        model = model.cuda()
    model.eval()
    
    # 2. load dlib model for face detection and landmark used for face cropping
    queue = Queue()
    lock = Lock()
    consumers = []
    for i in range(args.num_consumers):
        p = Process(target=consumer, args=(queue, lock))
        p.daemon = True
        consumers.append(p)
    for c in consumers:
        c.start()
    # 3. forward
    ttl_nimgs = 0
    ttl_imgs = []
    data_meter = lz.AverageMeter()
    model_meter = lz.AverageMeter()
    post_meter = lz.AverageMeter()
    lz.timer.since_last_check('start crop face')
    for ind, data in enumerate(loader):
        
        data_meter.update(lz.timer.since_last_check(verbose=False))
        if (data['finish'] == 1).all().item():
            logging.info('finish')
            break
        if ind % 10 == 0:
            logging.info(
                f'proc batch {ind}, data time: {data_meter.avg:.2f}, model: {model_meter.avg:.2f}, post: {post_meter.avg:.2f}')
        mask = data['finish'] == 0
        input = data['img'][mask]
        input_np = input.numpy()
        roi_box = data['roi_box'][mask].numpy()
        imgfn = np.asarray(data['imgfn'])[mask.numpy().astype(bool)]
        dst_imgfn = [img_fp.replace(root_folder_name, root_folder_name + '_OPPOFaces') for img_fp in imgfn]
        ttl_imgs.extend(dst_imgfn)
        ttl_nimgs += mask.sum().item()
        with torch.no_grad():
            if args.mode == 'gpu':
                input = input.cuda()
            param = model(input)
            param = param.squeeze().cpu().numpy().astype(np.float32)
        model_meter.update(lz.timer.since_last_check(verbose=False))
        queue.put((imgfn, param, roi_box, dst_imgfn))
        # pts68 = [predict_68pts(param[i], roi_box[i]) for i in range(param.shape[0])]
        # pts68_proc = [predict_68pts(param[i], [0, 0, STD_SIZE, STD_SIZE]) for i in range(param.shape[0])]
        # for img_fp, pts68_, pts68_proc_, img_, dst in zip(imgfn, pts68, pts68_proc, input_np, dst_imgfn):
        #     ## this may need opt to async read write
        #     img_ori = cvb.read_img(img_fp)
        #     pts5 = to_landmark5(pts68_[:2, :].transpose())
        #     warped = preprocess(img_ori, landmark=pts5)
        #     # plt_imshow(warped, inp_mode='bgr');  plt.show()
        #     lz.mkdir_p(osp.dirname(dst), delete=False)
        #     cvb.write_img(warped, dst)
        #
        #     ## this may cause black margin
        #     # pts5 = to_landmark5(pts68_proc_[:2, :].transpose())
        #     # warped = preprocess(to_img(img_), landmark=pts5)
        #     # # plt_imshow(warped, inp_mode='bgr'); plt.show()
        #     # dst = img_fp.replace(root_folder_name, root_folder_name + '_OPPOFaces')
        #     # cvb.write_img(warped, dst)
        #     if args.dump_res:
        #         img_ori = cvb.read_img(img_fp)
        #         pts_res = [pts68_]
        #         dst = img_fp.replace(root_folder_name, root_folder_name + '_kpts.demo')
        #         lz.mkdir_p(osp.dirname(dst), delete=False)
        #         draw_landmarks(img_ori, pts_res,
        #                        wfp=dst,
        #                        show_flg=args.show_flg)
        post_meter.update(lz.timer.since_last_check(verbose=False))
    lz.msgpack_dump(ttl_imgs, dst_folder + '/' + 'all_imgs.pk')
    del model, input
    torch.cuda.empty_cache()
    while not queue.empty():
        time.sleep(1)
예제 #5
0
def test_ijbc3(conf, learner):
    if not use_mxnet:
        learner.model.eval()
    ds = DatasetIJBC2(flip=False)
    loader = torch.utils.data.DataLoader(
        ds,
        batch_size=bs,
        num_workers=conf.num_workers,
        shuffle=False,
        pin_memory=False,
    )
    len(loader) * bs
    for ind, data in enumerate(loader):
        (img, faceness_score, items, names) = data
        if ind % 9 == 0:
            logging.info(f'ok {ind} {len(loader)}')
        if not use_mxnet:
            with torch.no_grad():
                img_feat = learner.model(img)
                img_featf = learner.model(img.flip((3, )))
                fea = (img_feat + img_featf) / 2.
                fea = fea.cpu().numpy()
        else:
            img = img.numpy()
            img_feat = learner.gets(img)
            img_featf = learner.gets(img[:, :, :, ::-1].copy())
            fea = (img_feat + img_featf) / 2.
        # fea = fea * faceness_score.numpy().reshape(-1, 1) # todo need?
        img_feats[ind * bs:min((ind + 1) * bs, ind * bs +
                               fea.shape[0]), :] = fea
    print('last fea shape', fea.shape,
          np.linalg.norm(fea, axis=-1)[-10:], img_feats.shape)
    if dump_mid_res:
        import h5py
        f = h5py.File('/tmp/feas.ijbb.h5', 'w')
        f['feas'] = img_feats
        f.flush()
        f.close()

    templates, medias = df_tm.values[:, 1], df_tm.values[:, 2]
    p1, p2, label = df_pair.values[:, 0], df_pair.values[:,
                                                         1], df_pair.values[:,
                                                                            2]
    unique_templates = np.unique(templates)
    # cache_tfn = lz.work_path + 'ijbc.tfeas.256.pk'
    cache_tfn = None
    if cache_tfn and osp.exists(cache_tfn):
        template_norm_feats = lz.msgpack_load(cache_tfn).copy()
        clst = msgpack_load(lz.work_path + 'ijbc.tclst.pk').copy()
        # clst = msgpack_load(work_path + 'ijbc.tgt.pk').copy()
        lbs = np.unique(clst)
        for lb in lbs:
            if lb == -1: continue
            mask = clst == lb
            if mask.sum() <= 4: continue
            nowf = template_norm_feats[mask, :]
            dist = cdist(nowf, nowf)
            dist[np.arange(dist.shape[0]),
                 np.arange(dist.shape[0])] = dist.max() * 10
            wei = lz.softmax_th(-dist, dim=1, temperature=1)
            refinef = np.matmul(wei, nowf)
            refinef = refinef * 0.3 + nowf * 0.7
            refinef = normalize(refinef, axis=1)
            template_norm_feats[mask, :] = refinef
            if lb % 999 == 1:
                print('now refine ', lb, len(lbs), np.linalg.norm(nowf,
                                                                  axis=1),
                      np.linalg.norm(refinef, axis=1))
    else:
        template_feats = np.zeros((len(unique_templates), img_feats.shape[1]))
        for count_template, uqt in enumerate(unique_templates):
            (ind_t, ) = np.where(templates == uqt)
            face_norm_feats = img_feats[ind_t]
            face_medias = medias[ind_t]
            unique_medias, unique_media_counts = np.unique(face_medias,
                                                           return_counts=True)
            media_norm_feats = []
            for u, ct in zip(unique_medias, unique_media_counts):
                (ind_m, ) = np.where(face_medias == u)
                if ct == 1:
                    media_norm_feats += [face_norm_feats[ind_m]]
                else:  # image features from the same video will be aggregated into one feature
                    media_norm_feats += [
                        np.mean(face_norm_feats[ind_m], 0, keepdims=True)
                    ]
            media_norm_feats = np.array(media_norm_feats)
            # media_norm_feats = media_norm_feats / np.sqrt(np.sum(media_norm_feats ** 2, -1, keepdims=True))
            template_feats[count_template] = np.sum(media_norm_feats, 0)
            if count_template % 2000 == 0:
                print('Finish Calculating {} template features.'.format(
                    count_template))
        template_norm_feats = template_feats / np.sqrt(
            np.sum(template_feats**2, -1, keepdims=True))
        if cache_tfn:
            lz.msgpack_dump(template_norm_feats, cache_tfn)

    template2id = np.zeros((max(unique_templates) + 1, 1), dtype=int)
    for count_template, uqt in enumerate(unique_templates):
        template2id[uqt] = count_template

    score = np.zeros((len(p1), ))  # save cosine distance between pairs

    total_pairs = np.array(range(len(p1)))
    batchsize = 100000  # small batchsize instead of all pairs in one batch due to the memory limiation
    sublists = [
        total_pairs[i:i + batchsize] for i in range(0, len(p1), batchsize)
    ]
    total_sublists = len(sublists)

    for c, s in enumerate(sublists):
        feat1 = template_norm_feats[template2id[p1[s]]].reshape(-1, DIM)
        feat2 = template_norm_feats[template2id[p2[s]]].reshape(-1, DIM)
        # similarity_score = np.sum(feat1 * feat2, -1)
        similarity_score = -(np.linalg.norm(feat1, axis=-1) + np.linalg.norm(
            feat2, axis=-1) - 2 * np.sum(feat1 * feat2, -1))
        score[s] = similarity_score.flatten()
        if c % 10 == 0:
            print('Finish {}/{} pairs.'.format(c, total_sublists))
    if dump_mid_res:
        msgpack_dump([label, score], f'/tmp/score.ijbb.pk')
    print('score range', score.max(), score.min())
    # _ = plt.hist(score)
    fpr, tpr, _ = roc_curve(label, score)
    # plt.figure()
    # plt.semilogx(fpr, tpr, '.-')
    # plt.show()
    fpr = np.flipud(fpr)
    tpr = np.flipud(tpr)  # select largest tpr at same fpr
    res = []
    x_labels = [
        10**-6,
        10**-4,
        10**-3,
    ]
    for fpr_iter in np.arange(len(x_labels)):
        _, min_index = min(
            list(zip(abs(fpr - x_labels[fpr_iter]), range(len(fpr)))))
        print(x_labels[fpr_iter], tpr[min_index])
        res.append((x_labels[fpr_iter], tpr[min_index]))
    roc_auc = auc(fpr, tpr)
    print('roc aux', roc_auc)
    logging.info(f'perf {res}')
    if not use_mxnet:
        learner.model.train()
    return res
예제 #6
0
def main(args):
    sys.stdout = Logger(osp.join(args.logs_dir, 'log.txt'))
    sys.stderr = Logger(osp.join(args.logs_dir, 'err.txt'))
    lz.init_dev(args.gpu)
    print('config is {}'.format(vars(args)))
    if args.seed is not None:
        np.random.seed(args.seed)
        torch.manual_seed(args.seed)
    cudnn.benchmark = True

    # Create data loaders
    assert args.num_instances > 1, "num_instances should be greater than 1"
    assert args.batch_size % args.num_instances == 0, \
        'num_instances should divide batch_size'

    test_loader = get_data(args)

    # Create model
    model = models.create(
        args.arch,
        dropout=args.dropout,
        pretrained=args.pretrained,
        block_name=args.block_name,
        block_name2=args.block_name2,
        num_features=args.num_classes,
        num_classes=100,
        num_deform=args.num_deform,
        fusion=args.fusion,
        last_conv_stride=args.last_conv_stride,
        last_conv_dilation=args.last_conv_dilation,
    )

    print(model)
    param_mb = sum(p.numel() for p in model.parameters()) / 1000000.0
    print('    Total params: %.2fM' % (param_mb))

    # Load from checkpoint
    start_epoch = best_top1 = 0
    if args.resume:
        while not osp.exists(args.resume):
            lz.logging.warning(' no chkpoint {} '.format(args.resume))
            time.sleep(20)
        if torch.cuda.is_available():
            checkpoint = load_checkpoint(args.resume)
        else:
            checkpoint = load_checkpoint(args.resume, map_location='cpu')
        # model.load_state_dict(checkpoint['state_dict'])
        db_name = args.logs_dir + '/' + args.logs_dir.split('/')[-1] + '.h5'
        load_state_dict(model, checkpoint['state_dict'])
        with lz.Database(db_name) as db:
            if 'cent' in checkpoint:
                db['cent'] = to_numpy(checkpoint['cent'])
            db['xent'] = to_numpy(checkpoint['state_dict']['embed2.weight'])
        if args.restart:
            start_epoch_ = checkpoint['epoch']
            best_top1_ = checkpoint['best_top1']
            print("=> Start epoch {}  best top1 {:.1%}".format(
                start_epoch_, best_top1_))
        else:
            start_epoch = checkpoint['epoch']
            best_top1 = checkpoint['best_top1']
            print("=> Start epoch {}  best top1 {:.1%}".format(
                start_epoch, best_top1))
    if args.gpu is None or len(args.gpu) == 0:
        model = nn.DataParallel(model)
    elif len(args.gpu) == 1:
        model = nn.DataParallel(model).cuda()
    else:
        model = nn.DataParallel(model, device_ids=range(len(args.gpu))).cuda()

    # Distance metric
    metric = DistanceMetric(algorithm=args.dist_metric)

    # Evaluator
    features, _ = extract_features(model, test_loader)
    for k in features.keys():
        features[k] = features[k].numpy()
    lz.msgpack_dump(features, work_path + '/reid.person/fea.mp', allow_np=True)
예제 #7
0
 def __init__(self, batch_size, data_shape,
              path_imgrec=None,
              shuffle=False, aug_list=None, mean=None,
              rand_mirror=False, cutoff=0, color_jittering=0,
              images_filter=0,
              data_name='data', label_name='softmax_label',
              # metric_learning=True,
              metric_learning=False,
              # todo  metric learning batch formation method do not affects the scale of loss ?
              **kwargs):
     super(FaceImageIter, self).__init__()
     self.metric_learning = metric_learning
     assert path_imgrec
     if path_imgrec:
         logging.info('loading recordio %s...',
                      path_imgrec)
         path_imgidx = path_imgrec[0:-4] + ".idx"
         self.imgrec = recordio.MXIndexedRecordIO(path_imgidx, path_imgrec,
                                                  'r')  # pylint: disable=redefined-variable-type
         try:
             self.imgidx, self.seq_identity, self.id2range = lz.msgpack_load(
                 os.path.dirname(path_imgidx) + '/info.mxnet.pk', use_list=True)
         except:
             s = self.imgrec.read_idx(0)
             header, _ = recordio.unpack(s)
             if header.flag > 0:
                 print('header0 label', header.label)
                 self.header0 = (int(header.label[0]), int(header.label[1]))
                 # assert(header.flag==1)
                 # self.imgidx = list(range(1, int(header.label[0])))
                 self.imgidx = []
                 self.id2range = {}
                 self.seq_identity = list(range(int(header.label[0]), int(header.label[1])))
                 for identity in self.seq_identity:
                     s = self.imgrec.read_idx(identity)
                     header, _ = recordio.unpack(s)
                     a, b = int(header.label[0]), int(header.label[1])
                     count = b - a
                     if count < images_filter:
                         continue
                     self.id2range[identity] = (a, b)
                     self.imgidx += range(a, b)
             else:
                 self.imgidx = list(self.imgrec.keys)
             lz.msgpack_dump([self.imgidx, self.seq_identity, self.id2range],
                             os.path.dirname(path_imgidx) + '/info.mxnet.pk')
         print('id2range', len(self.id2range))
         if shuffle:
             self.seq = self.imgidx
             self.oseq = self.imgidx
             print(len(self.seq))
         else:
             self.seq = None
     
     self.mean = mean
     self.nd_mean = None
     if self.mean:
         self.mean = np.array(self.mean, dtype=np.float32).reshape(1, 1, 3)
         self.nd_mean = mx.nd.array(self.mean).reshape((1, 1, 3))
     
     self.check_data_shape(data_shape)
     self.provide_data = [(data_name, (batch_size,) + data_shape)]
     self.batch_size = batch_size
     self.data_shape = data_shape
     self.shuffle = shuffle
     self.image_size = '%d,%d' % (data_shape[1], data_shape[2])
     self.rand_mirror = rand_mirror
     print('rand_mirror', rand_mirror)
     self.cutoff = cutoff
     self.color_jittering = color_jittering
     self.CJA = mx.image.ColorJitterAug(0.125, 0.125, 0.125)
     self.provide_label = [(label_name, (batch_size,))]
     logging.info(f'one iter: provide {self.provide_data}, {self.provide_label}')
     # print(self.provide_label[0][1])
     self.cur = 0
     self.nbatch = 0
     self.is_init = False
     self.num_instances = 4
     self.num_pids_per_batch = self.batch_size // self.num_instances
     self.inds_queue = []