# -*- coding: utf-8 -*-
"""
DEPRICATE FOR CORE ANNOT AND CORE IMAGE DEFS
"""
from __future__ import absolute_import, division, print_function
import utool as ut
import six
import copy
#import dtool
from os.path import join
from os.path import splitext
from six.moves import zip, map, range, filter # NOQA
from ibeis import constants as const
from utool._internal.meta_util_six import get_funcname
(print, rrr, profile) = ut.inject2(__name__, '[cfg]')
#ConfigBase = ut.DynStruct
#ConfigBase = object
ConfigBase = ut.Pref
[docs]def parse_config_items(cfg):
"""
Recursively extracts key, val pairs from Config objects
into a flat list. (there must not be name conflicts)
Example:
>>> # ENABLE_DOCTEST
>>> from ibeis.algo.Config import * # NOQA
>>> import ibeis
>>> ibs = ibeis.opendb('testdb1')
>>> cfg = ibs.cfg.query_cfg
>>> param_list = parse_config_items(cfg)
"""
import ibeis
param_list = []
seen = set([])
for item in cfg.items():
key, val = item
if isinstance(val, ibeis.algo.Config.ConfigBase):
child_cfg = val
param_list.extend(parse_config_items(child_cfg))
#print(key)
pass
elif key.startswith('_'):
#print(key)
pass
else:
if key in seen:
print('[Config] WARNING: key=%r appears more than once' %
(key,))
seen.add(key)
param_list.append(item)
#print(key)
return param_list
ConfigMetaclass = make_config_metaclass()
@six.add_metaclass(ConfigMetaclass)
[docs]class GenericConfig(ConfigBase):
def __init__(cfg, *args, **kwargs):
super(GenericConfig, cfg).__init__(*args, **kwargs)
@six.add_metaclass(ConfigMetaclass)
[docs]class NNConfig(ConfigBase):
r"""
CommandLine:
python -m ibeis.algo.Config --exec-NNConfig
Example:
>>> # DISABLE_DOCTEST
>>> from ibeis.algo.Config import * # NOQA
>>> nn_cfg = NNConfig()
>>> nn_cfg = NNConfig(single_name_condition=True)
>>> result = nn_cfg.get_cfgstr()
>>> print(result)
_NN(single,K=4,Kn=1,padk=False,cks800)
"""
def __init__(nn_cfg, **kwargs):
super(NNConfig, nn_cfg).__init__()
#if True:
nn_cfg.initialize_params()
#else:
# nn_cfg.K = 4
# # TODO: force to false when in vsone
# nn_cfg.use_k_padding = False
# # number of annots before a new multi-indexer is built
# #nn_cfg.min_reindex_thresh = 3
# #nn_cfg.index_method = 'multi'
# nn_cfg.index_method = 'single'
# nn_cfg.Knorm = 1
# nn_cfg.checks = 800
# number of annots before a new multi-indexer is built
nn_cfg.min_reindex_thresh = 200
# number of annots before a new multi-indexer is built
nn_cfg.max_subindexers = 2
nn_cfg.valid_index_methods = ['single', 'multi', 'name']
nn_cfg.update(**kwargs)
[docs] def make_feasible(nn_cfg):
# normalizer rule depends on Knorm
assert nn_cfg.index_method in nn_cfg.valid_index_methods
[docs] def get_param_info_list(rrvsone_cfg):
# new way to try and specify config options.
# not sure if i like it yet
param_info_list = ut.flatten([
[
ut.ParamInfo('index_method', 'single', ''),
ut.ParamInfo('K', 4, type_=int),
ut.ParamInfo('Knorm', 1, 'Kn='),
ut.ParamInfo('use_k_padding', False, 'padk='),
ut.ParamInfo('single_name_condition', False, 'nameknn', type_=bool, hideif=False),
ut.ParamInfo('checks', 800, 'cks', type_=int),
#ut.ParamInfo('ratio_thresh', None, type_=float, hideif=None),
],
])
return param_info_list
@six.add_metaclass(ConfigMetaclass)
[docs]class SpatialVerifyConfig(ConfigBase):
"""
Spatial verification
"""
def __init__(sv_cfg, **kwargs):
super(SpatialVerifyConfig, sv_cfg).__init__(name='sv_cfg')
tau = 6.28 # 318530
sv_cfg.sv_on = True
sv_cfg.xy_thresh = .01
sv_cfg.scale_thresh = 2.0
sv_cfg.ori_thresh = tau / 4.0
sv_cfg.min_nInliers = 4
sv_cfg.full_homog_checks = True
sv_cfg.nNameShortlistSVER = 50
sv_cfg.nAnnotPerNameSVER = 6
#sv_cfg.prescore_method = 'csum'
sv_cfg.prescore_method = 'nsum'
sv_cfg.use_chip_extent = True # BAD CONFIG?
# weight feature scores with sver errors
sv_cfg.sver_output_weighting = False
sv_cfg.refine_method = 'homog'
# weight feature scores with sver errors
sv_cfg.weight_inliers = True
sv_cfg.update(**kwargs)
[docs] def get_cfgstr_list(sv_cfg, **kwargs):
if not sv_cfg.sv_on or sv_cfg.xy_thresh is None:
return ['_SV(OFF)']
thresh_tup = (sv_cfg.xy_thresh, sv_cfg.scale_thresh, sv_cfg.ori_thresh)
thresh_str = ut.remove_chars(str(thresh_tup), ' ()').replace(',', ';')
sv_cfgstr = [
'_SV(',
thresh_str,
'minIn=%d,' % (sv_cfg.min_nInliers,),
'nNRR=%d,' % (sv_cfg.nNameShortlistSVER,),
'nARR=%d,' % (sv_cfg.nAnnotPerNameSVER,),
sv_cfg.prescore_method, ',',
'cdl,' * sv_cfg.use_chip_extent, # chip diag len
'+ow,' * sv_cfg.sver_output_weighting, # chip diag len
'+wi,' * sv_cfg.weight_inliers, # chip diag len
'+fc,' * sv_cfg.full_homog_checks,
]
if sv_cfg.refine_method != 'homog':
sv_cfgstr += [sv_cfg.refine_method]
sv_cfgstr += [
')',
]
return sv_cfgstr
@six.add_metaclass(ConfigMetaclass)
[docs]class AggregateConfig(ConfigBase):
"""
Old Agg Cfg
"""
def __init__(agg_cfg, **kwargs):
super(AggregateConfig, agg_cfg).__init__(name='agg_cfg')
# chipsum, namesum, placketluce
#agg_cfg.score_method = 'csum'
agg_cfg.score_method = 'nsum'
agg_cfg.score_normalization = None
agg_cfg.normsum = False
#agg_cfg.score_normalization = True
alt_methods = {
'topk': 'topk',
'borda': 'borda',
'placketluce': 'pl',
'chipsum': 'csum',
'namesum': 'nsum',
'coverage': 'coverage',
}
# For Placket-Luce
agg_cfg.max_alts = 50
#-----
# User update
agg_cfg.update(**kwargs)
# ---
key = agg_cfg.score_method.lower()
# Use w as a toggle for weighted mode
# Sanatize the scoring method
if key in alt_methods:
agg_cfg.score_method = alt_methods[key]
[docs] def get_cfgstr_list(agg_cfg, **kwargs):
agg_cfgstr = []
agg_cfgstr.append('_AGG(')
agg_cfgstr.append(agg_cfg.score_method)
if agg_cfg.score_method == 'pl':
agg_cfgstr.append(',%d' % (agg_cfg.max_alts,))
if agg_cfg.score_normalization:
agg_cfgstr.append(',norm')
if agg_cfg.normsum:
agg_cfgstr.append(',normsum')
agg_cfgstr.append(')')
return agg_cfgstr
@six.add_metaclass(ConfigMetaclass)
[docs]class FlannConfig(ConfigBase):
r"""
this flann is only for neareset neighbors in vsone/many
TODO: this might not need to be here, should be part of neighbor config
References:
http://www.cs.ubc.ca/research/flann/uploads/FLANN/flann_pami2014.pdf
http://www.cs.ubc.ca/research/flann/uploads/FLANN/flann_manual-1.8.4.pdf
http://docs.opencv.org/trunk/modules/flann/doc/flann_fast_approximate_nearest_neighbor_search.html
"""
def __init__(flann_cfg, **kwargs):
super(FlannConfig, flann_cfg).__init__(name='flann_cfg')
#General Params
flann_cfg.algorithm = 'kdtree' # linear
flann_cfg.flann_cores = 0 # doesnt change config, just speed
# KDTree params
flann_cfg.trees = 8
# KMeansTree params
flann_cfg.iterations = 11
flann_cfg.centers_init = 'random'
flann_cfg.cb_index = .4
flann_cfg.branching = 64
flann_cfg.update(**kwargs)
[docs] def get_flann_params(flann_cfg):
flann_params = dict(
algorithm=flann_cfg.algorithm,
trees=flann_cfg.trees,
cores=flann_cfg.flann_cores,
)
return flann_params
[docs] def get_cfgstr_list(flann_cfg, **kwargs):
flann_cfgstrs = ['_FLANN(']
if flann_cfg.algorithm == 'kdtree':
flann_cfgstrs += ['%d_kdtrees' % flann_cfg.trees]
elif flann_cfg.algorithm == 'kdtree':
flann_cfgstrs += [
'%s_' % flann_cfg.algorithm,
'iter=%s_' % flann_cfg.iterations,
'cb=%s_' % flann_cfg.cb_index,
'branch=%s' % flann_cfg.branching,
]
elif flann_cfg.algorithm == 'linear':
flann_cfgstrs += ['%s' % flann_cfg.algorithm]
else:
flann_cfgstrs += ['%s' % flann_cfg.algorithm]
#flann_cfgstrs += ['checks=%r' % flann_cfg.checks]
flann_cfgstrs += [')']
return flann_cfgstrs
@six.add_metaclass(ConfigMetaclass)
[docs]class SMKConfig(ConfigBase):
"""
Example:
>>> # ENABLE_DOCTEST
>>> from ibeis.algo.Config import * # NOQA
>>> smk_cfg = SMKConfig()
>>> result1 = smk_cfg.get_cfgstr()
>>> print(result1)
Example2:
>>> # ENABLE_DOCTEST
>>> import ibeis
>>> ibs = ibeis.opendb('testdb1')
>>> smk_cfg = ibs.cfg.query_cfg.smk_cfg
>>> smk_cfg.printme3()
"""
def __init__(smk_cfg, **kwargs):
super(SMKConfig, smk_cfg).__init__(name='smk_cfg')
smk_cfg.smk_thresh = 0.0 # tau in the paper
smk_cfg.smk_alpha = 3.0
smk_cfg.smk_aggregate = False
# TODO Separate into vocab config
smk_cfg._valid_vocab_weighting = ['idf', 'negentropy']
smk_cfg.vocab_weighting = 'idf'
smk_cfg.allow_self_match = False
smk_cfg.vocabtrain_cfg = VocabTrainConfig(**kwargs)
smk_cfg.vocabassign_cfg = VocabAssignConfig(**kwargs)
smk_cfg.update(**kwargs)
[docs] def make_feasible(smk_cfg):
hasvalid_weighting = any([
smk_cfg.vocab_weighting == x
for x in smk_cfg._valid_vocab_weighting])
assert hasvalid_weighting, (
'invalid vocab weighting %r' % smk_cfg.vocab_weighting)
[docs] def get_cfgstr_list(smk_cfg, **kwargs):
smk_cfgstr_list = [
'_SMK(',
'agg=', str(smk_cfg.smk_aggregate),
',t=', str(smk_cfg.smk_thresh),
',a=', str(smk_cfg.smk_alpha),
',SelfOk' if smk_cfg.allow_self_match else '',
',%s' % smk_cfg.vocab_weighting,
')',
]
smk_cfgstr_list.extend(smk_cfg.vocabassign_cfg.get_cfgstr_list())
smk_cfgstr_list.extend(smk_cfg.vocabtrain_cfg.get_cfgstr_list())
return smk_cfgstr_list
@six.add_metaclass(ConfigMetaclass)
[docs]class VocabTrainConfig(ConfigBase):
"""
Example:
>>> # ENABLE_DOCTEST
>>> from ibeis.algo.Config import * # NOQA
>>> vocabtrain_cfg = VocabTrainConfig()
>>> result = vocabtrain_cfg.get_cfgstr()
>>> print(result)
"""
def __init__(vocabtrain_cfg, **kwargs):
super(VocabTrainConfig, vocabtrain_cfg).__init__(
name='vocabtrain_cfg')
vocabtrain_cfg.override_vocab = 'default' # Vocab
vocabtrain_cfg.vocab_taids = 'all' # Vocab
vocabtrain_cfg.nWords = int(8E3) #
vocabtrain_cfg.vocab_init_method = 'akmeans++'
vocabtrain_cfg.vocab_nIters = 128
# TODO: easy flann params cfgstr
vocabtrain_cfg.vocab_flann_params = dict(cores=0)
vocabtrain_cfg.update(**kwargs)
[docs] def get_cfgstr_list(vocabtrain_cfg, **kwargs):
if vocabtrain_cfg.override_vocab == 'default':
if isinstance(vocabtrain_cfg.vocab_taids, six.string_types):
taids_cfgstr = 'taids=%s' % vocabtrain_cfg.vocab_taids
else:
taids_cfgstr = ut.hashstr_arr(vocabtrain_cfg.vocab_taids,
'taids', hashlen=8)
vocabtrain_cfg_list = [
'_VocabTrain(',
'nWords=%d' % (vocabtrain_cfg.nWords,),
',init=', str(vocabtrain_cfg.vocab_init_method),
',nIters=%d,' % int(vocabtrain_cfg.vocab_nIters),
taids_cfgstr,
')',
]
else:
vocabtrain_cfg_list = ['_VocabTrain(override=%s)' %
(vocabtrain_cfg.override_vocab,)]
return vocabtrain_cfg_list
@six.add_metaclass(ConfigMetaclass)
[docs]class VocabAssignConfig(ConfigBase):
"""
Example:
>>> # ENABLE_DOCTEST
>>> from ibeis.algo.Config import * # NOQA
>>> vocabassign_cfg = VocabAssignConfig()
>>> result = vocabassign_cfg.get_cfgstr()
>>> print(result)
"""
def __init__(vocabassign_cfg, **kwargs):
super(VocabAssignConfig, vocabassign_cfg).__init__(
name='vocabassign_cfg')
vocabassign_cfg.nAssign = 10 # MultiAssignment
vocabassign_cfg.massign_equal_weights = True
vocabassign_cfg.massign_alpha = 1.2
vocabassign_cfg.massign_sigma = 80.0
vocabassign_cfg.update(**kwargs)
[docs] def make_feasible(vocabassign_cfg):
assert vocabassign_cfg.nAssign > 0, 'cannot assign to nothing'
if vocabassign_cfg.nAssign == 1:
# No point to multiassign weights if nAssign is 1
vocabassign_cfg.massign_equal_weights = True
if vocabassign_cfg.massign_equal_weights:
# massign sigma makes no difference if there are equal weights
vocabassign_cfg.massign_sigma = None
[docs] def get_cfgstr_list(vocabassign_cfg, **kwargs):
vocabassign_cfg_list = [
'_VocabAssign(',
'nAssign=', str(vocabassign_cfg.nAssign),
',a=', str(vocabassign_cfg.massign_alpha),
',s=', (str(vocabassign_cfg.massign_sigma)
if vocabassign_cfg.massign_equal_weights else ''),
',eqw=T' if vocabassign_cfg.massign_equal_weights else ',eqw=F',
')',
]
return vocabassign_cfg_list
@six.add_metaclass(ConfigMetaclass)
[docs]class NNWeightConfig(ConfigBase):
r"""
CommandLine:
python -m ibeis.algo.Config --test-NNWeightConfig
Example:
>>> # ENABLE_DOCTEST
>>> from ibeis.algo.Config import * # NOQA
>>> cfg_list = [
... NNWeightConfig(),
... NNWeightConfig(can_match_sameimg=True, can_match_samename=False),
... NNWeightConfig(ratio_thresh=.625, lnbnn_on=False),
... NNWeightConfig(ratio_thresh=.625, lnbnn_normer='foobarstr'),
... ]
>>> result = '\n'.join([cfg.get_cfgstr() for cfg in cfg_list])
>>> print(result)
_NNWeight(lnbnn,fg,last,nosqrd_dist)
_NNWeight(lnbnn,fg,last,sameimg,nosamename,nosqrd_dist)
_NNWeight(ratio_thresh=0.625,fg,last,nosqrd_dist)
_NNWeight(ratio_thresh=0.625,lnbnn,fg,last,lnbnn_normer=foobarstr,lnbnn_norm_thresh=0.5,nosqrd_dist)
"""
def __init__(nnweight_cfg, **kwargs):
super(NNWeightConfig, nnweight_cfg).__init__(name='nnweight_cfg')
nnweight_cfg.initialize_params()
nnweight_cfg.update(**kwargs)
[docs] def get_param_info_list(nnweight_cfg):
# new way to try and specify config options.
# not sure if i like it yet
param_info_list = ut.flatten([
[
ut.ParamInfo('ratio_thresh', None, type_=float, hideif=None),
ut.ParamInfoBool('lnbnn_on', True, hideif=False),
ut.ParamInfoBool('const_on', False, hideif=False),
ut.ParamInfoBool('borda_on', False, hideif=False),
ut.ParamInfoBool('lograt_on', False, hideif=False),
#ut.ParamInfoBool('loglnbnn_on', False, hideif=False),
#ut.ParamInfoBool('logdist_on', False, hideif=False),
#ut.ParamInfoBool('dist_on', False, hideif=False),
ut.ParamInfoBool('normonly_on', False, hideif=False),
ut.ParamInfoBool('bar_l2_on', False, hideif=False),
ut.ParamInfoBool('cos_on', False, hideif=False),
ut.ParamInfoBool('fg_on', True, hideif=False),
ut.ParamInfo('normalizer_rule', 'last', '', valid_values=['last', 'name']),
ut.ParamInfo('lnbnn_normer', None, hideif=None,
help_='config string for lnbnn score normalizer'),
ut.ParamInfo('lnbnn_norm_thresh', .5, type_=float,
hideif=lambda cfg: not cfg['lnbnn_normer'] ,
help_='config string for lnbnn score normalizer'),
#
ut.ParamInfoBool('can_match_sameimg', False, 'sameimg',
hideif=False),
ut.ParamInfoBool('can_match_samename', True, 'samename',
hideif=True),
# Hacked in
#ut.ParamInfoBool('root_sift_on', False, hideif=False),
ut.ParamInfoBool('sqrd_dist_on', False, hideif=True),
#ut.ParamInfoBool('sqrd_dist_on', True, hideif=True),
],
])
return param_info_list
@six.add_metaclass(ConfigMetaclass)
[docs]class RerankVsOneConfig(ConfigBase):
"""
CommandLine:
python -m ibeis.algo.Config --test-RerankVsOneConfig
Example0:
>>> # ENABLE_DOCTEST
>>> from ibeis.algo.Config import * # NOQA
>>> rrvsone_cfg = RerankVsOneConfig(rrvsone_on=True)
>>> result = rrvsone_cfg.get_cfgstr()
>>> assert result.startswith('_RRVsOne(True,')
Example1:
>>> # ENABLE_DOCTEST
>>> from ibeis.algo.Config import * # NOQA
>>> rrvsone_cfg = RerankVsOneConfig(rrvsone_on=True)
>>> result = rrvsone_cfg.get_cfgstr()
>>> print(result)
_RRVsOne(True,nNm=20,nApN=3,prior_coeff=0.6,unc_coeff=0.4,sver_unc=True,uncRat=0.8)
"""
def __init__(rrvsone_cfg, **kwargs):
super(RerankVsOneConfig, rrvsone_cfg).__init__(name='rrvsone_cfg')
rrvsone_cfg.initialize_params()
rrvsone_cfg.update(**kwargs)
[docs] def get_config_name(rrvsone_cfg):
return 'RRVsOne'
[docs] def get_param_info_list(rrvsone_cfg):
from ibeis.algo.hots import distinctiveness_normalizer
from ibeis.algo.hots import vsone_pipeline
# new way to try and specify config options.
# not sure if i like it yet
param_info_list = ut.flatten([
[
ut.ParamInfo('rrvsone_on', False, ''),
],
vsone_pipeline.OTHER_RRVSONE_PARAMS.aslist(),
vsone_pipeline.SHORTLIST_DEFAULTS.aslist(),
vsone_pipeline.COEFF_DEFAULTS.aslist(),
vsone_pipeline.UNC_DEFAULTS.aslist(),
vsone_pipeline.SCR_DEFAULTS.aslist(),
vsone_pipeline.COVKPTS_DEFAULT.aslist(
hideif=lambda cfg: not cfg['covscore_on'] or cfg['maskscore_mode'] != 'kpts'),
vsone_pipeline.COVGRID_DEFAULT.aslist(
hideif=lambda cfg: not cfg['covscore_on'] or cfg['maskscore_mode'] != 'grid'),
distinctiveness_normalizer.DCVS_DEFAULT.aslist(
hideif=lambda cfg: not cfg['dcvs_on']),
])
return param_info_list
[docs] def get_constraint_func():
# TODO:
def constraint_func(cfg):
if cfg['rrvsone_on']:
return False
if cfg['use_gridcov_scoring'] and cfg['use_kptscov_scoring']:
return False
[docs] def get_cfgstr_list(rrvsone_cfg, **kwargs):
if rrvsone_cfg.rrvsone_on:
rrvsone_cfg_list = rrvsone_cfg.meta_get_cfgstr_list(**kwargs)
else:
rrvsone_cfg_list = [
'_RRVsOne(',
str(rrvsone_cfg.rrvsone_on),
')'
]
return rrvsone_cfg_list
@six.add_metaclass(ConfigMetaclass)
[docs]class QueryConfig(ConfigBase):
"""
query configuration parameters
Example:
>>> # ENABLE_DOCTEST
>>> import ibeis
>>> ibs = ibeis.opendb('testdb1')
>>> cfg = ibs.cfg.query_cfg
>>> cfgstr = ibs.cfg.query_cfg.get_cfgstr()
>>> print(cfgstr)
"""
def __init__(query_cfg, **kwargs):
super(QueryConfig, query_cfg).__init__(name='query_cfg')
query_cfg.nn_cfg = NNConfig(**kwargs)
query_cfg.nnweight_cfg = NNWeightConfig(**kwargs)
query_cfg.sv_cfg = SpatialVerifyConfig(**kwargs)
query_cfg.agg_cfg = AggregateConfig(**kwargs)
query_cfg.flann_cfg = FlannConfig(**kwargs)
query_cfg.smk_cfg = SMKConfig(**kwargs)
query_cfg.rrvsone_cfg = RerankVsOneConfig(**kwargs)
# causes some bug in Preference widget if these don't have underscore
query_cfg._featweight_cfg = FeatureWeightConfig(**kwargs)
query_cfg.use_cache = False
# Start of pipeline
query_cfg._valid_pipeline_roots = ['vsmany', 'vsone', 'smk']
query_cfg.pipeline_root = 'vsmany'
# <Hack Paramaters>
query_cfg.with_metadata = False
query_cfg.augment_queryside_hack = False
# for hacky distinctivness
query_cfg.return_expanded_nns = False
# for distinctivness model
query_cfg.use_external_distinctiveness = False
query_cfg.codename = 'None'
query_cfg.species_code = '____' # TODO: make use of this
# </Hack Paramaters>
#if ut.is_developer():
# query_cfg.pipeline_root = 'smk'
# Depends on feature config
query_cfg.update_query_cfg(**kwargs)
if ut.VERYVERBOSE:
print('[config] NEW QueryConfig')
[docs] def get_cfgstr_list(query_cfg, **kwargs):
# Ensure feasibility of the configuration
query_cfg.make_feasible()
# Build cfgstr
cfgstr_list = ['_' + query_cfg.pipeline_root ]
if str(query_cfg.pipeline_root) == 'smk':
# SMK Parameters
if kwargs.get('use_smk', True):
cfgstr_list += query_cfg.smk_cfg.get_cfgstr_list(**kwargs)
if kwargs.get('use_sv', True):
cfgstr_list += query_cfg.sv_cfg.get_cfgstr_list(**kwargs)
elif str(query_cfg.pipeline_root) == 'vsmany' or str(query_cfg.pipeline_root) == 'vsone':
# Naive Bayes Parameters
if kwargs.get('use_nn', True):
cfgstr_list += query_cfg.nn_cfg.get_cfgstr_list(**kwargs)
if kwargs.get('use_nnweight', True):
cfgstr_list += query_cfg.nnweight_cfg.get_cfgstr_list(**kwargs)
if kwargs.get('use_sv', True):
cfgstr_list += query_cfg.sv_cfg.get_cfgstr_list(**kwargs)
if kwargs.get('use_agg', True):
cfgstr_list += query_cfg.agg_cfg.get_cfgstr_list(**kwargs)
if kwargs.get('use_flann', True):
cfgstr_list += query_cfg.flann_cfg.get_cfgstr_list(**kwargs)
if kwargs.get('use_rrvsone', True):
cfgstr_list += query_cfg.rrvsone_cfg.get_cfgstr_list(**kwargs)
else:
raise AssertionError('bad pipeline root: ' + str(query_cfg.pipeline_root))
if kwargs.get('use_featweight', True):
cfgstr_list += query_cfg._featweight_cfg.get_cfgstr_list(**kwargs)
# HACK: featweight_cfg used to include chip and feat
# but they arent working now due to new structures, so they are hacked in here
# This whole file will eventually be depricated
cfgstr_list += query_cfg._featweight_cfg._feat_cfg.get_cfgstr_list(**kwargs)
cfgstr_list += query_cfg._featweight_cfg._feat_cfg._chip_cfg.get_cfgstr_list(**kwargs)
if query_cfg.augment_queryside_hack:
# HACK
cfgstr_list += ['_HACK(augment_queryside)']
return cfgstr_list
[docs] def update_query_cfg(query_cfg, **cfgdict):
# Each config paramater should be unique
# So updating them all should not cause conflicts
# FIXME: Should be able to infer all the children that need updates
#
# apply codename before updating subconfigs
query_cfg.apply_codename(cfgdict.get('codename', None))
# update subconfigs
query_cfg.nn_cfg.update(**cfgdict)
query_cfg.nnweight_cfg.update(**cfgdict)
query_cfg.sv_cfg.update(**cfgdict)
query_cfg.agg_cfg.update(**cfgdict)
query_cfg.flann_cfg.update(**cfgdict)
query_cfg.smk_cfg.update(**cfgdict)
query_cfg.smk_cfg.vocabassign_cfg.update(**cfgdict)
query_cfg.smk_cfg.vocabtrain_cfg.update(**cfgdict)
query_cfg.rrvsone_cfg.update(**cfgdict)
query_cfg._featweight_cfg.update(**cfgdict)
query_cfg._featweight_cfg._feat_cfg.update(**cfgdict)
query_cfg._featweight_cfg._feat_cfg._chip_cfg.update(**cfgdict)
query_cfg.update(**cfgdict)
# Ensure feasibility of the configuration
try:
query_cfg.make_feasible()
except AssertionError as ex:
print(ut.dict_str(cfgdict, sorted_=True))
ut.printex(ex)
raise
[docs] def apply_codename(query_cfg, codename=None):
"""
codenames denote mass changes to configurations
it is a hacky solution to setting different parameter
values all at once.
"""
if codename is None:
codename = query_cfg.codename
nnweight_cfg = query_cfg.nnweight_cfg
nn_cfg = query_cfg.nn_cfg
agg_cfg = query_cfg.agg_cfg
if codename.startswith('csum') or codename.endswith('_csum'):
raise NotImplementedError('codename nsum')
if codename.startswith('nsum'):
raise NotImplementedError('codename nsum')
if codename.startswith('vsmany'):
query_cfg.pipeline_root = 'vsmany'
elif codename.startswith('vsone'):
query_cfg.pipeline_root = 'vsone'
nn_cfg.K = 1
nn_cfg.Knorm = 1
nnweight_cfg.lnbnn_on = False
#nnweight_cfg.ratio_thresh = 1.6
if codename.endswith('_dist') or '_dist_' in codename:
# no ratio use distance
nnweight_cfg.ratio_thresh = None
nnweight_cfg.dist_on = True
else:
nnweight_cfg.ratio_thresh = .625
if '_ratio' in codename:
nnweight_cfg.ratio_thresh = .625
if '_extern_distinctiveness' in codename:
query_cfg.use_external_distinctiveness = True
if codename.startswith('vsone_unnorm'):
agg_cfg.score_normalization = None
elif codename.startswith('vsone_norm'):
agg_cfg.score_normalization = 'vsone_default'
elif codename.startswith('asmk'):
query_cfg.pipeline_root = 'asmk'
elif codename.startswith('smk'):
query_cfg.pipeline_root = 'smk'
elif codename == 'None':
pass
[docs] def make_feasible(query_cfg):
try:
query_cfg.make_feasible_()
except AssertionError as ex:
if ut.NOT_QUIET:
query_cfg.printme3()
ut.printex(ex, 'failed ot make feasible')
raise
[docs] def make_feasible_(query_cfg):
"""
removes invalid parameter settings over all cfgs (move to QueryConfig)
"""
nnweight_cfg = query_cfg.nnweight_cfg
nn_cfg = query_cfg.nn_cfg
featweight_cfg = query_cfg._featweight_cfg
#feat_cfg = query_cfg._featweight_cfg._feat_cfg
smk_cfg = query_cfg.smk_cfg
vocabassign_cfg = query_cfg.smk_cfg.vocabassign_cfg
agg_cfg = query_cfg.agg_cfg
#sv_cfg = query_cfg.sv_cfg
#assert sv_cfg.prescore_method == agg_cfg.score_method, 'cannot be
# different yet.'
if agg_cfg.score_normalization and query_cfg.pipeline_root == 'vsmany':
assert agg_cfg.score_method == 'nsum'
if query_cfg.pipeline_root == 'asmk':
query_cfg.pipeline_root = 'smk'
smk_cfg.smk_aggregate = True
hasvalid_root = any([
query_cfg.pipeline_root == root
for root in query_cfg._valid_pipeline_roots])
try:
assert hasvalid_root, (
'invalid pipeline root %r' % query_cfg.pipeline_root)
except AssertionError as ex:
ut.printex(ex)
if ut.SUPER_STRICT:
raise
else:
query_cfg.pipeline_root = query_cfg._valid_pipeline_roots[0]
pass
# HACK
if nnweight_cfg.fg_on is not True:
featweight_cfg.featweight_enabled = False
if featweight_cfg.featweight_enabled is not True:
nnweight_cfg.fg_on = False
vocabassign_cfg.make_feasible()
smk_cfg.make_feasible()
#nnweight_cfg.make_feasible()
nn_cfg.make_feasible()
[docs] def deepcopy(query_cfg, **kwargs):
copy_ = copy.deepcopy(query_cfg)
copy_.update_query_cfg(**kwargs)
return copy_
@six.add_metaclass(ConfigMetaclass)
[docs]class FeatureWeightConfig(ConfigBase):
"""
CommandLine:
python -m ibeis.algo.Config --exec-FeatureWeightConfig
Example:
>>> # ENABLE_DOCTEST
>>> from ibeis.algo.Config import * # NOQA
>>> featweight_cfg = FeatureWeightConfig(fw_detector='rf',
>>> featweight_enabled=True)
>>> result = featweight_cfg.get_cfgstr()
>>> print(result)
_FEATWEIGHT(ON,uselabel,rf)_FEAT(hesaff+sift_)_CHIP(sz450)
_FEATWEIGHT(OFF)_FEAT(hesaff+sift_)_CHIP(sz450)
"""
def __init__(featweight_cfg, **kwargs):
super(FeatureWeightConfig, featweight_cfg).__init__(
name='featweight_cfg')
# Featweights depend on features
featweight_cfg._feat_cfg = FeatureConfig(**kwargs)
featweight_cfg.initialize_params()
# Feature weights depend on the detector, but we only need to mirror
# some parameters because featweight_cfg should not use the detect_cfg
# object
#featweight_cfg.featweight_enabled = False
#featweight_cfg.featweight_enabled = True
#featweight_cfg.featweight_species = 'uselabel'
#featweight_cfg.fw_detector = 'rf'
#featweight_cfg.fw_detector = 'cnn'
featweight_cfg.update(**kwargs)
[docs] def make_feasible(featweight_cfg):
#featweight_cfg.featweight_enabled = False
pass
[docs] def get_param_info_list(self):
from ibeis import core_annots
return core_annots.ProbchipConfig._param_info_list + core_annots.FeatWeightConfig._param_info_list
#def get_cfgstr_list(featweight_cfg, **kwargs):
# featweight_cfg.make_feasible()
# featweight_cfgstrs = []
# if kwargs.get('use_featweight', True):
# if featweight_cfg.featweight_enabled is not True:
# if featweight_cfg.featweight_enabled == 'ERR':
# featweight_cfgstrs.extend(['_FEATWEIGHT(ERR)'])
# else:
# featweight_cfgstrs.extend(['_FEATWEIGHT(OFF)'])
# else:
# featweight_cfgstrs.extend([
# '_FEATWEIGHT(ON',
# ',' + featweight_cfg.featweight_species,
# ',' + featweight_cfg.fw_detector,
# ')'])
# _cfgstrlist = featweight_cfg._feat_cfg.get_cfgstr_list(**kwargs)
# featweight_cfgstrs.extend(_cfgstrlist)
# return featweight_cfgstrs
@six.add_metaclass(ConfigMetaclass)
[docs]class FeatureConfig(ConfigBase):
"""
Feature configuration object.
TODO depcirate for core_annots.FeatConfig
CommandLine:
python -m ibeis.algo.Config --test-FeatureConfig
Example:
>>> # ENABLE_DOCTEST
>>> from ibeis.algo import Config # NOQA
>>> from ibeis.algo.Config import * # NOQA
>>> feat_cfg = Config.FeatureConfig()
>>> result = (feat_cfg.get_cfgstr())
>>> print(result)
>>> #assert result.startswith('_FEAT(hesaff+sift_)_CHIP')
_Feat(hesaff+sift)
"""
def __init__(feat_cfg, **kwargs):
# Features depend on chips
#import pyhesaff
super(FeatureConfig, feat_cfg).__init__(name='feat_cfg')
feat_cfg._chip_cfg = ChipConfig(**kwargs)
feat_cfg.initialize_params()
#feat_cfg.feat_type = 'hesaff+sift'
#feat_cfg.bgmethod = None
#feat_cfg._param_list = list(six.iteritems(
# pyhesaff.get_hesaff_default_params()))
#for type_, name, default, doc in feat_cfg._iterparams():
# setattr(feat_cfg, name, default)
#feat_cfg.use_adaptive_scale = False # 9001 # 80
#feat_cfg.nogravity_hack = False # 9001 # 80
feat_cfg.update(**kwargs)
[docs] def get_param_info_list(self):
from ibeis import core_annots
return core_annots.FeatConfig().get_param_info_list()
[docs] def get_config_name(self):
return 'Feat'
[docs] def get_hesaff_params(feat_cfg):
import pyhesaff
default_keys = list(pyhesaff.get_hesaff_default_params().keys())
hesaff_param_dict = ut.dict_subset(feat_cfg, default_keys)
return hesaff_param_dict
@six.add_metaclass(ConfigMetaclass)
[docs]class ChipConfig(ConfigBase):
""" ChipConfig """
def __init__(cc_cfg, **kwargs):
super(ChipConfig, cc_cfg).__init__(name='chip_cfg')
cc_cfg.initialize_params()
#cc_cfg.dim_size = 450
##cc_cfg.resize_dim = 'area'
#cc_cfg.resize_dim = 'width'
#cc_cfg.grabcut = False
#cc_cfg.histeq = False
#cc_cfg.adapteq = False
#cc_cfg.region_norm = False
#cc_cfg.rank_eq = False
#cc_cfg.local_eq = False
#cc_cfg.maxcontrast = False
#cc_cfg.chipfmt = '.png'
cc_cfg.update(**kwargs)
[docs] def get_param_info_list(self):
from ibeis import core_annots
return core_annots.ChipConfig._param_info_list
@six.add_metaclass(ConfigMetaclass)
[docs]class DetectionConfig(ConfigBase):
"""
CommandLine:
python -m ibeis.algo.Config --test-DetectionConfig
Example:
>>> # ENABLE_DOCTEST
>>> from ibeis.algo.Config import * # NOQA
>>> detect_cfg = DetectionConfig()
>>> result = (detect_cfg.get_cfgstr())
>>> print(result)
_DETECT(cnn,____,sz=800)
"""
def __init__(detect_cfg, **kwargs):
super(DetectionConfig, detect_cfg).__init__(name='detect_cfg')
#detect_cfg.species_text = 'zebra_grevys'
detect_cfg.species_text = const.UNKNOWN
# detect_cfg.detector = 'rf'
detect_cfg.detector = 'cnn'
detect_cfg.scale_list = '1.25, 1.0, 0.80, 0.65, 0.50, 0.40, 0.30, 0.20, 0.10'
detect_cfg.trees_path = ''
detect_cfg.detectimg_sqrt_area = 800
detect_cfg.update(**kwargs)
[docs] def get_cfgstr_list(detect_cfg):
cfgstrs = ['_DETECT(',
detect_cfg.detector,
',', detect_cfg.species_text,
',sz=%d' % (detect_cfg.detectimg_sqrt_area,),
')']
return cfgstrs
@six.add_metaclass(ConfigMetaclass)
[docs]class OccurrenceConfig(ConfigBase):
""" OccurrenceConfig
CommandLine:
python -m ibeis.algo.Config --exec-OccurrenceConfig --show
Example:
>>> # DISABLE_DOCTEST
>>> from ibeis.algo.Config import * # NOQA
>>> occur_cfg = OccurrenceConfig()
>>> print(occur_cfg.get_cfgstr())
"""
def __init__(occur_cfg, **kwargs):
super(OccurrenceConfig, occur_cfg).__init__(name='occur_cfg')
occur_cfg.initialize_params()
occur_cfg.update(**kwargs)
[docs] def get_param_info_list(occur_cfg):
param_info_list = [
ut.ParamInfo('min_imgs_per_occurrence', 1, 'minper='),
ut.ParamInfo('cluster_algo', 'agglomerative', '', valid_values=['agglomerative', 'meanshift']),
ut.ParamInfo('quantile', .01, 'quant', hideif=lambda cfg: cfg['cluster_algo'] != 'meanshift'),
ut.ParamInfo('seconds_thresh', 600, 'sec', hideif=lambda cfg: cfg['cluster_algo'] != 'agglomerative'),
ut.ParamInfo('use_gps', False, hideif=False),
]
return param_info_list
@six.add_metaclass(ConfigMetaclass)
[docs]class DisplayConfig(ConfigBase):
""" DisplayConfig """
def __init__(display_cfg, **kwargs):
super(DisplayConfig, display_cfg).__init__(name='display_cfg')
display_cfg.N = 6
display_cfg.name_scoring = False
display_cfg.showanalysis = False
display_cfg.annotations = True
display_cfg.vert = True # None
display_cfg.show_results_in_image = False # None
[docs] def get_cfgstr_list(nn_cfg):
raise NotImplementedError('abstract')
return ['unimplemented']
@six.add_metaclass(ConfigMetaclass)
[docs]class OtherConfig(ConfigBase):
def __init__(other_cfg, **kwargs):
super(OtherConfig, other_cfg).__init__(name='other_cfg')
#other_cfg.thumb_size = 128
other_cfg.thumb_size = 221
other_cfg.thumb_bare_size = 700
other_cfg.ranks_lt = 2
other_cfg.filter_reviewed = True
other_cfg.auto_localize = True
# maximum number of exemplars per name
other_cfg.max_exemplars = 6
other_cfg.exemplars_per_view = 2
other_cfg.prioritized_subset_annots_per_name = 2
other_cfg.exemplar_distinctiveness_thresh = .95
other_cfg.detect_add_after = 1
# other_cfg.detect_use_chunks = True
other_cfg.use_more_special_imagesets = True
other_cfg.location_for_names = 'IBEIS'
#other_cfg.location_for_names = 'MUGU'
other_cfg.smart_enabled = True
other_cfg.enable_custom_filter = False
other_cfg.hots_batch_size = 256
other_cfg.use_augmented_indexer = True
other_cfg.show_shipped_imagesets = ut.is_developer()
other_cfg.update(**kwargs)
# Convinience
def __dict_default_func(dict_):
# Sets keys only if they dont exist
def set_key(key, val):
if key not in dict_:
dict_[key] = val
return set_key
[docs]def default_vsone_cfg(ibs, **kwargs):
# DEPRICATE
kwargs['pipeline_root'] = 'vsone'
ut.dict_update_newkeys(kwargs, {
'lnbnn_on': False,
'checks': 256, 'K': 1,
'Knorm': 1,
'ratio_thresh': .6666 # 1.5,
})
query_cfg = QueryConfig(**kwargs)
return query_cfg
[docs]def set_query_cfg(cfg, query_cfg):
""" hack 12-30-2014 """
cfg.query_cfg = query_cfg
cfg.featweight_cfg = cfg.query_cfg._featweight_cfg
cfg.feat_cfg = cfg.query_cfg._featweight_cfg._feat_cfg
cfg.chip_cfg = cfg.query_cfg._featweight_cfg._feat_cfg._chip_cfg
[docs]def update_query_config(cfg, **kwargs):
""" hack 12-30-2014 """
cfg.query_cfg.update_query_cfg(**kwargs)
cfg.featweight_cfg = cfg.query_cfg._featweight_cfg
cfg.feat_cfg = cfg.query_cfg._featweight_cfg._feat_cfg
cfg.chip_cfg = cfg.query_cfg._featweight_cfg._feat_cfg._chip_cfg
[docs]def load_named_config(cfgname, dpath, use_config_cache=False,
verbose=ut.VERBOSE and ut.NOT_QUIET):
""" hack 12-30-2014
Args:
cfgname (str):
dpath (str):
use_config_cache (bool):
Returns:
Config: cfg
CommandLine:
python -m ibeis.algo.Config --test-load_named_config
Example:
>>> # DISABLE_DOCTEST
>>> from ibeis.algo.Config import * # NOQA
>>> from ibeis.algo.Config import _default_config # NOQA
>>> import ibeis
>>> ibs = ibeis.opendb('PZ_Master0')
>>> #ibs.cfg.save()
>>> # build test data
>>> cfgname = 'zebra_plains'
>>> dpath = ibs.get_dbdir()
>>> use_config_cache = True
>>> # execute function
>>> cfg = load_named_config(cfgname, dpath, use_config_cache)
>>> #
>>> keys1 = ut.get_list_column(cfg.parse_items(), 0)
>>> keys2 = ut.get_list_column(ibs.cfg.parse_items(), 0)
>>> symdiff = set(keys1) ^ set(keys2)
>>> # verify results
>>> result = str(cfg)
>>> print(result)
"""
if cfgname is None:
# TODO: find last cfgname
cfgname = 'cfg'
fpath = join(dpath, cfgname) + '.cPkl'
if verbose:
print('[Config] loading named config fpath=%r' % (fpath,))
# Always a fresh object
cfg = GenericConfig(cfgname, fpath=fpath)
try:
# Use pref cache
if not use_config_cache:
raise Exception('force config cache miss')
# Get current "schema"
tmp = _default_config(cfg, cfgname, new=True)
current_itemset = tmp.parse_items()
current_keyset = list(ut.get_list_column(current_itemset, 0))
# load saved preferences
cfg.load()
# Check if loaded schema has changed
loaded_keyset = list(ut.get_list_column(cfg.parse_items(), 0))
missing_keys = set(current_keyset) - set(loaded_keyset)
if len(missing_keys) != 0:
# Bring over new values into old structure
tmp.update(**dict(cfg.parse_items()))
cfg = tmp
#missing_vals = ut.dict_take(dict(current_itemset), missing_keys)
#def find_cfgkey_parent(tmp, key):
# subconfig_list = []
# for attr in dir(tmp):
# if attr == key:
# return tmp
# child = getattr(tmp, attr)
# if isinstance(child, ConfigBase):
# subconfig_list.append(child)
# for subconfig in subconfig_list:
# found = find_cfgkey_parent(subconfig, key)
# if found is not None:
# return found
#missing_parents = [find_cfgkey_parent(tmp, key) for key in missing_keys]
#for parent, key, val in zip(missing_parents, missing_keys, missing_vals):
# setattr(parent, key, val)
# # TODO: Finishme update the out of data preferences
# pass
if verbose:
print('[Config] successfully loaded config cfgname=%r' % (cfgname,))
except Exception as ex:
if ut.VERBOSE:
ut.printex(ex, iswarning=True)
# Totally new completely default preferences
cfg = _default_config(cfg, cfgname)
# Hack in cfgname
if verbose:
print('[Config] hack in z_cfgname=%r' % (cfgname,))
cfg.z_cfgname = cfgname
return cfg
def _default_config(cfg, cfgname=None, new=True):
""" hack 12-30-2014 """
if ut.VERBOSE:
print('[Config] building default config')
if cfgname is None:
cfgname = cfg.z_cfgname
if new:
fpath = cfg.get_fpath()
cfg = GenericConfig(cfgname, fpath=fpath)
cfg.z_cfgname = cfgname
query_cfg = QueryConfig(pipeline_root='vsmany')
set_query_cfg(cfg, query_cfg)
cfg.occur_cfg = OccurrenceConfig()
cfg.detect_cfg = DetectionConfig()
cfg.other_cfg = OtherConfig()
_default_named_config(cfg, cfgname)
#if len(species_list) == 1:
# # try to be intelligent about the default speceis
# cfg.detect_cfg.species_text = species_list[0]
return cfg
def _default_named_config(cfg, cfgname):
""" hack 12-30-2014
list default parameters per species
"""
if cfgname == 'cfg':
cfg.detect_cfg.species_text = 'none'
elif cfgname == 'zebra_plains':
cfg.detect_cfg.species_text = cfgname
#speedup': 46.90769958496094,
cfg.query_cfg.flann_cfg.algorithm = 'kdtree'
cfg.query_cfg.flann_cfg.trees = 8
cfg.query_cfg.nn_cfg.checks = 704
#'algorithm': 'kdtree',
#[dev.tune_flann] 'checks': 6656,
#[dev.tune_flann] 'trees': 4,
# Kmeans seems a bit more accurate
#'algorithm': 'kmeans',
#'branching': 16,
#'cb_index': 0.6000000238418579,
#'centers_init': 'random',
#'checks': 18432,
#'iterations': 1,
#'leaf_max_size': 4,
#'speedup': 65.54280090332031,
#'target_precision': 0.9800000190734863,
elif cfgname == 'zebra_grevys':
cfg.detect_cfg.species_text = cfgname
#speedup': 224.7425994873047,
cfg.query_cfg.flann_cfg.algorithm = 'kdtree'
cfg.query_cfg.flann_cfg.trees = 4
cfg.query_cfg.nn_cfg.checks = 896
elif cfgname == 'giraffe_reticulated':
cfg.detect_cfg.species_text = cfgname
cfg.query_cfg.flann_cfg.algorithm = 'kdtree'
cfg.query_cfg.flann_cfg.trees = 8
cfg.query_cfg.nn_cfg.checks = 316
else:
if ut.VERBOSE:
print('WARNING: UNKNOWN CFGNAME=%r' % (cfgname,))
if __name__ == '__main__':
"""
CommandLine:
python -m ibeis.algo.Config
python -m ibeis.algo.Config --allexamples
"""
import multiprocessing
multiprocessing.freeze_support() # for win32
import utool as ut # NOQA
ut.doctest_funcs()