Exemple #1
0
def get_namescore_nonvoting_feature_flags(fm_list, fs_list, dnid_list, name_groupxs, kpts1=None):
    r"""
    DEPRICATE

    fm_list = [fm[:min(len(fm), 10)] for fm in fm_list]
    fs_list = [fs[:min(len(fs), 10)] for fs in fs_list]
    """
    fx1_list = [fm.T[0] for fm in fm_list]
    # Group annotation matches by name
    name_grouped_fx1_list = vt.apply_grouping_(fx1_list, name_groupxs)
    name_grouped_fs_list  = vt.apply_grouping_(fs_list,  name_groupxs)
    # Stack up all matches to a particular name, keep track of original indicies via offets
    name_invertable_flat_fx1_list = list(map(ut.invertible_flatten2_numpy, name_grouped_fx1_list))
    name_grouped_fx1_flat = ut.get_list_column(name_invertable_flat_fx1_list, 0)
    name_grouped_invertable_cumsum_list = ut.get_list_column(name_invertable_flat_fx1_list, 1)
    name_grouped_fs_flat = list(map(np.hstack, name_grouped_fs_list))
    if kpts1 is not None:
        xys1_ = vt.get_xys(kpts1).T
        kpts_xyid_list = vt.compute_unique_data_ids(xys1_)
        # Make nested group for every name by query feature index (accounting for duplicate orientation)
        name_grouped_comboid_flat = list(kpts_xyid_list.take(fx1) for fx1 in name_grouped_fx1_flat)
        xyid_groupxs_list = list(vt.group_indices(xyid_flat)[1] for xyid_flat in name_grouped_comboid_flat)
        name_group_fx1_groupxs_list = xyid_groupxs_list
    else:
        # Make nested group for every name by query feature index
        fx1_groupxs_list = [vt.group_indices(fx1_flat)[1] for fx1_flat in name_grouped_fx1_flat]
        name_group_fx1_groupxs_list = fx1_groupxs_list
    name_grouped_fid_grouped_fs_list = [
        vt.apply_grouping(fs_flat, fid_groupxs)
        for fs_flat, fid_groupxs in zip(name_grouped_fs_flat, name_group_fx1_groupxs_list)
    ]

    # Flag which features are valid in this grouped space. Only one keypoint should be able to vote
    # for each group
    name_grouped_fid_grouped_isvalid_list = [
        np.array([fs_group.max() == fs_group for fs_group in fid_grouped_fs_list])
        for fid_grouped_fs_list in name_grouped_fid_grouped_fs_list
    ]

    # Go back to being grouped only in name space
    #dtype = np.bool
    name_grouped_isvalid_flat_list = [
        vt.invert_apply_grouping2(fid_grouped_isvalid_list, fid_groupxs, dtype=np.bool)
        for fid_grouped_isvalid_list, fid_groupxs in zip(name_grouped_fid_grouped_isvalid_list, name_group_fx1_groupxs_list)
    ]

    name_grouped_isvalid_unflat_list = [
        ut.unflatten2(isvalid_flat, invertable_cumsum_list)
        for isvalid_flat, invertable_cumsum_list in zip(name_grouped_isvalid_flat_list, name_grouped_invertable_cumsum_list)
    ]

    # Reports which features were valid in name scoring for every annotation
    featflag_list = vt.invert_apply_grouping(name_grouped_isvalid_unflat_list, name_groupxs)
    return featflag_list
Exemple #2
0
def get_namescore_nonvoting_feature_flags(fm_list, fs_list, dnid_list, name_groupxs, kpts1=None):
    r"""
    fm_list = [fm[:min(len(fm), 10)] for fm in fm_list]
    fs_list = [fs[:min(len(fs), 10)] for fs in fs_list]
    """
    fx1_list = [fm.T[0] for fm in fm_list]
    # Group annotation matches by name
    name_grouped_fx1_list = vt.apply_grouping_(fx1_list, name_groupxs)
    name_grouped_fs_list  = vt.apply_grouping_(fs_list,  name_groupxs)
    # Stack up all matches to a particular name, keep track of original indicies via offets
    name_invertable_flat_fx1_list = list(map(ut.invertible_flatten2_numpy, name_grouped_fx1_list))
    name_grouped_fx1_flat = ut.get_list_column(name_invertable_flat_fx1_list, 0)
    name_grouped_invertable_cumsum_list = ut.get_list_column(name_invertable_flat_fx1_list, 1)
    name_grouped_fs_flat = list(map(np.hstack, name_grouped_fs_list))
    if kpts1 is not None:
        xys1_ = vt.get_xys(kpts1).T
        kpts_xyid_list = vt.compute_unique_data_ids(xys1_)
        # Make nested group for every name by query feature index (accounting for duplicate orientation)
        name_grouped_xyid_flat = list(kpts_xyid_list.take(fx1) for fx1 in name_grouped_fx1_flat)
        xyid_groupxs_list = list(vt.group_indices(xyid_flat)[1] for xyid_flat in name_grouped_xyid_flat)
        name_group_fx1_groupxs_list = xyid_groupxs_list
    else:
        # Make nested group for every name by query feature index
        fx1_groupxs_list = [vt.group_indices(fx1_flat)[1] for fx1_flat in name_grouped_fx1_flat]
        name_group_fx1_groupxs_list = fx1_groupxs_list
    name_grouped_fid_grouped_fs_list = [
        vt.apply_grouping(fs_flat, fid_groupxs)
        for fs_flat, fid_groupxs in zip(name_grouped_fs_flat, name_group_fx1_groupxs_list)
    ]

    # Flag which features are valid in this grouped space. Only one keypoint should be able to vote
    # for each group
    name_grouped_fid_grouped_isvalid_list = [
        np.array([fs_group.max() == fs_group for fs_group in fid_grouped_fs_list])
        for fid_grouped_fs_list in name_grouped_fid_grouped_fs_list
    ]

    # Go back to being grouped only in name space
    #dtype = np.bool
    name_grouped_isvalid_flat_list = [
        vt.invert_apply_grouping2(fid_grouped_isvalid_list, fid_groupxs, dtype=np.bool)
        for fid_grouped_isvalid_list, fid_groupxs in zip(name_grouped_fid_grouped_isvalid_list, name_group_fx1_groupxs_list)
    ]

    name_grouped_isvalid_unflat_list = [
        ut.unflatten2(isvalid_flat, invertable_cumsum_list)
        for isvalid_flat, invertable_cumsum_list in zip(name_grouped_isvalid_flat_list, name_grouped_invertable_cumsum_list)
    ]

    # Reports which features were valid in name scoring for every annotation
    featflag_list = vt.invert_apply_grouping(name_grouped_isvalid_unflat_list, name_groupxs)
    return featflag_list
Exemple #3
0
def show_multichip_match(rchip1,
                         rchip2_list,
                         kpts1,
                         kpts2_list,
                         fm_list,
                         fs_list,
                         featflag_list,
                         fnum=None,
                         pnum=None,
                         **kwargs):
    """
    move to df2
    rchip = rchip1
    H = H1 = None
    target_wh = None

    """
    import vtool.image as gtool
    import plottool as pt
    import numpy as np
    import vtool as vt
    kwargs = kwargs.copy()

    colorbar_ = kwargs.pop('colorbar_', True)
    stack_larger = kwargs.pop('stack_larger', False)
    # mode for features disabled by name scoring
    NONVOTE_MODE = kwargs.get('nonvote_mode', 'filter')

    def preprocess_chips(rchip, H, target_wh):
        rchip_ = rchip if H is None else gtool.warpHomog(rchip, H, target_wh)
        return rchip_

    if fnum is None:
        fnum = pt.next_fnum()

    target_wh1 = None
    H1 = None
    rchip1_ = preprocess_chips(rchip1, H1, target_wh1)
    # Hack to visually identify the query
    rchip1_ = vt.draw_border(rchip1_,
                             out=rchip1_,
                             thickness=15,
                             color=(pt.UNKNOWN_PURP[0:3] * 255).astype(
                                 np.uint8).tolist())
    wh1 = gtool.get_size(rchip1_)
    rchip2_list_ = [
        preprocess_chips(rchip2, None, wh1) for rchip2 in rchip2_list
    ]
    wh2_list = [gtool.get_size(rchip2) for rchip2 in rchip2_list_]

    num = 0 if len(rchip2_list) < 3 else 1
    #vert = True if len(rchip2_list) > 1 else False
    vert = True if len(rchip2_list) > 1 else None
    #num = 0

    if False and kwargs.get('fastmode', False):
        # This doesn't actually help the speed very much
        stackkw = dict(
            # Hack draw results faster Q
            #initial_sf=.4,
            #initial_sf=.9,
            use_larger=stack_larger,
            #use_larger=True,
        )
    else:
        stackkw = dict()
    #use_larger = True
    #vert = kwargs.get('fastmode', False)

    match_img, offset_list, sf_list = vt.stack_image_list_special(rchip1_,
                                                                  rchip2_list_,
                                                                  num=num,
                                                                  vert=vert,
                                                                  **stackkw)
    wh_list = np.array(ut.flatten([[wh1], wh2_list])) * sf_list

    offset1 = offset_list[0]
    wh1 = wh_list[0]
    sf1 = sf_list[0]

    fig, ax = pt.imshow(match_img, fnum=fnum, pnum=pnum)

    if kwargs.get('show_matches', True):
        ut.flatten(fs_list)
        #ut.embed()
        flat_fs, cumlen_list = ut.invertible_flatten2(fs_list)
        flat_colors = pt.scores_to_color(np.array(flat_fs), 'hot')
        colors_list = ut.unflatten2(flat_colors, cumlen_list)
        for _tup in zip(offset_list[1:], wh_list[1:], sf_list[1:], kpts2_list,
                        fm_list, fs_list, featflag_list, colors_list):
            offset2, wh2, sf2, kpts2, fm2_, fs2_, featflags, colors = _tup
            xywh1 = (offset1[0], offset1[1], wh1[0], wh1[1])
            xywh2 = (offset2[0], offset2[1], wh2[0], wh2[1])
            #colors = pt.scores_to_color(fs2)
            if kpts1 is not None and kpts2 is not None:
                if NONVOTE_MODE == 'filter':
                    fm2 = fm2_.compress(featflags, axis=0)
                    fs2 = fs2_.compress(featflags, axis=0)
                elif NONVOTE_MODE == 'only':
                    fm2 = fm2_.compress(np.logical_not(featflags), axis=0)
                    fs2 = fs2_.compress(np.logical_not(featflags), axis=0)
                else:
                    # TODO: optional coloring of nonvotes instead
                    fm2 = fm2_
                    fs2 = fs2_
                pt.plot_fmatch(xywh1,
                               xywh2,
                               kpts1,
                               kpts2,
                               fm2,
                               fs2,
                               fm_norm=None,
                               H1=None,
                               H2=None,
                               scale_factor1=sf1,
                               scale_factor2=sf2,
                               colorbar_=False,
                               colors=colors,
                               **kwargs)
        if colorbar_:
            pt.colorbar(flat_fs, flat_colors)
    bbox_list = [(x, y, w, h) for (x, y), (w, h) in zip(offset_list, wh_list)]
    return offset_list, sf_list, bbox_list
def test_zotero_sql():
    r"""
    "C:\Program Files (x86)\Mozilla Firefox\firefox.exe"
    "C:\Program Files (x86)\Mozilla Firefox\firefox.exe" -profile "C:\Users\joncrall\AppData\Roaming\Mozilla\Firefox\Profiles\7kadig32.default" -repl 4242

    References:
        http://www.cogsci.nl/blog/tutorials/97-writing-a-command-line-zotero-client-in-9-lines-of-code
        https://forums.zotero.org/discussion/2919/command-line-export-to-bib-file/
        http://www.curiousjason.com/zoterotobibtex.html

        https://addons.mozilla.org/en-US/firefox/addon/mozrepl/

        # bibtex plugin
        https://github.com/ZotPlus/zotero-better-bibtex

        https://groups.google.com/forum/#!forum/zotero-dev

    Ignore:
        C:\Users\joncrall\AppData\Roaming\Zotero\Zotero\Profiles\xrmkwlkz.default\zotero\translators
    """

    cur = zotero.cur   # NOQA
    #ut.rrrr()
    # ENTIRE DATABASE INFO
    ut.print_database_structure(cur)

    tablename_list = ut.get_tablenames(cur)
    colinfos_list = [ut.get_table_columninfo_list(cur, tablename) for tablename in tablename_list]   # NOQA
    numrows_list = [ut.get_table_num_rows(cur, tablename) for tablename in tablename_list]    # NOQA

    tablename = 'items'
    colnames = ('itemID',)   # NOQA
    colinfo_list = ut.get_table_columninfo_list(cur, tablename)  # NOQA

    itemtype_id_list = ut.get_table_rows(cur, 'items', ('itemTypeID',))

    ut.get_table_columninfo_list(cur, 'itemTypeFields')

    ut.get_table_rows(cur, 'itemTypeFields', ('fieldID',), where='itemTypeID=?', params=itemtype_ids)   # NOQA
    ut.get_table_rows(cur, 'itemTypeFields', ('orderIndex',), where='itemTypeID=?', params=itemtype_ids)   # NOQA

    ut.get_table_rows(cur, 'itemTypeFields', ('',), where='itemTypeID=?', params=itemtype_ids)   # NOQA

    itemData   # NOQA

    # Item Table INFO
    ut.get_table_columninfo_list(cur, 'tags')
    ut.get_table_columninfo_list(cur, 'items')
    ut.get_table_columninfo_list(cur, 'itemTypeFields')
    ut.get_table_columninfo_list(cur, 'itemData')
    ut.get_table_columninfo_list(cur, 'itemDataValues')
    ut.get_table_columninfo_list(cur, 'fields')
    ut.get_table_columninfo_list(cur, 'fieldsCombined')

    ut.get_table_rows(cur, 'fields', ('fieldName',))

    # The ID of each item in the database
    itemid_list = ut.get_table_rows(cur, 'items', ('itemID',))
    # The type of each item
    itemtype_id_list = ut.get_list_column(ut.get_table_rows(cur, 'items', ('itemTypeID',), where='itemID=?', params=itemid_list), 0)

    # The different types of items
    itemtype_ids = list(set(itemtype_id_list))

    # The fields of each item type
    fieldids_list_ = ut.get_table_rows(cur, 'itemTypeFields', ('fieldID',), where='itemTypeID=?', params=itemtype_ids)
    orderids_list_ = ut.get_table_rows(cur, 'itemTypeFields', ('orderIndex',), where='itemTypeID=?', params=itemtype_ids)
    fieldids_list = [ut.sortedby(f, o) for f, o in zip(fieldids_list_, orderids_list_)]

    itemtypeid2_fields = dict(zip(itemtype_ids, fieldids_list))

    itemid_fieldids_list = [[(itemID[0], fieldID[0]) for fieldID in itemtypeid2_fields[itemTypeID]] for itemID, itemTypeID in list(zip(itemid_list, itemtype_id_list))[0:7]]
    flat_list, cumsum_list = ut.invertible_flatten2(itemid_fieldids_list)
    # Get field values
    flat_valueID_list = ut.get_table_rows(cur, 'itemData', ('valueID',), where='itemID=? and fieldID=?', params=flat_list)
    valueIDs_list = ut.unflatten2(flat_valueID_list, cumsum_list)

    filtered_itemid_fieldids_list = [[if_ for if_, v in zip(ifs, vs) if len(v) > 0] for ifs, vs in zip(itemid_fieldids_list, valueIDs_list)]

    filtered_flat_list, filtered_cumsum_list = ut.invertible_flatten2(filtered_itemid_fieldids_list)
    # Get field values
    filt_flat_valueID_list = ut.get_table_rows(cur, 'itemData', ('valueID',), where='itemID=? and fieldID=?', params=filtered_flat_list)
    filt_flat_valueID_list_ = ut.get_list_column(filt_flat_valueID_list, 0)
    filt_flat_fieldname_list = ut.get_table_rows(cur, 'fields', ('fieldName',), where='fieldID=?', params=ut.get_list_column(filtered_flat_list, [1]))
    filt_flat_value_list = ut.get_table_rows(cur, 'itemDataValues', ('value',), where='valueID=?', params=filt_flat_valueID_list_)   # NOQA
    #

    filt_fieldname_list = ut.unflatten2(filt_flat_fieldname_list, filtered_cumsum_list)   # NOQA
    filt_valueIDs_list = ut.unflatten2(filt_flat_valueID_list, filtered_cumsum_list)  # NOQA

    ut.get_table_rows(cur, 'itemTypeFields', ('fieldID', 'orderIndex'), where='itemTypeID=?', params=itemtype_ids)

    all_values = ut.get_list_column(ut.get_table_rows(cur, 'itemDataValues', ('value',)), 0)
    import re
    import six
    for value in all_values:
        if isinstance(value, six.string_types) and re.search('CVPR', value):
            print(value)
Exemple #5
0
def show_multichip_match(rchip1, rchip2_list, kpts1, kpts2_list, fm_list,
                         fs_list, featflag_list, fnum=None, pnum=None,
                         **kwargs):
    """
    move to df2
    rchip = rchip1
    H = H1 = None
    target_wh = None

    """
    import vtool.image as gtool
    import plottool as pt
    import numpy as np
    import vtool as vt
    kwargs = kwargs.copy()

    colorbar_ = kwargs.pop('colorbar_', True)
    stack_larger = kwargs.pop('stack_larger', False)
    # mode for features disabled by name scoring
    NONVOTE_MODE = kwargs.get('nonvote_mode', 'filter')

    def preprocess_chips(rchip, H, target_wh):
        rchip_ = rchip if H is None else gtool.warpHomog(rchip, H, target_wh)
        return rchip_

    if fnum is None:
        fnum = pt.next_fnum()

    target_wh1 = None
    H1 = None
    rchip1_ = preprocess_chips(rchip1, H1, target_wh1)
    # Hack to visually identify the query
    rchip1_ = vt.draw_border(
        rchip1_, out=rchip1_, thickness=15,
        color=(pt.UNKNOWN_PURP[0:3] * 255).astype(np.uint8).tolist())
    wh1 = gtool.get_size(rchip1_)
    rchip2_list_ = [preprocess_chips(rchip2, None, wh1)
                    for rchip2 in rchip2_list]
    wh2_list = [gtool.get_size(rchip2) for rchip2 in rchip2_list_]

    num = 0 if len(rchip2_list) < 3 else 1
    #vert = True if len(rchip2_list) > 1 else False
    vert = True if len(rchip2_list) > 1 else None
    #num = 0

    if False and kwargs.get('fastmode', False):
        # This doesn't actually help the speed very much
        stackkw = dict(
            # Hack draw results faster Q
            #initial_sf=.4,
            #initial_sf=.9,
            use_larger=stack_larger,
            #use_larger=True,
        )
    else:
        stackkw = dict()
    #use_larger = True
    #vert = kwargs.get('fastmode', False)

    match_img, offset_list, sf_list = vt.stack_image_list_special(rchip1_,
                                                                  rchip2_list_,
                                                                  num=num,
                                                                  vert=vert,
                                                                  **stackkw)
    wh_list = np.array(ut.flatten([[wh1], wh2_list])) * sf_list

    offset1 = offset_list[0]
    wh1 = wh_list[0]
    sf1 = sf_list[0]

    fig, ax = pt.imshow(match_img, fnum=fnum, pnum=pnum)

    if kwargs.get('show_matches', True):
        ut.flatten(fs_list)
        #ut.embed()
        flat_fs, cumlen_list = ut.invertible_flatten2(fs_list)
        flat_colors = pt.scores_to_color(np.array(flat_fs), 'hot')
        colors_list = ut.unflatten2(flat_colors, cumlen_list)
        for _tup in zip(offset_list[1:], wh_list[1:], sf_list[1:], kpts2_list,
                        fm_list, fs_list, featflag_list, colors_list):
            offset2, wh2, sf2, kpts2, fm2_, fs2_, featflags, colors = _tup
            xywh1 = (offset1[0], offset1[1], wh1[0], wh1[1])
            xywh2 = (offset2[0], offset2[1], wh2[0], wh2[1])
            #colors = pt.scores_to_color(fs2)
            if kpts1 is not None and kpts2 is not None:
                if NONVOTE_MODE == 'filter':
                    fm2 = fm2_.compress(featflags, axis=0)
                    fs2 = fs2_.compress(featflags, axis=0)
                elif NONVOTE_MODE == 'only':
                    fm2 = fm2_.compress(np.logical_not(featflags), axis=0)
                    fs2 = fs2_.compress(np.logical_not(featflags), axis=0)
                else:
                    # TODO: optional coloring of nonvotes instead
                    fm2 = fm2_
                    fs2 = fs2_
                pt.plot_fmatch(xywh1, xywh2, kpts1, kpts2, fm2, fs2,
                               fm_norm=None, H1=None, H2=None,
                               scale_factor1=sf1, scale_factor2=sf2,
                               colorbar_=False, colors=colors, **kwargs)
        if colorbar_:
            pt.colorbar(flat_fs, flat_colors)
    bbox_list = [(x, y, w, h) for (x, y), (w, h) in zip(offset_list, wh_list)]
    return offset_list, sf_list, bbox_list
Exemple #6
0
def analyze(ibsmap, qreq_dict, species_dict, path_to_file_list, params):
    print('[analyze] Beginning Analyze')
    print('[analyze] Received %d file paths' % (len(path_to_file_list)))
    # decompose the filename to get the car/person to whom this image belongs
    info_tup_list = [preprocess_fpath(ibsmap, species_dict, path_to_file, params) for path_to_file in path_to_file_list]
    is_valid_list = [tup_ is not None for tup_ in info_tup_list]

    # get the ungrouped tuples that were not None
    valid_tup_list_ug = ut.filter_items(info_tup_list, is_valid_list)
    valid_path_list_ug = ut.filter_items(path_to_file_list, is_valid_list)

    # group by species
    valid_species_list_ug = ut.get_list_column(valid_tup_list_ug, 3)
    seen_species = {}
    def get_species_tmpid(txt):
        if txt in seen_species:
            return seen_species[txt]
        else:
            seen_species[txt] = len(seen_species)
            return get_species_tmpid(txt)
    species_tmpid_list = np.array([get_species_tmpid(txt) for txt in valid_species_list_ug])
    #ibs.get_species_rowids_from_text(valid_species_list_ug)
    unique_species_rowids, groupxs = vt.group_indices(np.array(species_tmpid_list))

    grouped_valid_tup_list = vt.apply_grouping(np.array(valid_tup_list_ug, dtype=object), groupxs)
    grouped_path_list = vt.apply_grouping(np.array(valid_path_list_ug, dtype=object), groupxs)

    print('[analyze] Created  %d species groups' % (len(grouped_valid_tup_list)))
    print('[analyze] grouped_valid_tup_list = ' + ut.list_str(grouped_valid_tup_list))
    print('[analyze] grouped_path_list      = ' + ut.list_str(grouped_path_list))

    assert len(grouped_valid_tup_list) == len(grouped_path_list), 'lengths must match for zip'
    for groupx, (tup, valid_path_list) in enumerate(zip(grouped_valid_tup_list, grouped_path_list)):
        car_list, person_list, animal_list, species_list, offset_list, contributor_row_id_list = zip(*tup)

        assert ut.list_allsame(species_list)

        animal = animal_list[0]
        species = species_list[0]
        ibs = ibsmap[animal]
        with ut.Indenter('[GROUP-%d-%s]' % (groupx, species)):
            assert ((animal == 'zebra' and species == species_dict['zebra']) or
                    (animal == 'giraffe' and species == species_dict['giraffe'])), 'animal/species mismatch!'
            # Add image to database
            gid_list = ibs.add_images(valid_path_list, auto_localize=False)

            reported_time_list = list(map(vt.parse_exif_unixtime, valid_path_list))
            actual_unixtime_list = [
                reported_unixtime + offset
                for reported_unixtime, offset in
                zip(reported_time_list, offset_list)
            ]
            ibs.set_image_unixtime(gid_list, actual_unixtime_list, duplicate_behavior='filter')
            ibs.set_image_contributor_rowid(gid_list, contributor_row_id_list, duplicate_behavior='filter')

            print('[analyze] starting detection for %d images and species %s...' % (len(valid_path_list), species))
            qaids_list = ibs.detect_random_forest(gid_list, species=species)
            qaid_list, reverse_list = ut.invertible_flatten2(qaids_list)
            print('\n[analyze] detected %d animals of species %s' % (len(qaid_list), species))

            # if there were no detections, don't bother
            if not qaid_list:
                continue

            # because qreq_ is persistent we need only to update the qaid_list
            qreq_ = qreq_dict[animal]  # there is a qreq_ for each species
            qaid_list_unique, unique_inverse = np.unique(qaid_list, return_inverse=True)
            qreq_.set_external_qaids(qaid_list_unique)
            qres_list_unique = ibs.query_chips(qreq_=qreq_, verbose=False)
            qres_list = ut.list_take(qres_list_unique, unique_inverse)

            # so that we can draw a new bounding box for each detection
            detection_bbox_list = ibs.get_annot_verts(qaid_list)
            detection_bboxes_list = ut.unflatten2(detection_bbox_list, reverse_list)
            qreses_list = ut.unflatten2(qres_list, reverse_list)

            with ut.Indenter('[POSTPROCESS]'):
                for _tup in zip(valid_path_list, detection_bboxes_list, qreses_list,
                                car_list, person_list, animal_list, gid_list, qaids_list):
                    postprocess_result(ibs, _tup, params)

            with ut.Indenter('[REVIEW_CHECK]'):
                for car, person in zip(car_list, person_list):
                    check_if_need_review(person, car, params)