diff --git a/wbia/web/apis_query.py b/wbia/web/apis_query.py index 7a782ca94..60e72a418 100644 --- a/wbia/web/apis_query.py +++ b/wbia/web/apis_query.py @@ -907,7 +907,7 @@ def query_chips_graph( query_config_dict={}, echo_query_params=True, cache_images=True, - n=20, + n=12, view_orientation='horizontal', return_summary=True, **kwargs, @@ -1002,6 +1002,7 @@ def convert_to_uuid(nid): name_score_list = cm.name_score_list zipped = sorted(zip(name_score_list, unique_nids), reverse=True) + zipped = [(s, nid) for s, nid in zipped if s > 0] or zipped[:1] n_ = min(n, len(zipped)) zipped = zipped[:n_] logger.info('Top %d names: %r' % (n_, zipped)) @@ -1051,6 +1052,7 @@ def convert_to_uuid(nid): # Get best annotations logger.info('Visualizing annotation matches') zipped = sorted(zip(score_list, daid_list_), reverse=True) + zipped = [(s, daid) for s, daid in zipped if s > 0] or zipped[:1] n_ = min(n, len(zipped)) zipped = zipped[:n_] logger.info('Top %d annots: %r' % (n_, zipped)) @@ -1061,138 +1063,51 @@ def convert_to_uuid(nid): daid_set = list(set(daid_set)) logger.info('Visualizing %d annots: %r' % (len(daid_set), daid_set)) + # HotSpotter (vsmany) needs synchronous heatmask rendering + # because the yellow overlay requires the ChipMatch spatial data. + # All other algorithms (MiewID, PIE, etc.) defer to on-demand + # rendering in /match/thumb/ for faster job completion. + is_hotspotter = proot == 'vsmany' + extern_flag_list = [] for daid in daid_list_: extern_flag = daid in daid_set if extern_flag: - logger.info('Rendering match images to disk for daid=%d' % (daid,)) duuid = ibs.get_annot_uuids(daid) - args = (duuid,) dannot_cache_filepath = join( qannot_cache_filepath, 'dannot_uuid_%s' % args ) ut.ensuredir(dannot_cache_filepath) - cache_filepath_fmtstr = join( - dannot_cache_filepath, 'version_%s_orient_%s.png' - ) - - try: - _, filepath_matches = ensure_review_image( - ibs, - daid, - cm, - qreq_, - view_orientation=view_orientation, - draw_matches=True, - draw_heatmask=False, - use_gradcam=use_gradcam, - ) - except Exception as ex: - filepath_matches = None - extern_flag = 'error' - ut.printex(ex, iswarning=True) - log_render_status( - ibs, - ut.timestamp(), - cm.qaid, - daid, - quuid, - duuid, - cm, - qreq_, - view_orientation, - True, - False, - filepath_matches, - extern_flag, - ) - try: - _, filepath_heatmask = ensure_review_image( - ibs, - daid, - cm, - qreq_, - view_orientation=view_orientation, - draw_matches=False, - draw_heatmask=True, - use_gradcam=use_gradcam, - ) - except Exception as ex: - filepath_heatmask = None - extern_flag = 'error' - ut.printex(ex, iswarning=True) - log_render_status( - ibs, - ut.timestamp(), - cm.qaid, - daid, - quuid, - duuid, - cm, - qreq_, - view_orientation, - False, - True, - filepath_heatmask, - extern_flag, - ) - try: - _, filepath_clean = ensure_review_image( - ibs, - daid, - cm, - qreq_, - view_orientation=view_orientation, - draw_matches=False, - draw_heatmask=False, - use_gradcam=use_gradcam, - ) - except Exception as ex: - filepath_clean = None - extern_flag = 'error' - ut.printex(ex, iswarning=True) - log_render_status( - ibs, - ut.timestamp(), - cm.qaid, - daid, - quuid, - duuid, - cm, - qreq_, - view_orientation, - False, - False, - filepath_clean, - extern_flag, - ) - - if filepath_matches is not None: - args = ( - 'matches', - view_orientation, - ) - cache_filepath = cache_filepath_fmtstr % args - ut.symlink(filepath_matches, cache_filepath, overwrite=True) - - if filepath_heatmask is not None: - args = ( - 'heatmask', - view_orientation, - ) - cache_filepath = cache_filepath_fmtstr % args - ut.symlink(filepath_heatmask, cache_filepath, overwrite=True) - - if filepath_clean is not None: - args = ( - 'clean', - view_orientation, + if is_hotspotter: + cache_filepath_fmtstr = join( + dannot_cache_filepath, 'version_%s_orient_%s.png' ) - cache_filepath = cache_filepath_fmtstr % args - ut.symlink(filepath_clean, cache_filepath, overwrite=True) + try: + _, filepath_heatmask = ensure_review_image( + ibs, + daid, + cm, + qreq_, + view_orientation=view_orientation, + draw_matches=False, + draw_heatmask=True, + use_gradcam=use_gradcam, + ) + except Exception as ex: + filepath_heatmask = None + extern_flag = 'error' + ut.printex(ex, iswarning=True) + + if filepath_heatmask is not None: + args = ( + 'heatmask', + view_orientation, + ) + cache_filepath = cache_filepath_fmtstr % args + ut.symlink(filepath_heatmask, cache_filepath, overwrite=True) extern_flag_list.append(extern_flag) else: @@ -1289,6 +1204,7 @@ def query_chips_graph_match_thumb( ): from io import BytesIO + import cv2 import vtool as vt from flask import send_file from PIL import Image # NOQA @@ -1337,11 +1253,23 @@ def query_chips_graph_match_thumb( version_path = join(dannot_path, 'version_{}_orient_horizontal.png'.format(version)) if not exists(version_path): - message = ( - 'match thumb version is unknown for the given reference %s, query_annot_uuid %s, database_annot_uuid %s' - % (extern_reference, query_annot_uuid, database_annot_uuid) - ) - raise controller_inject.WebMatchThumbException(*args, message=message) + # Render on-demand: stack query + database chips side-by-side + try: + qaid_list = ibs.get_annot_aids_from_uuid([query_annot_uuid]) + daid_list = ibs.get_annot_aids_from_uuid([database_annot_uuid]) + qaid = qaid_list[0] + daid = daid_list[0] + chips = ibs.get_annot_chips([qaid, daid]) + image = vt.stack_image_list(chips) + cv2.imwrite(version_path, image) + logger.info('On-demand render: %s' % (version_path,)) + except Exception as ex: + logger.warning('On-demand render failed: %s' % (ex,)) + message = ( + 'match thumb version is unknown for the given reference %s, query_annot_uuid %s, database_annot_uuid %s' + % (extern_reference, query_annot_uuid, database_annot_uuid) + ) + raise controller_inject.WebMatchThumbException(*args, message=message) # Load image image = vt.imread(version_path, orient='auto')