def get_namescore_nonvoting_feature_flags(fm_list, fs_list, dnid_list, name_groupxs, kpts1=None): r""" fm_list = [fm[:min(len(fm), 10)] for fm in fm_list] fs_list = [fs[:min(len(fs), 10)] for fs in fs_list] """ fx1_list = [fm.T[0] for fm in fm_list] # Group annotation matches by name name_grouped_fx1_list = vt.apply_grouping_(fx1_list, name_groupxs) name_grouped_fs_list = vt.apply_grouping_(fs_list, name_groupxs) # Stack up all matches to a particular name, keep track of original indicies via offets name_invertable_flat_fx1_list = list(map(ut.invertible_flatten2_numpy, name_grouped_fx1_list)) name_grouped_fx1_flat = ut.get_list_column(name_invertable_flat_fx1_list, 0) name_grouped_invertable_cumsum_list = ut.get_list_column(name_invertable_flat_fx1_list, 1) name_grouped_fs_flat = list(map(np.hstack, name_grouped_fs_list)) if kpts1 is not None: xys1_ = vt.get_xys(kpts1).T kpts_xyid_list = vt.compute_unique_data_ids(xys1_) # Make nested group for every name by query feature index (accounting for duplicate orientation) name_grouped_xyid_flat = list(kpts_xyid_list.take(fx1) for fx1 in name_grouped_fx1_flat) xyid_groupxs_list = list(vt.group_indices(xyid_flat)[1] for xyid_flat in name_grouped_xyid_flat) name_group_fx1_groupxs_list = xyid_groupxs_list else: # Make nested group for every name by query feature index fx1_groupxs_list = [vt.group_indices(fx1_flat)[1] for fx1_flat in name_grouped_fx1_flat] name_group_fx1_groupxs_list = fx1_groupxs_list name_grouped_fid_grouped_fs_list = [ vt.apply_grouping(fs_flat, fid_groupxs) for fs_flat, fid_groupxs in zip(name_grouped_fs_flat, name_group_fx1_groupxs_list) ] # Flag which features are valid in this grouped space. Only one keypoint should be able to vote # for each group name_grouped_fid_grouped_isvalid_list = [ np.array([fs_group.max() == fs_group for fs_group in fid_grouped_fs_list]) for fid_grouped_fs_list in name_grouped_fid_grouped_fs_list ] # Go back to being grouped only in name space #dtype = np.bool name_grouped_isvalid_flat_list = [ vt.invert_apply_grouping2(fid_grouped_isvalid_list, fid_groupxs, dtype=np.bool) for fid_grouped_isvalid_list, fid_groupxs in zip(name_grouped_fid_grouped_isvalid_list, name_group_fx1_groupxs_list) ] name_grouped_isvalid_unflat_list = [ ut.unflatten2(isvalid_flat, invertable_cumsum_list) for isvalid_flat, invertable_cumsum_list in zip(name_grouped_isvalid_flat_list, name_grouped_invertable_cumsum_list) ] # Reports which features were valid in name scoring for every annotation featflag_list = vt.invert_apply_grouping(name_grouped_isvalid_unflat_list, name_groupxs) return featflag_list
def general_name_coverage_mask_generator(make_mask_func, qreq_, cm, config, cov_cfg): """ DEPRICATE Yeilds: nid, weight_mask_m, weight_mask CommandLine: python -m wbia.algo.hots.scoring --test-general_name_coverage_mask_generator --show python -m wbia.algo.hots.scoring --test-general_name_coverage_mask_generator --show --qaid 18 Note: Evaluate output one at a time or it will get clobbered Example0: >>> # SLOW_DOCTEST >>> # (IMPORTANT) >>> from wbia.algo.hots.scoring import * # NOQA >>> qreq_, cm = plh.testdata_scoring('PZ_MTEST', qaid_list=[18]) >>> config = qreq_.qparams >>> make_mask_func, cov_cfg = get_mask_func(config) >>> masks_iter = general_name_coverage_mask_generator(make_mask_func, qreq_, cm, config, cov_cfg) >>> dnid_list, score_list, masks_list = evaluate_masks_iter(masks_iter) >>> ut.quit_if_noshow() >>> nidx = np.where(dnid_list == cm.qnid)[0][0] >>> daids = cm.get_groundtruth_daids() >>> dnid, weight_mask_m, weight_mask = masks_list[nidx] >>> show_single_coverage_mask(qreq_, cm, weight_mask_m, weight_mask, daids) >>> ut.show_if_requested() """ import vtool as vt if ut.VERYVERBOSE: logger.info('[ncov] make_mask_func = %r' % (make_mask_func, )) logger.info('[ncov] cov_cfg = %s' % (ut.repr2(cov_cfg), )) assert cm.dnid_list is not None, 'eval nids' unique_dnids, groupxs = vt.group_indices(cm.dnid_list) fm_groups = vt.apply_grouping_(cm.fm_list, groupxs) fs_groups = vt.apply_grouping_(cm.fs_list, groupxs) fs_name_list = [np.hstack(fs_group) for fs_group in fs_groups] fm_name_list = [np.vstack(fm_group) for fm_group in fm_groups] return general_coverage_mask_generator( make_mask_func, qreq_, cm.qaid, unique_dnids, fm_name_list, fs_name_list, config, cov_cfg, )
def compute_nsum_score2(cm, qreq_=None): r""" Example3: >>> # DISABLE_DOCTEST >>> from ibeis.algo.hots.name_scoring import * # NOQA >>> #ibs, qreq_, cm_list = plh.testdata_pre_sver('testdb1', qaid_list=[1]) >>> ibs, qreq_, cm_list = plh.testdata_post_sver('testdb1', qaid_list=[1], cfgdict=dict(fg_on=False, augment_queryside_hack=True)) >>> cm = cm_list[0] >>> cm.evaluate_dnids(qreq_.ibs) >>> nsum_nid_list1, nsum_score_list1, featflag_list1 = compute_nsum_score2(cm, qreq_) >>> nsum_nid_list2, nsum_score_list2 = compute_nsum_score(cm, qreq_) >>> ut.quit_if_noshow() >>> cm.show_ranked_matches(qreq_, ori=True) """ featflag_list2 = get_chipmatch_namescore_nonvoting_feature_flags(cm, qreq_) fs_list = cm.get_fsv_prod_list() name_groupxs2 = cm.name_groupxs nsum_nid_list2 = cm.unique_nids #-- valid_fs_list2 = vt.zipcompress(fs_list, featflag_list2) name_grouped_valid_fs_list2 = vt.apply_grouping_(valid_fs_list2, name_groupxs2) nsum_score_list2 = np.array([sum(list(map(np.sum, valid_fs_group))) for valid_fs_group in name_grouped_valid_fs_list2]) if False: nsum_score_list3 = np.array([ # NOQA np.sum([fs_group.sum() for fs_group in valid_fs_group]) for valid_fs_group in name_grouped_valid_fs_list2]) return nsum_nid_list2, nsum_score_list2, featflag_list2
def general_name_coverage_mask_generator(make_mask_func, qreq_, cm, config, cov_cfg): """ Yeilds: nid, weight_mask_m, weight_mask CommandLine: python -m ibeis.algo.hots.scoring --test-general_name_coverage_mask_generator --show python -m ibeis.algo.hots.scoring --test-general_name_coverage_mask_generator --show --qaid 18 Note: Evaluate output one at a time or it will get clobbered Example0: >>> # SLOW_DOCTEST >>> # (IMPORTANT) >>> from ibeis.algo.hots.scoring import * # NOQA >>> qreq_, cm = plh.testdata_scoring('PZ_MTEST', qaid_list=[18]) >>> config = qreq_.qparams >>> make_mask_func, cov_cfg = get_mask_func(config) >>> masks_iter = general_name_coverage_mask_generator(make_mask_func, qreq_, cm, config, cov_cfg) >>> dnid_list, score_list, masks_list = evaluate_masks_iter(masks_iter) >>> ut.quit_if_noshow() >>> nidx = np.where(dnid_list == cm.qnid)[0][0] >>> daids = cm.get_groundtruth_daids() >>> dnid, weight_mask_m, weight_mask = masks_list[nidx] >>> show_single_coverage_mask(qreq_, cm, weight_mask_m, weight_mask, daids) >>> ut.show_if_requested() """ if ut.VERYVERBOSE: print('[ncov] make_mask_func = %r' % (make_mask_func,)) print('[ncov] cov_cfg = %s' % (ut.dict_str(cov_cfg),)) assert cm.dnid_list is not None, 'eval nids' unique_dnids, groupxs = vt.group_indices(cm.dnid_list) fm_groups = vt.apply_grouping_(cm.fm_list, groupxs) fs_groups = vt.apply_grouping_(cm.fs_list, groupxs) fs_name_list = [np.hstack(fs_group) for fs_group in fs_groups] fm_name_list = [np.vstack(fm_group) for fm_group in fm_groups] return general_coverage_mask_generator(make_mask_func, qreq_, cm.qaid, unique_dnids, fm_name_list, fs_name_list, config, cov_cfg)
def compute_nsum_score(cm, qreq_=None): r""" nsum Args: cm (ibeis.ChipMatch): Returns: tuple: (unique_nids, nsum_score_list) CommandLine: python -m ibeis.algo.hots.name_scoring --test-compute_nsum_score python -m ibeis.algo.hots.name_scoring --test-compute_nsum_score:0 python -m ibeis.algo.hots.name_scoring --test-compute_nsum_score:2 utprof.py -m ibeis.algo.hots.name_scoring --test-compute_nsum_score:2 utprof.py -m ibeis.algo.hots.pipeline --test-request_ibeis_query_L0:0 --db PZ_Master1 -a timectrl:qindex=0:256 Example0: >>> # ENABLE_DOCTEST >>> from ibeis.algo.hots.name_scoring import * # NOQA >>> # build test data >>> cm = testdata_chipmatch() >>> # execute function >>> (unique_nids, nsum_score_list) = compute_nsum_score(cm) >>> result = ut.list_str((unique_nids, nsum_score_list), label_list=['unique_nids', 'nsum_score_list'], with_dtype=False) >>> print(result) unique_nids = np.array([1, 2, 3]) nsum_score_list = np.array([ 4., 7., 5.]) Example1: >>> # ENABLE_DOCTEST >>> from ibeis.algo.hots.name_scoring import * # NOQA >>> #ibs, qreq_, cm_list = plh.testdata_pre_sver('testdb1', qaid_list=[1]) >>> ibs, qreq_, cm_list = plh.testdata_post_sver('PZ_MTEST', qaid_list=[18]) >>> cm = cm_list[0] >>> cm.evaluate_dnids(qreq_.ibs) >>> cm._cast_scores() >>> #cm.qnid = 1 # Hack for testdb1 names >>> nsum_nid_list, nsum_score_list = compute_nsum_score(cm, qreq_) >>> assert np.all(nsum_nid_list == cm.unique_nids), 'nids out of alignment' >>> flags = (nsum_nid_list == cm.qnid) >>> max_true = nsum_score_list[flags].max() >>> max_false = nsum_score_list[~flags].max() >>> assert max_true > max_false, 'is this truely a hard case?' >>> assert max_true > 1.2, 'score=%r should be higher for aid=18' % (max_true,) >>> nsum_nid_list2, nsum_score_list2, _ = compute_nsum_score2(cm, qreq_) >>> assert np.allclose(nsum_score_list2, nsum_score_list), 'something is very wrong' >>> #assert np.all(nsum_score_list2 == nsum_score_list), 'could be a percision issue' Example2: >>> # ENABLE_DOCTEST >>> from ibeis.algo.hots.name_scoring import * # NOQA >>> #ibs, qreq_, cm_list = plh.testdata_pre_sver('testdb1', qaid_list=[1]) >>> ibs, qreq_, cm_list = plh.testdata_post_sver('PZ_MTEST', qaid_list=[18], cfgdict=dict(augment_queryside_hack=True)) >>> cm = cm_list[0] >>> cm.score_nsum(qreq_) >>> #cm.evaluate_dnids(qreq_.ibs) >>> #cm.qnid = 1 # Hack for testdb1 names >>> #nsum_nid_list, nsum_score_list = compute_nsum_score(cm, qreq_=qreq_) >>> ut.quit_if_noshow() >>> cm.show_ranked_matches(qreq_, ori=True) Example3: >>> # DISABLE_DOCTEST >>> from ibeis.algo.hots.name_scoring import * # NOQA >>> #ibs, qreq_, cm_list = plh.testdata_pre_sver('testdb1', qaid_list=[1]) >>> ibs, qreq_, cm_list = plh.testdata_post_sver('testdb1', qaid_list=[1], cfgdict=dict(augment_queryside_hack=True)) >>> cm = cm_list[0] >>> cm.score_nsum(qreq_) >>> #cm.evaluate_dnids(qreq_.ibs) >>> #cm.qnid = 1 # Hack for testdb1 names >>> #nsum_nid_list, nsum_score_list = compute_nsum_score(cm, qreq_=qreq_) >>> ut.quit_if_noshow() >>> cm.show_ranked_matches(qreq_, ori=True) Example4: >>> # ENABLE_DOCTEST >>> # FIXME: breaks when fg_on=True >>> from ibeis.algo.hots.name_scoring import * # NOQA >>> from ibeis.algo.hots import name_scoring >>> from ibeis.algo.hots import scoring >>> import ibeis >>> # Test to make sure name score and chips score are equal when per_name=1 >>> qreq_, args = plh.testdata_pre( >>> 'spatial_verification', defaultdb='PZ_MTEST', >>> a=['default:dpername=1,qsize=1,dsize=10'], >>> p=['default:K=1,fg_on=True,sqrd_dist_on=True']) >>> cm = args.cm_list_FILT[0] >>> ibs = qreq_.ibs >>> # Ensure there is only one aid per database name >>> assert isinstance(ibs, ibeis.control.IBEISControl.IBEISController) >>> #stats_dict = ibs.get_annot_stats_dict(qreq_.get_external_daids(), prefix='d') >>> #stats = stats_dict['dper_name'] >>> stats = ibs.get_annot_per_name_stats(qreq_.get_external_daids()) >>> print('per_name_stats = %s' % (ut.dict_str(stats, nl=False),)) >>> assert stats['mean'] == 1 and stats['std'] == 0, 'this test requires one annot per name in the database' >>> cm.evaluate_dnids(qreq_.ibs) >>> cm.assert_self(qreq_) >>> cm._cast_scores() >>> # cm.fs_list = cm.fs_list.astype(np.float) >>> nsum_nid_list, nsum_score_list = name_scoring.compute_nsum_score(cm, qreq_) >>> nsum_nid_list2, nsum_score_list2, _ = name_scoring.compute_nsum_score2(cm, qreq_) >>> csum_score_list = scoring.compute_csum_score(cm) >>> vt.asserteq(nsum_score_list, csum_score_list) >>> vt.asserteq(nsum_score_list, csum_score_list, thresh=0, iswarning=True) >>> vt.asserteq(nsum_score_list2, csum_score_list, thresh=0, iswarning=True) >>> #assert np.allclose(nsum_score_list, csum_score_list), 'should be the same when K=1 and per_name=1' >>> #assert all(nsum_score_list == csum_score_list), 'should be the same when K=1 and per_name=1' >>> #assert all(nsum_score_list2 == csum_score_list), 'should be the same when K=1 and per_name=1' >>> # Evaluate parts of the sourcecode Ignore: assert all(nsum_score_list3 == csum_score_list), 'should be the same when K=1 and per_name=1' fm_list = fm_list[0:1] fs_list = fs_list[0:1] featflag_list2 = featflag_list2[0:1] dnid_list = dnid_list[0:1] name_groupxs2 = name_groupxs2[0:1] nsum_nid_list2 = nsum_nid_list2[0:1] """ #assert qreq_ is not None try: HACK_SINGLE_ORI = qreq_ is not None and (qreq_.qparams.augment_queryside_hack or qreq_.qparams.rotation_invariance) except AttributeError: HACK_SINGLE_ORI = qreq_ is not None and (qreq_.config.augment_queryside_hack or qreq_.config.feat_cfg.rotation_invariance) pass # The core for each feature match # # The query feature index for each feature match fm_list = cm.fm_list fs_list = cm.get_fsv_prod_list() dnid_list = cm.dnid_list #-- fx1_list = [fm.T[0] for fm in fm_list] """ # Try a rebase? fx1_list = list(map(vt.compute_unique_data_ids_, fx1_list)) """ # Group annotation matches by name nsum_nid_list, name_groupxs = vt.group_indices(dnid_list) name_grouped_fx1_list = vt.apply_grouping_(fx1_list, name_groupxs) name_grouped_fs_list = vt.apply_grouping_(fs_list, name_groupxs) # Stack up all matches to a particular name name_grouped_fx1_flat = list(map(np.hstack, name_grouped_fx1_list)) name_grouped_fs_flat = list(map(np.hstack, name_grouped_fs_list)) """ assert np.all(name_grouped_fs_list[0][0] == fs_list[0]) assert np.all(name_grouped_fs_flat[0] == fs_list[0]) """ if HACK_SINGLE_ORI: # keypoints with the same xy can only have one of them vote kpts1 = qreq_.ibs.get_annot_kpts(cm.qaid, config2_=qreq_.get_external_query_config2()) xys1_ = vt.get_xys(kpts1).T kpts_xyid_list = vt.compute_unique_arr_dataids(xys1_) # Make nested group for every name by query feature index (accounting for duplicate orientation) name_grouped_xyid_flat = [kpts_xyid_list.take(fx1) for fx1 in name_grouped_fx1_flat] feat_groupxs_list = [vt.group_indices(xyid_flat)[1] for xyid_flat in name_grouped_xyid_flat] else: # make unique indicies using feature indexes feat_groupxs_list = [vt.group_indices(fx1_flat)[1] for fx1_flat in name_grouped_fx1_flat] # Make nested group for every name by unique query feature index feat_grouped_fs_list = [[fs_flat.take(xs, axis=0) for xs in feat_groupxs] for fs_flat, feat_groupxs in zip(name_grouped_fs_flat, feat_groupxs_list)] """ np.array(feat_grouped_fs_list)[0].T[0] == fs_list """ if False: valid_fs_list = [ np.array([group.max() for group in grouped_fs]) #np.array([group[group.argmax()] for group in grouped_fs]) for grouped_fs in feat_grouped_fs_list ] nsum_score_list4 = np.array([valid_fs.sum() for valid_fs in valid_fs_list]) # NOQA # Prevent a feature from voting twice: # take only the max score that a query feature produced #name_grouped_valid_fs_list1 =[np.array([fs_group.max() for fs_group in feat_grouped_fs]) # for feat_grouped_fs in feat_grouped_fs_list] nsum_score_list = np.array([np.sum([fs_group.max() for fs_group in feat_grouped_fs]) for feat_grouped_fs in feat_grouped_fs_list]) return nsum_nid_list, nsum_score_list