Source code for wbia.annots

# -*- coding: utf-8 -*-
import logging
import utool as ut
import itertools as it
from wbia import _wbia_object
from wbia.control.controller_inject import make_ibs_register_decorator
import six

(print, rrr, profile) = ut.inject2(__name__, '[annot]')
logger = logging.getLogger('wbia')

CLASS_INJECT_KEY, register_ibs_method = make_ibs_register_decorator(__name__)


BASE_TYPE = type


[docs]@register_ibs_method def annots(ibs, aids=None, uuids=None, **kwargs): """Makes an Annots object""" if uuids is not None: assert aids is None, 'specify one primary key' aids = ibs.get_annot_aids_from_uuid(uuids) if aids is None: aids = ibs.get_valid_aids() elif aids.__class__.__name__ == 'Annots': return aids aids = ut.ensure_iterable(aids) return Annots(aids, ibs, **kwargs)
[docs]@register_ibs_method def matches(ibs, ams=None, edges=None, uuid_edges=None, **kwargs): """Makes an Annots object""" if uuid_edges is not None: assert ams is None, 'specify one primary key' assert edges is None, 'specify one primary key' uuids1, uuids2 = list(zip(*uuid_edges)) aids1 = ibs.get_annot_aids_from_uuid(uuids1) aids2 = ibs.get_annot_aids_from_uuid(uuids2) ams = ibs.get_annotmatch_rowid_from_undirected_superkey(aids1, aids2) if edges is not None: assert ams is None, 'specify one primary key' assert uuid_edges is None, 'specify one primary key' aids1, aids2 = list(zip(*edges)) ams = ibs.get_annotmatch_rowid_from_undirected_superkey(aids1, aids2) if ams is None: ams = ibs._get_all_annotmatch_rowids() elif ams.__class__.__name__ == 'AnnotMatches': return ams ams = ut.ensure_iterable(ams) return AnnotMatches(ams, ibs, **kwargs)
@register_ibs_method def _annot_groups(ibs, aids_list=None, config=None): annots_list = [ibs.annots(aids, config=config) for aids in aids_list] return AnnotGroups(annots_list, ibs) ANNOT_BASE_ATTRS = [ 'aid', 'parent_aid', 'multiple', 'age_months_est_max', 'age_months_est_min', 'sex', 'sex_texts', 'uuids', 'hashid_uuid', 'visual_uuids', 'hashid_visual_uuid', 'semantic_uuids', 'hashid_semantic_uuid', 'verts', 'thetas', 'bboxes', 'bbox_area', 'species_uuids', 'species', 'species_rowids', 'species_texts', 'viewpoint_int', 'viewpoint_code', 'qualities', 'quality_texts', 'exemplar_flags', # DEPRICATE YAW 'yaw_texts', 'yaws', 'yaws_asfloat', # Images # 'image_rowids', 'gids', 'image_uuids', 'image_gps', 'image_gps2', 'image_unixtimes_asfloat', 'image_datetime_str', 'image_contributor_tag', # Names 'nids', 'names', 'name_uuids', # Inferred from context attrs 'contact_aids', 'num_contact_aids', 'groundfalse', 'groundtruth', 'num_groundtruth', 'has_groundtruth', 'otherimage_aids', # Image Set 'imgset_uuids', 'imgsetids', 'image_set_texts', # Occurrence / Encounter 'static_encounter', 'encounter_text', 'occurrence_text', 'primary_imageset', # Tags 'all_tags', 'case_tags', 'annotmatch_tags', 'notes', # Processing State 'reviewed', 'reviewed_matching_aids', 'has_reviewed_matching_aids', 'num_reviewed_matching_aids', 'detect_confidence', ] ANNOT_SETTABLE_ATTRS = [ 'age_months_est_max', 'age_months_est_min', 'bboxes', 'thetas', 'verts', 'qualities', 'quality_texts', 'viewpoint_int', 'viewpoint_code', # DEPRICATE YAW 'yaw_texts', 'yaws', 'sex', 'sex_texts', 'species', 'exemplar_flags', 'static_encounter', 'multiple', 'case_tags', 'detect_confidence', 'reviewed', 'name_texts', 'names', 'notes', 'parent_rowid', ] class _AnnotPropInjector(BASE_TYPE): """ Ignore: >>> from wbia import _wbia_object >>> import wbia >>> ibs = wbia.opendb(defaultdb='testdb1') >>> objname = 'annot' >>> blacklist = ['annot_pair'] >>> _wbia_object._find_wbia_attrs(ibs, objname, blacklist) """ def __init__(metaself, name, bases, dct): super(_AnnotPropInjector, metaself).__init__(name, bases, dct) metaself.rrr = rrr attrs = ANNOT_BASE_ATTRS settable_attrs = ANNOT_SETTABLE_ATTRS configurable_attrs = [ # Chip 'chip_dlensqrd', 'chip_fpath', 'chip_sizes', 'chip_thumbpath', 'chip_thumbtup', 'chips', # Feat / FeatWeight / Kpts / Desc 'feat_rowids', 'num_feats', 'featweight_rowids', 'fgweights', 'fgweights_subset', 'kpts', 'kpts_distinctiveness', 'vecs', 'vecs_cache', 'vecs_subset', ] # misc = [ # 'gar_rowids', 'alrids', 'alrids_oftype', 'lblannot_rowids', # 'lblannot_rowids_oftype', 'lblannot_value_of_lbltype', 'rows', # 'instancelist', 'lazy_dict', 'lazy_dict2', 'missing_uuid', # 'been_adjusted', 'class_labels', # ] # extra_attrs = [ # # Age / Sex # 'age_months_est', 'age_months_est_max', 'age_months_est_max_texts', # 'age_months_est_min', 'age_months_est_min_texts', # 'age_months_est_texts', 'sex', 'sex_texts', # # Stats # 'stats_dict', 'per_name_stats', 'qual_stats', 'info', 'yaw_stats', # 'intermediate_viewpoint_stats', # ] # inverse_attrs = [ # # External lookups via superkeys # 'aids_from_semantic_uuid', # 'aids_from_uuid', # 'aids_from_visual_uuid', # 'rowids_from_partial_vuuids', # ] depcache_attrs = [ ('hog', 'hog'), ('probchip', 'img'), ] aliased_attrs = { 'time': 'image_unixtimes_asfloat', 'gps': 'image_gps2', 'chip_size': 'chip_sizes', 'yaw': 'yaws_asfloat', 'qual': 'qualities', 'name': 'names', 'nid': 'nids', 'unary_tags': 'case_tags', # DEPRICATE 'rchip': 'chips', 'rchip_fpath': 'chip_fpath', } objname = 'annot' _wbia_object._inject_getter_attrs( metaself, objname, attrs, configurable_attrs, 'depc_annot', depcache_attrs, settable_attrs, aliased_attrs, ) # TODO: incorporate dynamic setters # def set_case_tags(self, tags): # self._ibs.append_annot_case_tags(self._rowids, tags) # fget = metaself.case_tags.fget # fset = set_case_tags # setattr(metaself, 'case_tags', property(fget, fset)) try: from wbia import _autogen_annot_base BASE = _autogen_annot_base._annot_base_class except ImportError: BASE = _wbia_object.ObjectList1D # @ut.reloadable_class
[docs]@six.add_metaclass(_AnnotPropInjector) class Annots(BASE): """ Represents a group of annotations. Efficiently accesses properties from a database using lazy evaluation. CommandLine: python -m wbia.annots Annots Example: >>> # ENABLE_DOCTEST >>> from wbia.annots import * # NOQA >>> import wbia >>> ibs = wbia.opendb(defaultdb='testdb1') >>> aids = ibs.get_valid_aids() >>> a = self = annots = Annots(aids, ibs) >>> a.preload('vecs', 'kpts', 'nids') >>> print(Annots.mro()) >>> print(ut.depth_profile(a.vecs)) >>> print(a) Example: >>> # ENABLE_DOCTEST >>> from wbia.annots import * # NOQA >>> import wbia >>> ibs = wbia.opendb(defaultdb='testdb1') >>> aids = ibs.get_valid_aids() >>> a = self = annots = Annots(aids, ibs) >>> a.preload('vecs', 'kpts', 'nids') >>> a.disconnect() >>> assert 'vecs' in a._internal_attrs.keys() >>> assert a._ibs is None >>> ut.assert_raises(KeyError, a._get_num_feats) >>> a._ibs = ibs >>> assert len(a._get_num_feats()) > 0 """ # def __init__(self, aids, ibs, config=None, caching=False): # super(Annots, self).__init__(aids, ibs, config, caching) @property def aids(self): return self._rowids
[docs] def get_stats(self, **kwargs): self._ibs.get_annot_stats_dict(self.aids, **kwargs)
[docs] def print_stats(self, **kwargs): self._ibs.print_annot_stats(self.aids, **kwargs)
# @property
[docs] def get_speeds(self): # import vtool as vt edges = self.get_aidpairs() speeds = self._ibs.get_annotpair_speeds(edges) # edges = vt.pdist_indicies(len(annots)) # speeds = self._ibs.get_unflat_annots_speeds_list([self.aids])[0] edge_to_speed = dict(zip(edges, speeds)) return edge_to_speed
[docs] def get_name_image_closure(self): ibs = self._ibs aids = self.aids old_aids = [] while len(old_aids) != len(aids): old_aids = aids gids = ut.unique(ibs.get_annot_gids(aids)) other_aids = list(set(ut.flatten(ibs.get_image_aids(gids)))) other_nids = list(set(ibs.get_annot_nids(other_aids))) aids = ut.flatten(ibs.get_name_aids(other_nids)) return aids
[docs] def group2(self, by): """ self = annots by = annots.static_encounter encounters = annots.group2(annots.static_encounter) """ annots_list = self.group(by)[1] return AnnotGroups(annots_list, self._ibs)
[docs] def get_aidpairs(self): aids = self.aids aid_pairs = list(it.combinations(aids, 2)) return aid_pairs
[docs] def get_am_rowids(self, internal=True): """ if `internal is True` returns am rowids only between annotations in this Annots object, otherwise returns any am rowid that contains any aid in this Annots object. """ ibs = self._ibs if internal: ams = ibs.get_annotmatch_rowids_between(self.aids, self.aids) else: ams = ut.flatten(ibs.get_annotmatch_rowids_from_aid(self.aids)) return ams
[docs] def matches(self, internal=True): ams = self.get_am_rowids(internal) return self._ibs.matches(ams)
[docs] def get_am_rowids_and_pairs(self): ibs = self._ibs ams = self.get_am_rowids() aid_pairs = ibs.get_annotmatch_aids(ams) # aid_pairs = self.get_aidpairs() # aids1 = ut.take_column(aid_pairs, 0) # aids2 = ut.take_column(aid_pairs, 1) # ams = ibs.get_annotmatch_rowid_from_undirected_superkey(aids1, aids2) # flags = ut.not_list(ut.flag_None_items(ams)) # ams = ut.compress(ams, flags) # aid_pairs = ut.compress(aid_pairs, flags) return ams, aid_pairs
[docs] def get_am_aidpairs(self): ibs = self._ibs ams = self.get_am_rowids() aids1 = ibs.get_annotmatch_aid1(ams) aids2 = ibs.get_annotmatch_aid2(ams) aid_pairs = list(zip(aids1, aids2)) return aid_pairs
@property def hog_img(self): from wbia import core_annots return [core_annots.make_hog_block_image(hog) for hog in self.hog_hog]
[docs] def append_tags(self, tags): self._ibs.append_annot_case_tags(self._rowids, tags)
[docs] def remove_tags(self, tags): self._ibs.remove_annot_case_tags(self._rowids, tags)
def __hash__(self): return hash(tuple(self.aids)) def __lt__(self, other): if len(self.aids) == len(other.aids): if len(self.aids) == 0: return False else: return tuple(self) < tuple(other) elif len(self.aids) < len(other.aids): return True else: return False def __eq__(self, other): if len(self.aids) == len(other.aids): return all(a == b for a, b in zip(self, other)) return False
[docs] def show(self, *args, **kwargs): if len(self) != 1: raise ValueError('Can only show one, got {}'.format(len(self))) from wbia.viz import viz_chip for aid in self: return viz_chip.show_chip(self._ibs, aid, *args, **kwargs)
class _AnnotGroupPropInjector(BASE_TYPE): def __init__(metaself, name, bases, dct): super(_AnnotGroupPropInjector, metaself).__init__(name, bases, dct) metaself.rrr = rrr # TODO: move to wbia object as a group call def _make_unflat_getter(objname, attrname): ibs_funcname = 'get_%s_%s' % (objname, attrname) def ibs_unflat_getter(self, *args, **kwargs): ibs_callable = getattr(self._ibs, ibs_funcname) rowids = self._rowids_list ibs = self._ibs return ibs.unflat_map(ibs_callable, rowids, *args, **kwargs) ut.set_funcname(ibs_unflat_getter, 'unflat_' + ibs_funcname) return ibs_unflat_getter for attrname in ANNOT_BASE_ATTRS: if hasattr(metaself, attrname): logger.info('Cannot inject annot group attrname = %r' % (attrname,)) continue ibs_unflat_getter = _make_unflat_getter('annot', attrname) setattr(metaself, '_unflat_get_' + attrname, ibs_unflat_getter) setattr(metaself, attrname, property(ibs_unflat_getter))
[docs]@ut.reloadable_class @six.add_metaclass(_AnnotGroupPropInjector) class AnnotGroups(ut.NiceRepr): """Effciently handle operations on multiple groups of annotations""" def __init__(self, annots_list, ibs): self._ibs = ibs self.annots_list = annots_list self._rowids_list = [a._rowids for a in self.annots_list] def __len__(self): return len(self.annots_list) def __nice__(self): import numpy as np len_list = ut.lmap(len, self.annots_list) num = len(self.annots_list) mean = np.mean(len_list) std = np.std(len_list) nice = '(n=%r, μ=%.1f, σ=%.1f)' % (num, mean, std) return nice def __iter__(self): return iter(self.annots_list) def __getitem__(self, index): return self.annots_list[index] @property def aids(self): return [a.aids for a in self.annots_list] @property def images(self, config=None): return self._ibs.images(self.gids, config) @property def match_tags(self): """returns pairwise tags within the annotation group""" ams_list = self._ibs.get_unflat_am_rowids(self.aids) tags = self._ibs.unflat_map(self._ibs.get_annotmatch_case_tags, ams_list) return tags
class _AnnotMatchPropInjector(BASE_TYPE): """ Example: >>> # DISABLE_DOCTEST >>> from wbia import _wbia_object >>> import wbia >>> ibs = wbia.opendb(defaultdb='testdb1') >>> objname = 'annotmatch' >>> blacklist = [] >>> tup = _wbia_object._find_wbia_attrs(ibs, objname, blacklist) >>> attrs, settable_attrs = tup >>> print('attrs = ' + ut.repr4(attrs)) >>> print('settable_attrs = ' + ut.repr4(settable_attrs)) """ def __init__(metaself, name, bases, dct): super(_AnnotMatchPropInjector, metaself).__init__(name, bases, dct) metaself.rrr = rrr attrs = [ 'aid1', 'aid2', 'confidence', 'count', 'evidence_decision', 'meta_decision', 'posixtime_modified', 'reviewer', 'tag_text', 'case_tags', ] settable_attrs = [ 'confidence', 'count', 'evidence_decision', 'meta_decision', 'posixtime_modified', 'reviewer', 'tag_text', ] configurable_attrs = [] depcache_attrs = [] aliased_attrs = {} objname = 'annotmatch' _wbia_object._inject_getter_attrs( metaself, objname, attrs, configurable_attrs, None, depcache_attrs, settable_attrs, aliased_attrs, )
[docs]@six.add_metaclass(_AnnotMatchPropInjector) class AnnotMatches(BASE): """ Represents a group of annotations. Efficiently accesses properties from a database using lazy evaluation. CommandLine: python -m wbia.annots Annots Example: >>> # ENABLE_DOCTEST >>> from wbia.annots import * # NOQA >>> import wbia >>> ibs = wbia.opendb(defaultdb='testdb1') >>> aids = ibs.get_valid_aids() >>> annots = Annots(aids, ibs) >>> ams = annots.get_am_rowids() >>> matches = self = ibs.matches() >>> ed1 = matches.evidence_decision >>> md2 = matches.meta_decision >>> table = ibs.db.get_table_as_pandas('annotmatch') >>> assert len(table) == len(matches) """ @property def edges(self): return list(zip(self.aid1, self.aid2)) @property def confidence_code(self): INT_TO_CODE = self._ibs.const.CONFIDENCE.INT_TO_CODE return [INT_TO_CODE[c] for c in self.confidence] @property def meta_decision_code(self): INT_TO_CODE = self._ibs.const.META_DECISION.INT_TO_CODE return [INT_TO_CODE[c] for c in self.meta_decision] @property def evidence_decision_code(self): INT_TO_CODE = self._ibs.const.EVIDENCE_DECISION.INT_TO_CODE return [INT_TO_CODE[c] for c in self.evidence_decision]