# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function, unicode_literals
import plottool as pt
import utool as ut # NOQA
import numpy as np
from ibeis.other import ibsfuncs
#from ibeis.algo.hots import chip_match
from ibeis.viz import viz_helpers as vh
from ibeis.viz import viz_chip
from ibeis.viz import viz_matches # NOQA
(print, rrr, profile) = ut.inject2(__name__, '[viz_qres]')
DEFAULT_NTOP = 3
#@ut.indent_func
@profile
[docs]def show_qres_top(ibs, cm, qreq_=None, **kwargs):
"""
Wrapper around show_qres.
"""
N = kwargs.get('N', DEFAULT_NTOP)
#name_scoring = kwargs.get('name_scoring', False)
#if isinstance(cm, chip_match.ChipMatch):
top_aids = cm.get_top_aids(N)
#else:
# top_aids = cm.get_top_aids(num=N, ibs=ibs, name_scoring=name_scoring)
aidstr = ibsfuncs.aidstr(cm.qaid)
figtitle = kwargs.get('figtitle', '')
if len(figtitle) > 0:
figtitle = ' ' + figtitle
kwargs['figtitle'] = ('q%s -- TOP %r' % (aidstr, N)) + figtitle
return show_qres(ibs, cm, top_aids=top_aids, qreq_=qreq_,
# dont use these. use annot mode instead
#draw_kpts=False,
#draw_ell=False,
#all_kpts=False,
**kwargs)
#@ut.indent_func
@profile
[docs]def show_qres_analysis(ibs, cm, qreq_=None, **kwargs):
"""
Wrapper around show_qres.
KWARGS:
aid_list - show matches against aid_list (default top 3)
Args:
ibs (IBEISController): ibeis controller object
cm (ChipMatch): object of feature correspondences and scores
qreq_ (QueryRequest): query request object with hyper-parameters(default = None)
Kwargs:
N, show_gt, show_query, aid_list, figtitle, viz_name_score, viz_name_score
CommandLine:
python -m ibeis.viz.viz_qres --exec-show_qres_analysis --show
Example:
>>> # ENABLE_DOCTEST
>>> from ibeis.viz.viz_qres import * # NOQA
>>> import ibeis
>>> species = ibeis.const.TEST_SPECIES.ZEB_PLAIN
>>> ibs = ibeis.opendb(defaultdb='PZ_MTEST')
>>> daids = ibs.get_valid_aids(species=species)
>>> qaids = ibs.get_valid_aids(species=species)
>>> qres_list, qreq_ = ibs.query_chips(
>>> [1], [2, 3, 4, 5, 6, 7, 8, 9],
>>> cfgdict=dict(), return_request=True)
>>> cm = qres_list[0]
>>> kwargs = dict(show_query=False, viz_name_score=True,
>>> show_timedelta=True, N=3, show_gf=True)
>>> show_qres_analysis(ibs, cm, qreq_, **kwargs)
>>> ut.show_if_requested()
"""
if ut.NOT_QUIET:
print('[show_qres] cm.show_analysis()')
# Parse arguments
N = kwargs.get('N', DEFAULT_NTOP)
show_gt = kwargs.pop('show_gt', True)
show_gf = kwargs.pop('show_gf', False)
show_query = kwargs.pop('show_query', True)
aid_list = kwargs.pop('aid_list', None)
figtitle = kwargs.pop('figtitle', None)
#viz_name_score = kwargs.get('viz_name_score', qreq_ is not None)
#viz_name_score = kwargs.get('viz_name_score', False)
viz_name_score = kwargs.get('viz_name_score', True)
failed_to_match = False
# Debug printing
#print('[analysis] noshow_gt = %r' % noshow_gt)
#print('[analysis] show_query = %r' % show_query)
#print('[analysis] aid_list = %r' % aid_list)
if aid_list is None:
# Compare to aid_list instead of using top ranks
#print('[analysis] showing top aids')
top_aids = cm.get_top_aids(N)
if len(top_aids) == 0:
failed_to_match = True
print('WARNING! No matches found for this query')
if figtitle is None:
if len(top_aids) == 0:
figtitle = 'WARNING: no matches found!' + ibsfuncs.aidstr(cm.qaid)
else:
topscore = cm.get_annot_scores(top_aids)[0]
figtitle = ('q%s -- topscore=%r' % (ibsfuncs.aidstr(cm.qaid), topscore))
else:
print('[analysis] showing a given list of aids')
top_aids = aid_list
if figtitle is None:
figtitle = 'comparing to ' + ibsfuncs.aidstr(top_aids) + figtitle
# Get any groundtruth if you are showing it
showgt_aids = []
if show_gt:
# Get the missed groundtruth annotations
#if isinstance(cm, chip_match.ChipMatch):
assert qreq_ is not None
matchable_aids = qreq_.daids
#matchable_aids = cm.daid_list
#else:
# matchable_aids = cm.daids
#matchable_aids = ibs.get_recognition_database_aids()
#matchable_aids = list(cm.aid2_fm.keys())
_gtaids = ibs.get_annot_groundtruth(cm.qaid, daid_list=matchable_aids)
if viz_name_score:
# Only look at the groundtruth if a name isnt in the top list
_gtnids = ibs.get_annot_name_rowids(_gtaids)
top_nids = ibs.get_annot_name_rowids(top_aids)
_valids = ~np.in1d(_gtnids, top_nids)
_gtaids = ut.compress(_gtaids, _valids)
# No need to display highly ranked groundtruth. It will already show up
_gtaids = np.setdiff1d(_gtaids, top_aids)
# Sort missed grountruth by score
_gtscores = cm.get_annot_scores(_gtaids)
_gtaids = ut.sortedby(_gtaids, _gtscores, reverse=True)
if viz_name_score:
if len(_gtaids) > 1:
_gtaids = _gtaids[0:1]
else:
if len(_gtaids) > 3:
# Hack to not show too many unmatched groundtruths
#_isexmp = ibs.get_annot_exemplar_flags(_gtaids)
_gtaids = _gtaids[0:3]
showgt_aids = _gtaids
if show_gf:
# Show only one top-scoring groundfalse example
top_nids = ibs.get_annot_name_rowids(top_aids)
is_groundfalse = top_nids != ibs.get_annot_name_rowids(cm.qaid)
gf_idxs = np.nonzero(is_groundfalse)[0]
if len(gf_idxs) > 0:
best_gf_idx = gf_idxs[0]
isvalid = ~is_groundfalse
isvalid[best_gf_idx] = True
# Filter so there is only one groundfalse
top_aids = top_aids.compress(isvalid)
else:
# seems like there were no results. Must be bad feature detections
# maybe too much spatial verification
top_aids = []
if len(showgt_aids) != 0:
# Hack to just include gtaids in normal list
top_aids = np.append(top_aids, showgt_aids)
showgt_aids = []
if viz_name_score:
# Make sure that there is only one of each name in the list
top_nids = ibs.get_annot_name_rowids(top_aids)
top_aids = ut.compress(top_aids, ut.flag_unique_items(top_nids))
return show_qres(ibs, cm, gt_aids=showgt_aids, top_aids=top_aids,
figtitle=figtitle, show_query=show_query, qreq_=qreq_,
failed_to_match=failed_to_match,
**kwargs)
[docs]def testdata_show_qres():
import ibeis
cm, qreq_ = ibeis.testdata_cm()
kwargs = dict(
top_aids=ut.get_argval('--top-aids', type_=int, default=3),
sidebyside=not ut.get_argflag('--no-sidebyside'),
annot_mode=ut.get_argval('--annot_mode', type_=int, default=1),
viz_name_score=not ut.get_argflag('--no-viz_name_score'),
max_nCols=ut.get_argval('--max_nCols', type_=int, default=None)
)
return qreq_.ibs, cm, qreq_, kwargs
#@ut.indent_func
#@ut.tracefunc_xml
[docs]def show_qres(ibs, cm, qreq_=None, **kwargs):
"""
Display Query Result Logic
Defaults to: query chip, groundtruth matches, and top matches
Args:
ibs (ibeis.IBEISController): ibeis controller object
cm (ibeis.ChipMatch): object of feature correspondences and scores
Kwargs:
in_image (bool) show result in image view if True else chip view
annot_mode (int):
if annot_mode == 0, then draw lines and ellipse
elif annot_mode == 1, then dont draw lines or ellipse
elif annot_mode == 2, then draw only lines
See: viz_matches.show_name_matches, viz_helpers.get_query_text
Returns:
mpl.Figure: fig
CommandLine:
./main.py --query 1 -y --db PZ_MTEST --noshow-qtres
python -m ibeis.viz.viz_qres --test-show_qres --show
python -m ibeis.viz.viz_qres --test-show_qres --show --top-aids=10 --db=PZ_MTEST --sidebyside --annot_mode=0 --notitle --no-viz_name_score --qaids=5 --max_nCols=2 --adjust=.01,.01,.01
python -m ibeis.viz.viz_qres --test-show_qres --show --top-aids=10 --db=PZ_MTEST --sidebyside --annot_mode=0 --notitle --no-viz_name_score --qaids=5 --max_nCols=2 --adjust=.01,.01,.01
Example:
>>> # DISABLE_DOCTEST
>>> from ibeis.viz.viz_qres import * # NOQA
>>> import plottool as pt
>>> ibs, cm, qreq_, kwargs = testdata_show_qres()
>>> # execute function
>>> fig = show_qres(ibs, cm, show_query=False, qreq_=qreq_, **kwargs)
>>> # verify results
>>> #fig.show()
>>> pt.show_if_requested()
"""
#ut.print_dict(kwargs)
annot_mode = kwargs.get('annot_mode', 1) % 3 # this is toggled
figtitle = kwargs.get('figtitle', '')
make_figtitle = kwargs.get('make_figtitle', False)
aug = kwargs.get('aug', '')
top_aids = kwargs.get('top_aids', DEFAULT_NTOP)
gt_aids = kwargs.get('gt_aids', [])
all_kpts = kwargs.get('all_kpts', False)
show_query = kwargs.get('show_query', False)
in_image = kwargs.get('in_image', False)
sidebyside = kwargs.get('sidebyside', True)
#name_scoring = kwargs.get('name_scoring', False)
viz_name_score = kwargs.get('viz_name_score', qreq_ is not None)
max_nCols = kwargs.get('max_nCols', None)
failed_to_match = kwargs.get('failed_to_match', False)
fnum = pt.ensure_fnum(kwargs.get('fnum', None))
if ut.VERBOSE and ut.NOT_QUIET:
print('query_info = ' + ut.obj_str(
ibs.get_annot_info(cm.qaid, default=True, gname=False, name=False, notes=False,
exemplar=False), nl=4))
print('top_aids_info = ' + ut.obj_str(
ibs.get_annot_info(top_aids, default=True, gname=False, name=False, notes=False,
exemplar=False, reference_aid=cm.qaid), nl=4))
if make_figtitle is True:
pass
#figtitle = cm.make_title(pack=True)
#figtitle
fig = pt.figure(fnum=fnum, docla=True, doclf=True)
if isinstance(top_aids, int):
#if isinstance(cm, chip_match.ChipMatch):
top_aids = cm.get_top_aids(top_aids)
#else:
# top_aids = cm.get_top_aids(num=top_aids, name_scoring=name_scoring, ibs=ibs)
if failed_to_match:
# HACK to visually indicate failure to match in analysis
top_aids = [None] + top_aids
nTop = len(top_aids)
if max_nCols is None:
max_nCols = 5
if nTop in [6, 7]:
max_nCols = 3
if nTop in [8]:
max_nCols = 4
try:
assert len(list(set(top_aids).intersection(set(gt_aids)))) == 0, (
'gts should be missed. not in top')
except AssertionError as ex:
ut.printex(ex, keys=['top_aids', 'gt_aids'])
raise
if ut.DEBUG2:
print(cm.get_inspect_str())
#--------------------------------------------------
# Get grid / cell information to build subplot grid
#--------------------------------------------------
# Show query or not
nQuerySubplts = 1 if show_query else 0
# The top row is given slots for ground truths and querys
# all aids in gt_aids should not be in top aids
nGtSubplts = nQuerySubplts + (0 if gt_aids is None else len(gt_aids))
# The bottom rows are for the top results
nTopNSubplts = nTop
nTopNCols = min(max_nCols, nTopNSubplts)
nGTCols = min(max_nCols, nGtSubplts)
nGTCols = max(nGTCols, nTopNCols)
nTopNCols = nGTCols
# Get number of rows to show groundtruth
nGtRows = 0 if nGTCols == 0 else int(np.ceil(nGtSubplts / nGTCols))
# Get number of rows to show results
nTopNRows = 0 if nTopNCols == 0 else int(np.ceil(nTopNSubplts / nTopNCols))
nGtCells = nGtRows * nGTCols
# Total number of rows
nRows = nTopNRows + nGtRows
DEBUG_SHOW_QRES = 0
if DEBUG_SHOW_QRES:
allgt_aids = ibs.get_annot_groundtruth(cm.qaid)
nSelGt = len(gt_aids)
nAllGt = len(allgt_aids)
print('[show_qres]========================')
print('[show_qres]----------------')
print('[show_qres] * annot_mode=%r' % (annot_mode,))
print('[show_qres] #nTop=%r #missed_gts=%r/%r' % (nTop, nSelGt, nAllGt))
print('[show_qres] * -----')
print('[show_qres] * nRows=%r' % (nRows,))
print('[show_qres] * nGtSubplts=%r' % (nGtSubplts,))
print('[show_qres] * nTopNSubplts=%r' % (nTopNSubplts,))
print('[show_qres] * nQuerySubplts=%r' % (nQuerySubplts,))
print('[show_qres] * -----')
print('[show_qres] * nGTCols=%r' % (nGTCols,))
print('[show_qres] * -----')
print('[show_qres] * fnum=%r' % (fnum,))
print('[show_qres] * figtitle=%r' % (figtitle,))
print('[show_qres] * max_nCols=%r' % (max_nCols,))
print('[show_qres] * show_query=%r' % (show_query,))
print('[show_qres] * kwargs=%s' % (ut.dict_str(kwargs),))
# HACK:
_color_list = pt.distinct_colors(nTop)
aid2_color = {aid: _color_list[ox] for ox, aid in enumerate(top_aids)}
ranked_aids = cm.get_top_aids()
# Helpers
def _show_query_fn(plotx_shift, rowcols):
""" helper for show_qres """
plotx = plotx_shift + 1
pnum = (rowcols[0], rowcols[1], plotx)
#print('[viz] Plotting Query: pnum=%r' % (pnum,))
_kwshow = dict(draw_kpts=annot_mode)
_kwshow.update(kwargs)
_kwshow['prefix'] = 'q'
_kwshow['pnum'] = pnum
_kwshow['aid2_color'] = aid2_color
_kwshow['draw_ell'] = annot_mode >= 1
viz_chip.show_chip(ibs, cm.qaid, annote=False, qreq_=qreq_, **_kwshow)
def _plot_matches_aids(aid_list, plotx_shift, rowcols):
""" helper for show_qres to draw many aids """
_kwshow = dict(draw_ell=annot_mode, draw_pts=False, draw_lines=annot_mode,
ell_alpha=.5, all_kpts=all_kpts)
_kwshow.update(kwargs)
_kwshow['fnum'] = fnum
_kwshow['in_image'] = in_image
if sidebyside:
# Draw each match side by side the query
_kwshow['draw_ell'] = annot_mode == 1
_kwshow['draw_lines'] = annot_mode >= 1
else:
#print('annot_mode = %r' % (annot_mode,))
_kwshow['draw_ell'] = annot_mode == 1
#_kwshow['draw_pts'] = annot_mode >= 1
#_kwshow['draw_lines'] = False
_kwshow['show_query'] = False
def _show_matches_fn(aid, orank, pnum):
""" Helper function for drawing matches to one aid """
aug = 'rank=%r\n' % orank
_kwshow['pnum'] = pnum
_kwshow['title_aug'] = aug
#draw_ell = annot_mode == 1
#draw_lines = annot_mode >= 1
# If we already are showing the query dont show it here
if sidebyside:
# Draw each match side by side the query
if viz_name_score:
cm.show_single_namematch(qreq_, ibs.get_annot_nids(aid), **_kwshow)
else:
_kwshow['draw_border'] = False
_kwshow['draw_lbl'] = False
_kwshow['notitle'] = True
_kwshow['vert'] = False
cm.show_single_annotmatch(qreq_, aid, **_kwshow)
#viz_matches.show_matches(ibs, cm, aid, qreq_=qreq_, **_kwshow)
else:
# Draw each match by themselves
data_config2_ = None if qreq_ is None else qreq_.get_external_data_config2()
#_kwshow['draw_border'] = kwargs.get('draw_border', True)
#_kwshow['notitle'] = ut.get_argflag(('--no-title', '--notitle'))
viz_chip.show_chip(ibs, aid, annote=False, notitle=True,
data_config2_=data_config2_, **_kwshow)
if DEBUG_SHOW_QRES:
print('[show_qres()] Plotting Chips %s:' % vh.get_aidstrs(aid_list))
if aid_list is None:
return
# Do lazy load before show
#data_config2_ = None if qreq_ is None else qreq_.get_external_data_config2()
tblhack = getattr(qreq_, 'tablename', None)
# HACK FOR HUMPBACKS
# (Also in viz_matches)
if tblhack == 'vsone' or (qreq_ is not None and not qreq_._isnewreq):
# precompute
pass
#ibs.get_annot_chips(aid_list, config2_=data_config2_, ensure=True)
#ibs.get_annot_kpts(aid_list, config2_=data_config2_, ensure=True)
for ox, aid in enumerate(aid_list):
plotx = ox + plotx_shift + 1
pnum = (rowcols[0], rowcols[1], plotx)
oranks = np.where(ranked_aids == aid)[0]
# This pair has no matches between them.
if len(oranks) == 0:
orank = -1
if aid is None:
pt.imshow_null('Failed to find matches\nfor qaid=%r' % (cm.qaid), fnum=fnum, pnum=pnum, fontsize=18)
else:
_show_matches_fn(aid, orank, pnum)
#if DEBUG_SHOW_QRES:
# print('skipping pnum=%r' % (pnum,))
continue
if DEBUG_SHOW_QRES:
print('pnum=%r' % (pnum,))
orank = oranks[0] + 1
_show_matches_fn(aid, orank, pnum)
shift_topN = nGtCells
if nGtSubplts == 1:
nGTCols = 1
if nRows == 0:
pt.imshow_null('[viz_qres] No matches. nRows=0', fnum=fnum)
else:
fig = pt.figure(fnum=fnum, pnum=(nRows, nGTCols, 1), docla=True, doclf=True)
pt.plt.subplot(nRows, nGTCols, 1)
# Plot Query
if show_query:
_show_query_fn(0, (nRows, nGTCols))
# Plot Ground Truth (if given)
_plot_matches_aids(gt_aids, nQuerySubplts, (nRows, nGTCols))
# Plot Results
_plot_matches_aids(top_aids, shift_topN, (nRows, nTopNCols))
figtitle += aug
if failed_to_match:
figtitle += '\n No matches found'
incanvas = kwargs.get('with_figtitle', not vh.NO_LBL_OVERRIDE)
pt.set_figtitle(figtitle, incanvas=incanvas)
# Result Interaction
return fig
if __name__ == '__main__':
"""
CommandLine:
python -m ibeis.viz.viz_qres
python -m ibeis.viz.viz_qres --allexamples
python -m ibeis.viz.viz_qres --allexamples --noface --nosrc
"""
import multiprocessing
multiprocessing.freeze_support() # for win32
import utool as ut # NOQA
ut.doctest_funcs()