Source code for wbia.tag_funcs
# -*- coding: utf-8 -*-
import logging
import numpy as np
import vtool as vt
import utool as ut
from wbia.control import controller_inject
print, rrr, profile = ut.inject2(__name__)
logger = logging.getLogger('wbia')
# Create dectorator to inject functions in this module into the IBEISController
CLASS_INJECT_KEY, register_ibs_method = controller_inject.make_ibs_register_decorator(
__name__
)
# TODO : make a annot_tags file
ANNOTMATCH_PROPS_STANDARD = [
# 'SceneryMatch',
# 'Photobomb',
# 'Hard',
# 'NonDistinct',
]
ANNOTMATCH_PROPS_OTHER = [
'SceneryMatch',
'Photobomb',
'Hard',
'NonDistinct',
'Occlusion',
'Viewpoint',
'MildViewpoint',
'Pose',
'Lighting',
'Quality', # quality causes failure
'Orientation', # orientation caused failure
'EdgeMatch', # descriptors on the edge of the naimal produce strong matches
'Interesting', # flag a case as interesting
'JoinCase', # case should actually be marked as correct
'SplitCase', # case should actually be marked as correct
'random', # gf case has random matches, the gt is to blame
'BadShoulder', # gf is a bad shoulder match
'BadTail', # gf is a bad tail match
'TimeDeltaError',
# These annots have almost the same information
'NearDuplicate',
'CorrectPhotobomb', # FIXME: this is a terrible name
]
OLD_ANNOTMATCH_PROPS = [
'TooLargeMatches', # really big nondistinct matches
'TooSmallMatches', # really big nondistinct matches
'ScoringIssue', # matches should be scored differently
'BadCoverage', # matches were not in good places (missing matches)
'ViewpointOMG', # gf is a bad tail match
'ViewpointCanDo', # gf is a bad tail match
'shouldhavemore',
'Shadowing', # shadow causes failure
'success', # A good success case
'GoodCoverage', # matches were spread out correctly (scoring may be off though)
]
# Changes to prop names
PROP_MAPPING = {
'ViewpointCanDo': 'Correctable',
'ViewpointOMG': 'Uncorrectable',
'Shadowing': 'Lighting',
'success': None,
'GoodCoverage': None,
# 'Hard' : 'NeedsWork',
'shouldhavemore': 'NeedsWork',
'BadCoverage': 'NeedsWork',
'ScoringIssue': 'NeedsWork',
'TooSmallMatches': 'FeatureScale',
'TooLargeMatches': 'FeatureScale',
# 'BadShoulder' : 'BadShoulder',
# 'GoodCoverage': None,
}
for key, val in PROP_MAPPING.items():
if key in ANNOTMATCH_PROPS_OTHER:
ANNOTMATCH_PROPS_OTHER.remove(key)
if val is not None and val not in ANNOTMATCH_PROPS_OTHER:
ANNOTMATCH_PROPS_OTHER.append(val)
ANNOTMATCH_PROPS_OTHER_SET = set([_.lower() for _ in ANNOTMATCH_PROPS_OTHER])
ANNOTMATCH_PROPS_OLD_SET = set([_.lower() for _ in OLD_ANNOTMATCH_PROPS])
# ANNOTMATCH_PROPS_STANDARD_SET = set([_.lower() for _ in ANNOTMATCH_PROPS_STANDARD])
[docs]def consolodate_annotmatch_tags(old_tags):
# return case_tags
remove_tags = [
'hard',
'needswork',
'correctable',
'uncorrectable',
'interesting',
'splitcase',
'joincase',
# 'orientation',
'random',
# 'badtail', 'badshoulder', 'splitcase', 'joincase', 'goodcoverage', 'interesting', 'hard'
]
tags_dict = {
# 'quality': 'Quality',
# 'scoringissue': 'ScoringIssue',
# 'orientation': 'Orientation',
# 'orientation': 'MildViewpoint',
'orientation': 'Viewpoint',
# 'pose': 'SimilarPose',
'pose': 'NonDistinct',
# 'lighting': 'Lighting',
# 'occlusion': 'Occlusion',
# 'featurescale': 'FeatureScale',
# 'edgematch': 'EdgeMatches',
# 'featurescale': 'Pose',
# 'featurescale': 'FeatureScale',
'nondistinct': 'NonDistinct',
'featurescale': 'NonDistinct',
'edgematch': 'SimilarPose',
'badtail': 'NonDistinct',
'badshoulder': 'NonDistinct',
# 'mildviewpoint': 'MildViewpoint',
'mildviewpoint': 'Viewpoint',
# 'toolargematches': 'CoarseFeatures',
# 'badcoverage': 'LowCoverage',
# 'shouldhavemore': 'LowCoverage',
# 'viewpoint': 'Viewpoint',
}
def filter_tags(tags):
return [t for t in tags if t.lower() not in remove_tags]
def map_tags(tags):
return [tags_dict.get(t.lower(), t) for t in tags]
def cap_tags(tags):
return [t[0].upper() + t[1:] for t in tags]
filtered_tags = list(map(filter_tags, old_tags))
mapped_tags = list(map(map_tags, filtered_tags))
unique_tags = list(map(ut.unique_ordered, mapped_tags))
new_tags = list(map(cap_tags, unique_tags))
return new_tags
[docs]def rename_and_reduce_tags(ibs, annotmatch_rowids):
"""
Script to update tags to newest values
CommandLine:
python -m wbia.tag_funcs --exec-rename_and_reduce_tags --db PZ_Master1
Ignore:
>>> from wbia.tag_funcs import * # NOQA
>>> import wbia
>>> #ibs = wbia.opendb(defaultdb='PZ_Master1')
>>> ibs = wbia.opendb(defaultdb='testdb1')
>>> annotmatch_rowids = filter_annotmatch_by_tags(ibs, min_num=1)
>>> rename_and_reduce_tags(ibs, annotmatch_rowids)
"""
tags_list_ = get_annotmatch_case_tags(ibs, annotmatch_rowids)
def fix_tags(tags):
return {str(t.lower()) for t in tags}
tags_list = list(map(fix_tags, tags_list_))
prop_mapping = {str(key.lower()): val for key, val in PROP_MAPPING.items()}
bad_tags = fix_tags(prop_mapping.keys())
for rowid, tags in zip(annotmatch_rowids, tags_list):
old_tags = tags.intersection(bad_tags)
for tag in old_tags:
ibs.set_annotmatch_prop(tag, [rowid], [False])
new_tags = ut.dict_take(prop_mapping, old_tags)
for tag in new_tags:
if tag is not None:
ibs.set_annotmatch_prop(tag, [rowid], [True])
[docs]def get_cate_categories():
standard = ANNOTMATCH_PROPS_STANDARD
other = ANNOTMATCH_PROPS_OTHER
# case_list = standard + other
return standard, other
[docs]def export_tagged_chips(ibs, aid_list, dpath='.'):
"""
DEPRICATE
CommandLine:
python -m wbia.tag_funcs --exec-export_tagged_chips --tags Hard interesting needswork --db PZ_Master1
python -m wbia.tag_funcs --exec-export_tagged_chips --logic=or --any_startswith quality occlusion --has_any lighting needswork interesting hard --db GZ_Master1 --dpath=/media/raid
python -m wbia.tag_funcs --exec-export_tagged_chips --db GZ_Master1 --min_num=1 --dpath /media/raid
Example:
>>> # SCRIPT
>>> from wbia.tag_funcs import * # NOQA
>>> import wbia
>>> ibs = wbia.opendb(defaultdb='testdb1')
>>> kwargs = ut.argparse_dict(ut.get_kwdefaults2(filterflags_general_tags), type_hint=ut.ddict(list, logic=str))
>>> ut.print_dict(kwargs, 'filter args')
>>> aid_list = ibs.filter_annots_by_tags(**kwargs)
>>> print('len(aid_list) = %r' % (len(aid_list),))
>>> dpath = ut.get_argval('--dpath', default='')
>>> all_tags = ut.flatten(ibs.get_annot_all_tags(aid_list))
>>> filtered_tag_hist = ut.dict_hist(all_tags)
>>> ut.print_dict(filtered_tag_hist, key_order_metric='val')
>>> export_tagged_chips(ibs, aid_list, dpath)
"""
visual_uuid_hashid = ibs.get_annot_hashid_visual_uuid(aid_list)
zip_fpath = ut.unixjoin(
dpath, 'exported_chips2_' + ibs.get_dbname() + visual_uuid_hashid + '.zip'
)
chip_fpath = ibs.get_annot_chip_fpath(aid_list)
ut.archive_files(zip_fpath, chip_fpath, common_prefix=True)
[docs]@register_ibs_method
def filter_annots_by_tags(ibs, aid_list=None, **kwargs):
"""
Filter / Find / Search for annotations with particular tags
CommandLine:
python -m wbia.tag_funcs --exec-filter_annots_by_tags --helpx
python -m wbia.tag_funcs --exec-filter_annots_by_tags --db GZ_Master1
python -m wbia.tag_funcs --exec-filter_annots_by_tags --db GZ_Master1 --min_num=1
python -m wbia.tag_funcs --exec-filter_annots_by_tags --db GZ_Master1 --has_any=lighting --has_all=lighting:underexposed --show
SeeAlso:
python -m wbia.init.filter_annots --exec-filter_annots_general
Example:
>>> # ENABLE_DOCTEST
>>> from wbia.tag_funcs import * # NOQA
>>> import wbia
>>> ibs = wbia.opendb(defaultdb='testdb1')
>>> aid_list = ibs.get_valid_aids()
>>> kwargs = ut.argparse_dict(ut.get_kwdefaults2(filterflags_general_tags), type_hint=ut.ddict(list, logic=str))
>>> ut.print_dict(kwargs, 'filter args')
>>> aid_list = ibs.filter_annots_by_tags(aid_list, **kwargs)
>>> print('len(aid_list) = %r' % (len(aid_list),))
>>> # print results
>>> all_tags = ut.flatten(ibs.get_annot_all_tags(aid_list))
>>> filtered_tag_hist = ut.dict_hist(all_tags)
>>> ut.print_dict(filtered_tag_hist, key_order_metric='val')
>>> print('len(aid_list) = %r' % (len(aid_list),))
>>> print('sum(tags) = %r' % (sum(filtered_tag_hist.values()),))
>>> ut.quit_if_noshow()
>>> import wbia.viz.interact
>>> wbia.viz.interact.interact_chip.interact_multichips(ibs, aid_list)
>>> ut.show_if_requested()
"""
if aid_list is None:
aid_list = ibs.get_valid_aids()
tags_list = ibs.get_annot_all_tags(aid_list)
flags = filterflags_general_tags(tags_list, **kwargs)
aid_list = ut.compress(aid_list, flags)
return aid_list
[docs]@register_ibs_method
def filterflags_annot_tags(ibs, aid_list, **kwargs):
"""
Filter / Find / Search for annotations with particular tags
"""
tags_list = ibs.get_annot_all_tags(aid_list)
flags = filterflags_general_tags(tags_list, **kwargs)
return flags
[docs]@register_ibs_method
def get_aidpair_tags(ibs, aid1_list, aid2_list, directed=True):
r"""
Args:
ibs (IBEISController): wbia controller object
aid1_list (list):
aid2_list (list):
directed (bool): (default = True)
Returns:
list: tags_list
CommandLine:
python -m wbia.tag_funcs --exec-get_aidpair_tags --db PZ_Master1 --tags Hard interesting
Example:
>>> # DISABLE_DOCTEST
>>> from wbia.tag_funcs import * # NOQA
>>> import wbia
>>> ibs = wbia.opendb(defaultdb='testdb1')
>>> has_any = ut.get_argval('--tags', type_=list, default=None)
>>> min_num = ut.get_argval('--min_num', type_=int, default=1)
>>> aid_pairs = filter_aidpairs_by_tags(ibs, has_any=has_any, min_num=1)
>>> aid1_list = aid_pairs.T[0]
>>> aid2_list = aid_pairs.T[1]
>>> undirected_tags = get_aidpair_tags(ibs, aid1_list, aid2_list, directed=False)
>>> tagged_pairs = list(zip(aid_pairs.tolist(), undirected_tags))
>>> print(ut.repr2(tagged_pairs))
>>> tag_dict = ut.groupby_tags(tagged_pairs, undirected_tags)
>>> print(ut.repr2(tag_dict, nl=2))
>>> print(ut.repr2(ut.map_dict_vals(len, tag_dict)))
"""
aid_pairs = np.vstack([aid1_list, aid2_list]).T
if directed:
annotmatch_rowid = ibs.get_annotmatch_rowid_from_superkey(
aid_pairs.T[0], aid_pairs.T[1]
)
tags_list = ibs.get_annotmatch_case_tags(annotmatch_rowid)
else:
annotmatch_rowid = ibs.get_annotmatch_rowid_from_undirected_superkey(
aid_pairs.T[0], aid_pairs.T[1]
)
tags_list = ibs.get_annotmatch_case_tags(annotmatch_rowid)
if False:
expanded_aid_pairs = np.vstack([aid_pairs, aid_pairs[:, ::-1]])
expanded_annotmatch_rowid = ibs.get_annotmatch_rowid_from_superkey(
expanded_aid_pairs.T[0], expanded_aid_pairs.T[1]
)
expanded_edgeids = vt.get_undirected_edge_ids(expanded_aid_pairs)
unique_edgeids, groupxs = vt.group_indices(expanded_edgeids)
expanded_tags_list = ibs.get_annotmatch_case_tags(expanded_annotmatch_rowid)
grouped_tags = vt.apply_grouping(
np.array(expanded_tags_list, dtype=object), groupxs
)
undirected_tags = [list(set(ut.flatten(tags))) for tags in grouped_tags]
edgeid2_tags = dict(zip(unique_edgeids, undirected_tags))
input_edgeids = expanded_edgeids[: len(aid_pairs)]
tags_list = ut.dict_take(edgeid2_tags, input_edgeids)
return tags_list
[docs]@register_ibs_method
def filter_aidpairs_by_tags(
ibs, has_any=None, has_all=None, min_num=None, max_num=None, am_rowids=None
):
"""
list(zip(aid_pairs, undirected_tags))
"""
# annotmatch_rowids = ibs.get_annotmatch_rowids_from_aid(aid_list)
filtered_annotmatch_rowids = filter_annotmatch_by_tags(
ibs,
am_rowids,
has_any=has_any,
has_all=has_all,
min_num=min_num,
max_num=max_num,
)
aid1_list = np.array(ibs.get_annotmatch_aid1(filtered_annotmatch_rowids))
aid2_list = np.array(ibs.get_annotmatch_aid2(filtered_annotmatch_rowids))
aid_pairs = np.vstack([aid1_list, aid2_list]).T
# Dont double count
vt.get_undirected_edge_ids(aid_pairs)
xs = vt.find_best_undirected_edge_indexes(aid_pairs)
aid1_list = aid1_list.take(xs)
aid2_list = aid2_list.take(xs)
aid_pairs = np.vstack([aid1_list, aid2_list]).T
return aid_pairs
# directed_tags = get_aidpair_tags(ibs, aid_pairs.T[0], aid_pairs.T[1], directed=True)
# valid_tags_list = ibs.get_annotmatch_case_tags(filtered_annotmatch_rowids)
[docs]def filter_annotmatch_by_tags(ibs, annotmatch_rowids=None, **kwargs):
r"""
ignores case
Args:
ibs (IBEISController): wbia controller object
flags (?):
Returns:
list
CommandLine:
python -m wbia.tag_funcs --exec-filter_annotmatch_by_tags --show
python -m wbia.tag_funcs --exec-filter_annotmatch_by_tags --show --db PZ_Master1 --min-num=1
python -m wbia.tag_funcs --exec-filter_annotmatch_by_tags --show --db PZ_Master1 --tags JoinCase
python -m wbia.tag_funcs --exec-filter_annotmatch_by_tags --show --db PZ_Master1 --tags SplitCase
python -m wbia.tag_funcs --exec-filter_annotmatch_by_tags --show --db PZ_Master1 --tags occlusion
python -m wbia.tag_funcs --exec-filter_annotmatch_by_tags --show --db PZ_Master1 --tags viewpoint
python -m wbia.tag_funcs --exec-filter_annotmatch_by_tags --show --db PZ_Master1 --tags SceneryMatch
python -m wbia.tag_funcs --exec-filter_annotmatch_by_tags --show --db PZ_Master1 --tags Photobomb
python -m wbia.tag_funcs --exec-filter_annotmatch_by_tags --show --db GZ_Master1 --tags needswork
Example:
>>> # DISABLE_DOCTEST
>>> from wbia.tag_funcs import * # NOQA
>>> import wbia
>>> #ibs = wbia.opendb(defaultdb='testdb1')
>>> ibs = wbia.opendb(defaultdb='PZ_Master1')
>>> #tags = ['Photobomb', 'SceneryMatch']
>>> has_any = ut.get_argval('--tags', type_=list, default=['SceneryMatch', 'Photobomb'])
>>> min_num = ut.get_argval('--min_num', type_=int, default=1)
>>> prop = has_any[0]
>>> filtered_annotmatch_rowids = filter_annotmatch_by_tags(ibs, None, has_any=has_any, min_num=min_num)
>>> aid1_list = np.array(ibs.get_annotmatch_aid1(filtered_annotmatch_rowids))
>>> aid2_list = np.array(ibs.get_annotmatch_aid2(filtered_annotmatch_rowids))
>>> aid_pairs = np.vstack([aid1_list, aid2_list]).T
>>> # Dont double count
>>> xs = vt.find_best_undirected_edge_indexes(aid_pairs)
>>> aid1_list = aid1_list.take(xs)
>>> aid2_list = aid2_list.take(xs)
>>> valid_tags_list = ibs.get_annotmatch_case_tags(filtered_annotmatch_rowids)
>>> print('valid_tags_list = %s' % (ut.repr2(valid_tags_list, nl=1),))
>>> #
>>> print('Aid pairs with has_any=%s' % (has_any,))
>>> print('Aid pairs with min_num=%s' % (min_num,))
>>> print('aid_pairs = ' + ut.repr2(list(zip(aid1_list, aid2_list))))
>>> # Show timedelta info
>>> ut.quit_if_noshow()
>>> timedelta_list = ibs.get_annot_pair_timedelta(aid1_list, aid2_list)
>>> import wbia.plottool as pt
>>> pt.draw_timedelta_pie(timedelta_list, label='timestamp of tags=%r' % (has_any,))
>>> ut.show_if_requested()
"""
if annotmatch_rowids is None:
annotmatch_rowids = ibs._get_all_annotmatch_rowids()
tags_list = ibs.get_annotmatch_case_tags(annotmatch_rowids)
flags = filterflags_general_tags(tags_list, **kwargs)
filtered_annotmatch_rowids = ut.compress(annotmatch_rowids, flags)
return filtered_annotmatch_rowids
# TODO: ut.filterflags_general_tags
[docs]def filterflags_general_tags(
tags_list,
has_any=None,
has_all=None,
has_none=None,
min_num=None,
max_num=None,
any_startswith=None,
any_endswith=None,
any_match=None,
none_match=None,
logic='and',
):
r"""
maybe integrate into utool? Seems pretty general
Args:
tags_list (list):
has_any (None): (default = None)
has_all (None): (default = None)
min_num (None): (default = None)
max_num (None): (default = None)
CommandLine:
python -m wbia.tag_funcs --exec-filterflags_general_tags
python -m wbia.tag_funcs --exec-filterflags_general_tags:0 --helpx
python -m wbia.tag_funcs --exec-filterflags_general_tags:0
python -m wbia.tag_funcs --exec-filterflags_general_tags:0 --none_match n
python -m wbia.tag_funcs --exec-filterflags_general_tags:0 --has_none=n,o
python -m wbia.tag_funcs --exec-filterflags_general_tags:1
python -m wbia.tag_funcs --exec-filterflags_general_tags:2
Example:
>>> # DISABLE_DOCTEST
>>> from wbia.tag_funcs import * # NOQA
>>> tags_list = [['v'], [], ['P'], ['P', 'o'], ['n', 'o',], [], ['n', 'N'], ['e', 'i', 'p', 'b', 'n'], ['q', 'v'], ['n'], ['n'], ['N']]
>>> kwargs = ut.argparse_dict(ut.get_kwdefaults2(filterflags_general_tags), type_hint=list)
>>> print('kwargs = %r' % (kwargs,))
>>> flags = filterflags_general_tags(tags_list, **kwargs)
>>> print(flags)
>>> result = ut.compress(tags_list, flags)
>>> print('result = %r' % (result,))
Example:
>>> # ENABLE_DOCTEST
>>> from wbia.tag_funcs import * # NOQA
>>> tags_list = [['v'], [], ['P'], ['P'], ['n', 'o',], [], ['n', 'N'], ['e', 'i', 'p', 'b', 'n'], ['n'], ['n'], ['N']]
>>> has_all = 'n'
>>> min_num = 1
>>> flags = filterflags_general_tags(tags_list, has_all=has_all, min_num=min_num)
>>> result = ut.compress(tags_list, flags)
>>> print('result = %r' % (result,))
Example:
>>> # DISABLE_DOCTEST
>>> from wbia.tag_funcs import * # NOQA
>>> tags_list = [['vn'], ['vn', 'no'], ['P'], ['P'], ['n', 'o',], [], ['n', 'N'], ['e', 'i', 'p', 'b', 'n'], ['n'], ['n', 'nP'], ['NP']]
>>> kwargs = {
>>> 'any_endswith': 'n',
>>> 'any_match': None,
>>> 'any_startswith': 'n',
>>> 'has_all': None,
>>> 'has_any': None,
>>> 'has_none': None,
>>> 'max_num': 3,
>>> 'min_num': 1,
>>> 'none_match': ['P'],
>>> }
>>> flags = filterflags_general_tags(tags_list, **kwargs)
>>> filtered = ut.compress(tags_list, flags)
>>> result = ('result = %s' % (ut.repr2(filtered),))
result = [['vn', 'no'], ['n', 'o'], ['n', 'N'], ['n'], ['n', 'nP']]
"""
import re
import operator
def fix_tags(tags):
return {str(t.lower()) for t in tags}
if logic is None:
logic = 'and'
logic_func = {'and': np.logical_and, 'or': np.logical_or}[logic]
default_func = {'and': np.ones, 'or': np.zeros}[logic]
tags_list_ = [fix_tags(tags_) for tags_ in tags_list]
flags = default_func(len(tags_list_), dtype=np.bool)
if min_num is not None:
flags_ = [len(tags_) >= min_num for tags_ in tags_list_]
logic_func(flags, flags_, out=flags)
if max_num is not None:
flags_ = [len(tags_) <= max_num for tags_ in tags_list_]
logic_func(flags, flags_, out=flags)
if has_any is not None:
has_any = fix_tags(set(ut.ensure_iterable(has_any)))
flags_ = [len(has_any.intersection(tags_)) > 0 for tags_ in tags_list_]
logic_func(flags, flags_, out=flags)
if has_none is not None:
has_none = fix_tags(set(ut.ensure_iterable(has_none)))
flags_ = [len(has_none.intersection(tags_)) == 0 for tags_ in tags_list_]
logic_func(flags, flags_, out=flags)
if has_all is not None:
has_all = fix_tags(set(ut.ensure_iterable(has_all)))
flags_ = [
len(has_all.intersection(tags_)) == len(has_all) for tags_ in tags_list_
]
logic_func(flags, flags_, out=flags)
def check_item(tags_, fields, op, compare):
t_flags = [any([compare(t, f) for f in fields]) for t in tags_]
num_passed = sum(t_flags)
flag = op(num_passed, 0)
return flag
def flag_tags(tags_list, fields, op, compare):
flags = [check_item(tags_, fields, op, compare) for tags_ in tags_list_]
return flags
def execute_filter(flags, tags_list, fields, op, compare):
if fields is not None:
fields = ut.ensure_iterable(fields)
flags_ = flag_tags(tags_list, fields, op, compare)
logic_func(flags, flags_, out=flags)
return flags
flags = execute_filter(flags, tags_list, any_startswith, operator.gt, str.startswith)
flags = execute_filter(flags, tags_list, any_endswith, operator.gt, str.endswith)
flags = execute_filter(
flags, tags_list, any_match, operator.gt, lambda t, f: re.match(f, t)
)
flags = execute_filter(
flags, tags_list, none_match, operator.eq, lambda t, f: re.match(f, t)
)
return flags
[docs]@register_ibs_method
@profile
def get_annotmatch_case_tags(ibs, annotmatch_rowids):
r"""
Args:
ibs (IBEISController): wbia controller object
annotmatch_rowids (?):
Returns:
list: filtered_aid_list
CommandLine:
python -m wbia.tag_funcs --exec-get_annotmatch_case_tags
Example:
>>> # DISABLE_DOCTEST
>>> from wbia.tag_funcs import * # NOQA
>>> import wbia
>>> ibs = wbia.opendb(defaultdb='PZ_Master1')
>>> annotmatch_rowids = ibs._get_all_annotmatch_rowids()
>>> tags_list = get_annotmatch_case_tags(ibs, annotmatch_rowids)
>>> result = ('tags_list = %s' % (str(tags_list),))
>>> print(result)
tags_list = [[u'occlusion', u'pose', 'Hard', 'NonDistinct'], [], ['Hard']]
"""
standard, other = get_cate_categories()
annotmatch_tag_texts_list = ibs.get_annotmatch_tag_text(annotmatch_rowids)
tags_list = [
[] if note is None else _parse_tags(note) for note in annotmatch_tag_texts_list
]
# NEW = False
# if NEW:
# # hack for faster tag parsing
# from wbia.control import _autogen_annotmatch_funcs as _aaf
# import itertools
# colnames = (_aaf.ANNOTMATCH_IS_HARD, _aaf.ANNOTMATCH_IS_SCENERYMATCH,
# _aaf.ANNOTMATCH_IS_PHOTOBOMB, _aaf.ANNOTMATCH_IS_NONDISTINCT)
# id_iter = annotmatch_rowids
# annotmatch_is_col = ibs.db.get(
# ibs.const.ANNOTMATCH_TABLE, colnames, id_iter, id_colname='rowid',
# eager=True, nInput=None, unpack_scalars=True)
# annotmatch_is_col = [col if col is not None else [None] * len(colnames)
# for col in annotmatch_is_col]
# standardtags = [x[len('annotmatch_is_'):] for x in colnames]
# standard_tags_list = ut.list_zipcompress(itertools.repeat(standardtags), annotmatch_is_col)
# tags_list = [tags1 + tags2 for tags1, tags2 in zip(tags_list, standard_tags_list)]
# else:
# for case in standard:
# flag_list = ibs.get_annotmatch_prop(case, annotmatch_rowids)
# for tags in ut.compress(tags_list, flag_list):
# tags.append(case)
tags_list = [[str(t) for t in tags] for tags in tags_list]
# if ut.get_argval('--consol') or True:
# tags_list = consolodate_annotmatch_tags(tags_list)
return tags_list
[docs]@profile
def get_annotmatch_standard_prop(ibs, prop, annotmatch_rowids):
getter = getattr(ibs, 'get_annotmatch_is_' + prop.lower())
flag_list = getter(annotmatch_rowids)
return flag_list
[docs]@register_ibs_method
@profile
def get_annotmatch_prop(ibs, prop, annotmatch_rowids):
r"""
hacky getter for dynamic properties of annotmatches using notes table
Args:
prop (str):
annotmatch_rowids (?):
Returns:
list: filtered_aid_list
CommandLine:
python -m wbia.tag_funcs --exec-get_annotmatch_prop
Example:
>>> # DISABLE_DOCTEST
>>> # Test setting and getting standard keys
>>> from wbia.tag_funcs import * # NOQA
>>> import wbia
>>> ibs = wbia.opendb(defaultdb='testdb1')
>>> prop = 'hard'
>>> annotmatch_rowids = ibs._get_all_annotmatch_rowids()
>>> flag_list = get_annotmatch_prop(ibs, prop, annotmatch_rowids)
>>> flag_list = ('filtered_aid_list = %s' % (str(flag_list),))
>>> subset_rowids = annotmatch_rowids[::2]
>>> set_annotmatch_prop(ibs, prop, subset_rowids, [True] * len(subset_rowids))
>>> flag_list2 = get_annotmatch_prop(ibs, prop, annotmatch_rowids)
>>> print('flag_list2 = %r' % (flag_list2,))
Example:
>>> # DISABLE_DOCTEST
>>> # Test setting and getting non-standard keys
>>> from wbia.tag_funcs import * # NOQA
>>> import wbia
>>> ibs = wbia.opendb(defaultdb='testdb1')
>>> prop = 'occlusion'
>>> annotmatch_rowids = ibs._get_all_annotmatch_rowids()
>>> flag_list = get_annotmatch_prop(ibs, prop, annotmatch_rowids)
>>> flag_list = ('filtered_aid_list = %s' % (str(flag_list),))
>>> subset_rowids = annotmatch_rowids[1::2]
>>> subset_rowids1 = annotmatch_rowids[::2]
>>> set_annotmatch_prop(ibs, prop, subset_rowids1, [True] * len(subset_rowids))
>>> set_annotmatch_prop(ibs, 'pose', subset_rowids1, [True] * len(subset_rowids))
>>> flag_list2 = get_annotmatch_prop(ibs, prop, annotmatch_rowids)
>>> print('flag_list2 = %r' % (flag_list2,))
"""
# if prop.lower() in ANNOTMATCH_PROPS_STANDARD_SET:
# return ibs.get_annotmatch_standard_prop(prop, annotmatch_rowids)
for prop_ in ut.ensure_iterable(prop):
flag1 = prop_.lower() not in ANNOTMATCH_PROPS_OTHER_SET
flag2 = prop_.lower() not in ANNOTMATCH_PROPS_OLD_SET
if flag1 and flag2:
raise NotImplementedError('Unknown prop_=%r' % (prop_,))
return get_annotmatch_other_prop(ibs, prop, annotmatch_rowids)
[docs]@register_ibs_method
def set_annotmatch_prop(ibs, prop, annotmatch_rowids, flags):
"""
hacky setter for dynamic properties of annotmatches using notes table
"""
logger.info(
'[ibs] set_annotmatch_prop prop=%s for %d pairs' % (prop, len(annotmatch_rowids))
)
# if prop.lower() in ANNOTMATCH_PROPS_STANDARD_SET:
# setter = getattr(ibs, 'set_annotmatch_is_' + prop.lower())
# return setter(annotmatch_rowids, flags)
if (
prop.lower() in ANNOTMATCH_PROPS_OTHER_SET
or prop.lower() in ANNOTMATCH_PROPS_OLD_SET
):
return set_annotmatch_other_prop(ibs, prop, annotmatch_rowids, flags)
else:
raise NotImplementedError(
'Unknown prop=%r not in %r' % (prop, ANNOTMATCH_PROPS_OTHER_SET)
)
def _parse_tags(note):
"""convert a note into tags"""
return [tag.strip() for tag in note.split(';') if len(tag) > 0]
def _remove_tag(tags, prop):
"""convert a note into tags"""
try:
tags.remove(prop)
except ValueError:
pass
return tags
[docs]@profile
def get_annotmatch_other_prop(ibs, prop, annotmatch_rowids):
annotmatch_tag_texts_list = ibs.get_annotmatch_tag_text(annotmatch_rowids)
flag_list = get_textformat_tag_flags(prop, annotmatch_tag_texts_list)
return flag_list
[docs]def set_annotmatch_other_prop(ibs, prop, annotmatch_rowids, flags):
"""
sets nonstandard properties using the notes column
"""
annotmatch_tag_texts_list = ibs.get_annotmatch_tag_text(annotmatch_rowids)
new_notes_list = set_textformat_tag_flags(prop, annotmatch_tag_texts_list, flags)
ibs.set_annotmatch_tag_text(annotmatch_rowids, new_notes_list)
[docs]@profile
def get_textformat_tag_flags(prop, text_list):
"""general text tag getter hack"""
tags_list = [None if note is None else _parse_tags(note) for note in text_list]
if ut.isiterable(prop):
props_ = [p.lower() for p in prop]
flags_list = [
[None if tags is None else int(prop_ in tags) for tags in tags_list]
for prop_ in props_
]
return flags_list
else:
prop = prop.lower()
flag_list = [None if tags is None else int(prop in tags) for tags in tags_list]
return flag_list
[docs]def set_textformat_tag_flags(prop, text_list, flags):
"""general text tag setter hack"""
prop = prop.lower()
ensured_text = ['' if note is None else note for note in text_list]
tags_list = [_parse_tags(note) for note in ensured_text]
# Remove from all
new_tags_list = [_remove_tag(tags, prop) for tags in tags_list]
# then add to specified ones
for tags, flag in zip(new_tags_list, flags):
if flag:
tags.append(prop)
new_text_list = [';'.join(tags) for tags in new_tags_list]
return new_text_list
ANNOT_TAGS = [
'occlusion',
'lighting',
'quality',
'pose',
'error',
'interesting',
'error:viewpoint',
'error:quality',
'occlusion:large',
'occlusion:medium',
'occlusion:small',
'lighting:shadowed',
'lighting:overexposed',
'lighting:underexposed',
'quality:washedout',
'quality:blury',
'pose:novel',
'pose:common',
'error:bbox',
'error:mask',
'error:other',
]
[docs]def get_annot_prop(ibs, prop, aid_list):
"""
Annot tags
"""
text_list = ibs.get_annot_tag_text(aid_list)
flag_list = get_textformat_tag_flags(prop, text_list)
return flag_list
[docs]@register_ibs_method
def set_annot_prop(ibs, prop, aid_list, flags):
"""
sets nonstandard properties using the notes column
"""
text_list = ibs.get_annot_tag_text(aid_list)
new_text_list = set_textformat_tag_flags(prop, text_list, flags)
ibs.set_annot_tag_text(aid_list, new_text_list)
[docs]@register_ibs_method
def append_annot_case_tags(ibs, aid_list, tag_list):
"""
Generally appends tags to annotations. Careful not to introduce too many
random tags. Maybe we should just let that happen and introduce tag-aliases
Note: this is more of a set add rather than a list append
TODO: remove
"""
# Ensure each item is a list
# tags_list = [tag if isinstance(tag, list) else [tag] for tag in tag_list]
if isinstance(tag_list, str):
# Apply single tag to everybody
tag_list = [tag_list] * len(aid_list)
tags_list = [ut.ensure_iterable(tag) for tag in tag_list]
text_list = ibs.get_annot_tag_text(aid_list)
orig_tags_list = [[] if note is None else _parse_tags(note) for note in text_list]
new_tags_list = [ut.unique(t1 + t2) for t1, t2 in zip(tags_list, orig_tags_list)]
ibs.set_annot_case_tags(aid_list, new_tags_list)
[docs]@register_ibs_method
def set_annot_case_tags(ibs, aid_list, new_tags_list):
"""
Completely overwrite case tags
"""
for tag in new_tags_list:
assert isinstance(tag, list), 'each set of tags must be a list of strs'
new_text_list = [';'.join(tags) for tags in new_tags_list]
ibs.set_annot_tag_text(aid_list, new_text_list)
[docs]@register_ibs_method
def remove_annot_case_tags(ibs, aid_list, tag_list):
if isinstance(tag_list, str):
# Apply single tag to everybody
tag_list = [tag_list] * len(aid_list)
tags_list = [ut.ensure_iterable(tag) for tag in tag_list]
text_list = ibs.get_annot_tag_text(aid_list)
orig_tags_list = [[] if note is None else _parse_tags(note) for note in text_list]
new_tags_list = [ut.setdiff(t2, t1) for t1, t2 in zip(tags_list, orig_tags_list)]
new_text_list = [';'.join(tags) for tags in new_tags_list]
ibs.set_annot_tag_text(aid_list, new_text_list)
[docs]@register_ibs_method
def overwrite_annot_case_tags(ibs, aid_list, tag_list):
"""
Completely replaces annotation tags.
BE VERY CAREFUL WITH THIS FUNCTION
"""
assert all([ut.isiterable(tag) for tag in tag_list])
# text_list = ibs.get_annot_tag_text(aid_list)
# orig_tags_list = [[] if note is None else _parse_tags(note) for note in text_list]
new_tags_list = tag_list
new_text_list = [';'.join(tags) for tags in new_tags_list]
ibs.set_annot_tag_text(aid_list, new_text_list)
[docs]@register_ibs_method
def remove_all_annot_case_tags(ibs, aid_list):
ibs.set_annot_tag_text(aid_list, [''] * len(aid_list))
[docs]@register_ibs_method
def get_annot_case_tags(ibs, aid_list):
r"""
returns list of tags. Use instead of get_annot_tag_text
TODO:
rename to get_annot_unary_tags
Args:
ibs (IBEISController): wbia controller object
aid_list (list): list of annotation rowids
Returns:
list: tags_list
CommandLine:
python -m wbia.tag_funcs --exec-get_annot_case_tags
Example:
>>> # ENABLE_DOCTEST
>>> from wbia.tag_funcs import * # NOQA
>>> from wbia.tag_funcs import _parse_tags # NOQA
>>> import wbia
>>> ibs = wbia.opendb(defaultdb='testdb1')
>>> aid_list = ibs.get_valid_aids()
>>> tags_list = get_annot_case_tags(ibs, aid_list)
>>> result = ('tags_list = %s' % (str(tags_list),))
>>> print(result)
Ignore:
# FIXME incorrporate old tag notes
aid_list = ibs.get_valid_aids()
notes_list = ibs.get_annot_notes(aid_list)
flags = [len(notes) > 0 for notes in notes_list]
aid_list = ut.compress(aid_list, flags)
notes_list = ut.compress(notes_list, flags)
import re
notes_list = [note.replace('rfdetect', '') for note in notes_list]
notes_list = [note.replace('<COMMA>', ';') for note in notes_list]
notes_list = [note.replace('jpg', '') for note in notes_list]
notes_list = [note.replace('<HARDCASE>', '') for note in notes_list]
notes_list = [note.strip() for note in notes_list]
notes_list = [re.sub(';;*', ';', note) for note in notes_list]
notes_list = [note.strip(';') for note in notes_list]
notes_list = [note.strip(':') for note in notes_list]
notes_list = [note.strip() for note in notes_list]
flags = [len(notes) < 70 and len(notes) > 0 for notes in notes_list]
aid_list = ut.compress(aid_list, flags)
notes_list = ut.compress(notes_list, flags)
flags = ['M;' not in notes and 'F;' not in notes and 'H1' not in notes for notes in notes_list]
flags = [ 'M;' not in notes and 'F;' not in notes and 'H1' not in notes for notes in notes_list]
aid_list = ut.compress(aid_list, flags)
notes_list = ut.compress(notes_list, flags)
flags = ['aliases' not in notes for notes in notes_list]
aid_list = ut.compress(aid_list, flags)
notes_list = ut.compress(notes_list, flags)
#flags = [not re.match(';\d*;', note) for note in notes_list]
flags = [not re.match(r'\d\d*', note) for note in notes_list]
aid_list = ut.compress(aid_list, flags)
notes_list = ut.compress(notes_list, flags)
flags = [not notes.startswith('Foal;') for notes in notes_list]
aid_list = ut.compress(aid_list, flags)
notes_list = ut.compress(notes_list, flags)
old_tags_list = [_parse_tags(note) for note in notes_list]
old_tags = list(set(ut.flatten(old_tags_list)))
old_tags = sorted([tag for tag in old_tags if not re.match(r'\d\d*', tag)])
old_to_new = {
'gash': None,
'pose': 'novelpose',
'vocalizing': 'novelpose'
'occlusion': 'occlusion',
}
Ignore:
python -m wbia.tag_funcs --exec-filter_annotmatch_by_tags --show --db PZ_Master1 --tags viewpoint
"""
text_list = ibs.get_annot_tag_text(aid_list)
tags_list = [[] if note is None else _parse_tags(note) for note in text_list]
return tags_list
[docs]@register_ibs_method
@profile
def get_annot_annotmatch_tags(ibs, aid_list):
r"""
Args:
ibs (IBEISController): wbia controller object
aid_list (list): list of annotation rowids
Returns:
list: annotmatch_tags_list
CommandLine:
python -m wbia.tag_funcs --exec-get_annot_annotmatch_tags --db GZ_Master1
Example:
>>> # ENABLE_DOCTEST
>>> from wbia.tag_funcs import * # NOQA
>>> import wbia
>>> ibs = wbia.opendb(defaultdb='testdb1')
>>> aid_list = ibs.get_valid_aids()
>>> all_tags = ut.flatten(get_annot_annotmatch_tags(ibs, aid_list))
>>> tag_hist = ut.dict_hist(all_tags)
>>> ut.print_dict(tag_hist)
"""
annotmatch_rowids = ibs.get_annotmatch_rowids_from_aid(aid_list)
unflat_tags_list = ibs.unflat_map(ibs.get_annotmatch_case_tags, annotmatch_rowids)
annotmatch_tags_list = [
list(set(ut.flatten(_unflat_tags))) for _unflat_tags in unflat_tags_list
]
return annotmatch_tags_list
[docs]@register_ibs_method
@profile
def get_annot_all_tags(ibs, aid_list=None):
"""
CommandLine:
python -m wbia.tag_funcs --exec-get_annot_all_tags --db GZ_Master1
Example:
>>> # ENABLE_DOCTEST
>>> from wbia.tag_funcs import * # NOQA
>>> import wbia
>>> ibs = wbia.opendb(defaultdb='testdb1')
>>> aid_list = ibs.get_valid_aids()
>>> all_tags = ut.flatten(ibs.get_annot_all_tags(aid_list))
>>> tag_hist = ut.dict_hist(all_tags)
>>> ut.print_dict(tag_hist)
"""
if aid_list is None:
aid_list = ibs.get_valid_aids()
annotmatch_tags_list = ibs.get_annot_annotmatch_tags(aid_list)
annot_tags_list = ibs.get_annot_case_tags(aid_list)
both_tags_list = list(
map(
ut.unique_ordered,
map(ut.flatten, zip(annot_tags_list, annotmatch_tags_list)),
)
)
return both_tags_list