Source code for ibeis.viz.interact.interact_matches

# -*- coding: utf-8 -*-
"""
Single VsOne Chip Match Interface
For VsMany Interaction

Interaction for looking at matches between a single query and database annotation

Main development file

CommandLine:
    python -m ibeis.viz.interact.interact_matches --test-begin --show

    python -m ibeis.viz.interact.interact_matches --test-show_coverage --show
"""
from __future__ import absolute_import, division, print_function, unicode_literals
import utool as ut
import numpy as np
import plottool as pt
import six
#import guitool
from plottool import draw_func2 as df2
from plottool import viz_featrow
from plottool import interact_helpers as ih
from plottool import plot_helpers as ph
from ibeis import viz
from ibeis.algo.hots import scoring
from ibeis.algo.hots import hstypes
from ibeis.viz import viz_helpers as vh
from ibeis.viz import viz_hough
from ibeis.viz import viz_chip
from plottool import abstract_interaction  # TODO
from ibeis.algo.hots import _pipeline_helpers as plh  # NOQA
from ibeis.viz.interact.interact_chip import ishow_chip
(print, rrr, profile) = ut.inject2(__name__, '[interact_matches]', DEBUG=False)


AbstractInteraction = abstract_interaction.AbstractInteraction


[docs]def testdata_match_interact(**kwargs): """ CommandLine: python -m ibeis.viz.interact.interact_matches --test-testdata_match_interact --show --db PZ_MTEST --qaid 3 Example: >>> # VIZ_DOCTEST >>> from ibeis.viz.interact.interact_matches import * # NOQA >>> import plottool as pt >>> kwargs = {} >>> self = testdata_match_interact(**kwargs) >>> pt.show_if_requested() """ import ibeis qreq_ = ibeis.testdata_qreq_(defaultdb='testdb1', t=['default:Knorm=3']) ibs = qreq_.ibs cm = qreq_.execute()[0] cm.sortself() aid2 = None self = MatchInteraction(ibs, cm, aid2, mode=1, dodraw=False, qreq_=qreq_, **kwargs) return self # TODO inherit from AbstractInteraction
@six.add_metaclass(ut.ReloadingMetaclass)
[docs]class MatchInteraction(object): """ Plots a chip result and sets up callbacks for interaction. SeeAlso: plottool.interact_matches.MatchInteraction2 """ def __init__(self, ibs, cm, aid2=None, fnum=None, figtitle='Match Interaction', same_fig=True, qreq_=None, **kwargs): self.qres = cm self.ibs = ibs self.cm = cm self.qreq_ = qreq_ self.fnum = pt.ensure_fnum(fnum) # Unpack Args if aid2 is None: index = 0 # FIXME: no sortself cm.sortself() self.rank = index else: index = cm.daid2_idx.get(aid2, None) # TODO: rank? self.rank = None if index is not None: self.qaid = self.cm.qaid self.daid = self.cm.daid_list[index] self.fm = self.cm.fm_list[index] self.fk = self.cm.fk_list[index] self.fsv = self.cm.fsv_list[index] if self.cm.fs_list is None: fs_list = self.cm.get_fsv_prod_list() else: fs_list = self.cm.fs_list self.fs = None if fs_list is None else fs_list[index] self.score = None if self.cm.score_list is None else self.cm.score_list[index] self.H1 = None if self.cm.H_list is None else cm.H_list[index] else: self.qaid = self.cm.qaid self.daid = aid2 self.fm = np.empty((0, 2), dtype=hstypes.FM_DTYPE) self.fk = np.empty(0, dtype=hstypes.FK_DTYPE) self.fsv = np.empty((0, 2), dtype=hstypes.FS_DTYPE) self.fs = np.empty(0, dtype=hstypes.FS_DTYPE) self.score = None self.H1 = None # Read properties self.query_config2_ = (None if self.qreq_ is None else self.qreq_.get_external_query_config2()) self.data_config2_ = (None if self.qreq_ is None else self.qreq_.get_external_data_config2()) self.rchip1 = vh.get_chips(ibs, [self.qaid], config2_=self.query_config2_)[0] self.rchip2 = vh.get_chips(ibs, [self.daid], config2_=self.data_config2_)[0] # Begin Interaction # call doclf docla and make figure self.fig = ih.begin_interaction('matches', self.fnum) self.xywh2_ptr = [None] self.mode = kwargs.pop('mode', 0) # New state vars self.same_fig = same_fig self.use_homog = False self.vert = kwargs.pop('vert', None) self.mx = kwargs.pop('mx', None) self.last_fx = 0 self.fnum2 = pt.next_fnum() self.figtitle = figtitle self.kwargs = kwargs abstract_interaction.register_interaction(self) ut.inject_func_as_method(self, AbstractInteraction.append_button.im_func) ut.inject_func_as_method(self, AbstractInteraction.show_popup_menu.im_func) self.scope = [] if not kwargs.get('nobegin', False): dodraw = kwargs.get('dodraw', True) self.begin(dodraw=dodraw)
[docs] def begin(self, dodraw=True): r""" CommandLine: python -m ibeis.viz.interact.interact_matches --test-begin python -m ibeis.viz.interact.interact_matches --test-begin --show Example: >>> # DISABLE_DOCTEST >>> from ibeis.viz.interact.interact_matches import * # NOQA >>> self = testdata_match_interact() >>> self.begin(dodraw=False) >>> pt.show_if_requested() """ if self.mx is None: self.chipmatch_view() else: self.select_ith_match(self.mx) self.set_callbacks() # FIXME: this should probably not be called here if dodraw: ph.draw() # ph-> adjust stuff draw -> fig_presenter.draw -> all figures show
[docs] def set_callbacks(self): # TODO: view probchip #guitool.connect_context_menu(self.fig.canvas, options) ih.connect_callback(self.fig, 'button_press_event', self.on_click) # Callback
[docs] def on_click(self, event): aid = self.daid qaid = self.qaid ibs = self.ibs xywh2_ptr = self.xywh2_ptr print('[inter] clicked matches') if event is None: return button = event.button is_right_click = button == 3 # Out of axes click (x, y, ax) = (event.xdata, event.ydata, event.inaxes) if None in [x, y, ax]: in_axis = False if not is_right_click: print('... out of axis') self.chipmatch_view() viz.draw() return else: in_axis = True if in_axis: viztype = vh.get_ibsdat(ax, 'viztype', '') is_match_type = viztype in ['matches', 'multi_match'] print('[ir] viztype=%r ' % viztype) else: is_match_type = False viztype = '' if is_right_click: from ibeis.gui import inspect_gui options = [] if is_match_type: options += inspect_gui.get_aidpair_context_menu_options( self.ibs, self.qaid, self.daid, self.cm, qreq_=self.qreq_, #update_callback=self.show_page, #backend_callback=None, aid_list=aid_list) ) options += [ ('Toggle same_fig', self.toggle_samefig), ('Toggle vert', self.toggle_vert), ('query last feature', self.query_last_feature), ('show each chip', self.show_each_chip), ('show each distinctiveness chip', self.show_each_dstncvs_chip), ('show each foreground weight chip', self.show_each_fgweight_chip), ('show each probchip', self.show_each_probchip), ('show coverage', self.show_coverage), #('show each probchip', self.query_last_feature), ] #options.append(('name_interaction', self.name_interaction)) if self.H1 is not None: options.append(('Toggle homog', self.toggle_homog)) if ut.is_developer(): options.append(('dev_reload', self.dev_reload)) options.append(('dev_embed', self.dev_embed)) #options.append(('cancel', lambda: print('cancel'))) self.show_popup_menu(options, event) return if in_axis: key = '' if event.key is None else event.key print('key=%r ' % key) ctrl_down = key.find('control') == 0 # Click in match axes if is_match_type and ctrl_down: # Ctrl-Click print('.. control click') return self.sv_view() elif is_match_type: if len(self.fm) == 0: print('[inter] no feature matches to click') else: # Normal Click # Select nearest feature match to the click kpts1 = ibs.get_annot_kpts([qaid], config2_=self.query_config2_)[0] kpts2 = ibs.get_annot_kpts([aid], config2_=self.data_config2_)[0] kpts1_m = kpts1[self.fm.T[0]] kpts2_m = kpts2[self.fm.T[1]] x2, y2, w2, h2 = xywh2_ptr[0] _mx1, _dist1 = ut.nearest_point(x, y, kpts1_m) _mx2, _dist2 = ut.nearest_point(x - x2, y - y2, kpts2_m) mx = _mx1 if _dist1 < _dist2 else _mx2 (fx1, fx2) = self.fm[mx] print('... clicked mx=%r' % mx) print('... fx1, fx2 = %r, %r' % (fx1, fx2,)) self.select_ith_match(mx) elif viztype in ['warped', 'unwarped']: print('clicked at patch') ut.print_dict(ph.get_plotdat_dict(ax)) hs_aid = vh.get_ibsdat(ax, 'aid', None) hs_fx = vh.get_ibsdat(ax, 'fx', None) #hs_aid = ax.__dict__.get('_hs_aid', None) #hs_fx = ax.__dict__.get('_hs_fx', None) print('hs_fx = %r' % (hs_fx,)) print('hs_aid = %r' % (hs_aid,)) if hs_aid is not None and viztype == 'unwarped': ishow_chip(ibs, hs_aid, fx=hs_fx, fnum=df2.next_fnum()) elif hs_aid is not None and viztype == 'warped': viz.show_keypoint_gradient_orientations(ibs, hs_aid, hs_fx, fnum=df2.next_fnum()) elif viztype.startswith('colorbar'): # Hack to get a specific scoring feature sortx = self.fs.argsort() idx = np.clip(int(np.round(y * len(sortx))), 0, len(sortx) - 1) mx = sortx[idx] (fx1, fx2) = self.fm[mx] (fx1, fx2) = self.fm[mx] print('... selected score at rank idx=%r' % (idx,)) print('... selected score with fs=%r' % (self.fs[mx],)) print('... resolved to mx=%r' % mx) print('... fx1, fx2 = %r, %r' % (fx1, fx2,)) self.select_ith_match(mx) else: print('...Unknown viztype: %r' % viztype) viz.draw()
[docs] def chipmatch_view(self, pnum=(1, 1, 1), **kwargs_): """ just visualizes the matches using some type of lines CommandLine: python -m ibeis.viz.interact.interact_matches --test-chipmatch_view --show Example: >>> # DISABLE_DOCTEST >>> from ibeis.viz.interact.interact_matches import * # NOQA >>> self = testdata_match_interact() >>> self.chipmatch_view() >>> pt.show_if_requested() """ ibs = self.ibs aid = self.daid qaid = self.qaid fnum = self.fnum figtitle = self.figtitle xywh2_ptr = self.xywh2_ptr # drawing mode draw: with/without lines/feats mode = self.mode draw_ell = mode >= 1 draw_lines = mode == 2 self.mode = (self.mode + 1) % 3 df2.figure(fnum=fnum, docla=True, doclf=True) show_matches_kw = self.kwargs.copy() show_matches_kw.update( dict(fnum=fnum, pnum=pnum, draw_lines=draw_lines, draw_ell=draw_ell, colorbar_=True, vert=self.vert)) show_matches_kw.update(kwargs_) if self.use_homog: show_matches_kw['H1'] = self.H1 #show_matches_kw['score'] = self.score show_matches_kw['rawscore'] = self.score #ut.embed() show_matches_kw['aid2_raw_rank'] = self.rank tup = viz.viz_matches.show_matches2(ibs, self.qaid, self.daid, self.fm, self.fs, qreq_=self.qreq_, **show_matches_kw) ax, xywh1, xywh2 = tup xywh2_ptr[0] = xywh2 df2.set_figtitle(figtitle + ' ' + vh.get_vsstr(qaid, aid)) # Draw clicked selection
[docs] def select_ith_match(self, mx): """ Selects the ith match and visualizes and prints information concerning features weights, keypoint details, and sift descriptions Args: mx (int) - the ith match to visualize qaid (int) - query annotation id aid (int) - database annotation id CommandLine: python -m ibeis.viz.interact.interact_matches --test-select_ith_match --show Example: >>> # DISABLE_DOCTEST >>> from ibeis.viz.interact.interact_matches import * # NOQA >>> self = testdata_match_interact(mx=1) >>> pt.show_if_requested() """ ibs = self.ibs qaid = self.qaid aid = self.daid fnum = self.fnum figtitle = self.figtitle rchip1 = self.rchip1 rchip2 = self.rchip2 aid = self.daid same_fig = self.same_fig self.mx = mx print('+--- SELECT --- ') print('qaid=%r, daid=%r' % (qaid, aid)) print('... selecting mx-th=%r feature match' % mx) if False: print('score stats:') print(ut.get_stats_str(self.fsv, axis=0, newlines=True)) print('fsv[mx] = %r' % (self.fsv[mx],)) print('fs[mx] = %r' % (self.fs[mx],)) """ # test feature weights of actual chips fx1, fx2 = fm[mx] daid = aid ibs.get_annot_fgweights([daid])[0][fx2] ibs.get_annot_fgweights([qaid])[0][fx1] """ #---------------------- # Get info for the select_ith_match plot self.mode = 1 # Get the mx-th feature match fx1, fx2 = self.fm[mx] fscore2 = self.fs[mx] fk2 = self.fk[mx] kpts1 = ibs.get_annot_kpts([self.qaid], config2_=self.query_config2_)[0] kpts2 = ibs.get_annot_kpts([self.daid], config2_=self.data_config2_)[0] desc1 = ibs.get_annot_vecs([self.qaid], config2_=self.query_config2_)[0] desc2 = ibs.get_annot_vecs([self.daid], config2_=self.data_config2_)[0] kp1, kp2 = kpts1[fx1], kpts2[fx2] sift1, sift2 = desc1[fx1], desc2[fx2] info1 = '\nquery' info2 = '\nk=%r fscore=%r' % (fk2, fscore2) #last_state.last_fx = fx1 self.last_fx = fx1 # Extracted keypoints to draw extracted_list = [(rchip1, kp1, sift1, fx1, self.qaid, info1), (rchip2, kp2, sift2, fx2, self.daid, info2)] # Normalizng Keypoint #if hasattr(cm, 'filt2_meta') and 'lnbnn' in cm.filt2_meta: # qfx2_norm = cm.filt2_meta['lnbnn'] # # Normalizing chip and feature # (aid3, fx3, normk) = qfx2_norm[fx1] # rchip3 = ibs.get_annot_chips(aid3) # kp3 = ibs.get_annot_kpts(aid3)[fx3] # sift3 = ibs.get_annot_vecs(aid3)[fx3] # info3 = '\nnorm %s k=%r' % (vh.get_aidstrs(aid3), normk) # extracted_list.append((rchip3, kp3, sift3, fx3, aid3, info3)) #else: # pass # print('WARNING: meta doesnt exist') #---------------------- # Draw the select_ith_match plot nRows, nCols = len(extracted_list) + same_fig, 3 # Draw matching chips and features sel_fm = np.array([(fx1, fx2)]) pnum1 = (nRows, 1, 1) if same_fig else (1, 1, 1) vert = self.vert if self.vert is not None else False self.chipmatch_view(pnum1, ell_alpha=.4, ell_linewidth=1.8, colors=df2.BLUE, sel_fm=sel_fm, vert=vert) # Draw selected feature matches px = nCols * same_fig # plot offset prevsift = None if not same_fig: #fnum2 = fnum + len(viz.FNUMS) fnum2 = self.fnum2 fig2 = df2.figure(fnum=fnum2, docla=True, doclf=True) else: fnum2 = fnum for (rchip, kp, sift, fx, aid, info) in extracted_list: px = viz_featrow.draw_feat_row(rchip, fx, kp, sift, fnum2, nRows, nCols, px, prevsift=prevsift, aid=aid, info=info) prevsift = sift if not same_fig: ih.connect_callback(fig2, 'button_press_event', self.on_click) df2.set_figtitle(figtitle + vh.get_vsstr(qaid, aid))
[docs] def sv_view(self, dodraw=True): """ spatial verification view """ #fnum = viz.FNUMS['special'] aid = self.daid fnum = pt.next_fnum() fig = df2.figure(fnum=fnum, docla=True, doclf=True) ih.disconnect_callback(fig, 'button_press_event') viz.viz_sver.show_sver(self.ibs, self.qaid, aid2=aid, fnum=fnum) if dodraw: viz.draw()
[docs] def show_coverage(self, dodraw=True): """ CommandLine: python -m ibeis.viz.interact.interact_matches --test-show_coverage --show python -m ibeis.viz.interact.interact_matches --test-show_coverage Example: >>> # DISABLE_DOCTEST >>> from ibeis.viz.interact.interact_matches import * # NOQA >>> self = testdata_match_interact(mx=1) >>> self.show_coverage(dodraw=False) >>> pt.show_if_requested() """ masks_list = scoring.get_masks(self.qreq_, self.cm) scoring.show_coverage_mask(self.qreq_, self.cm, masks_list) if dodraw: viz.draw()
[docs] def show_each_chip(self): viz_chip.show_chip(self.ibs, self.qaid, fnum=pt.next_fnum(), nokpts=True) viz_chip.show_chip(self.ibs, self.daid, fnum=pt.next_fnum(), nokpts=True) viz.draw()
[docs] def show_each_fgweight_chip(self): viz_chip.show_chip(self.ibs, self.qaid, fnum=pt.next_fnum(), weight_label='fg_weights') viz_chip.show_chip(self.ibs, self.daid, fnum=pt.next_fnum(), weight_label='fg_weights') viz.draw()
[docs] def show_each_dstncvs_chip(self, dodraw=True): """ CommandLine: python -m ibeis.viz.interact.interact_matches --test-show_each_dstncvs_chip --show Example: >>> # DISABLE_DOCTEST >>> from ibeis.viz.interact.interact_matches import * # NOQA >>> self = testdata_match_interact(mx=1) >>> self.show_each_dstncvs_chip(dodraw=False) >>> pt.show_if_requested() """ dstncvs1, dstncvs2 = scoring.get_kpts_distinctiveness(self.ibs, [self.qaid, self.daid]) print('dstncvs1_stats = ' + ut.get_stats_str(dstncvs1)) print('dstncvs2_stats = ' + ut.get_stats_str(dstncvs2)) weight_label = 'dstncvs' showkw = dict(weight_label=weight_label, ell=False, pts=True) viz_chip.show_chip(self.ibs, self.qaid, weights=dstncvs1, fnum=pt.next_fnum(), **showkw) viz_chip.show_chip(self.ibs, self.daid, weights=dstncvs2, fnum=pt.next_fnum(), **showkw) if dodraw: viz.draw()
[docs] def show_each_probchip(self): viz_hough.show_probability_chip(self.ibs, self.qaid, fnum=pt.next_fnum()) viz_hough.show_probability_chip(self.ibs, self.daid, fnum=pt.next_fnum()) viz.draw()
[docs] def dev_reload(self): ih.disconnect_callback(self.fig, 'button_press_event') self.rrr() self.set_callbacks()
[docs] def dev_embed(self): ut.embed()
[docs] def toggle_vert(self): self.vert = not self.vert if self.mx is not None: self.select_ith_match(self.mx)
[docs] def toggle_homog(self): self.use_homog = not self.use_homog self.chipmatch_view() viz.draw()
[docs] def toggle_samefig(self): self.same_fig = not self.same_fig if self.mx is not None: self.select_ith_match(self.mx) pt.update()
[docs] def query_last_feature(self): ibs = self.ibs qaid = self.qaid viz.show_nearest_descriptors(ibs, qaid, self.last_fx, df2.next_fnum(), qreq_=self.qreq_, draw_chip=True) fig3 = df2.gcf() ih.connect_callback(fig3, 'button_press_event', self.on_click) viz.draw() #df2.update()
if __name__ == '__main__': """ CommandLine: python -m ibeis.viz.interact.interact_matches python -m ibeis.viz.interact.interact_matches --allexamples python -m ibeis.viz.interact.interact_matches --allexamples --noface --nosrc """ import multiprocessing multiprocessing.freeze_support() # for win32 import utool as ut # NOQA ut.doctest_funcs()