Source code for wbia.control.manual_part_funcs

# -*- coding: utf-8 -*-
"""
Autogen:
    python -c "import utool as ut; ut.write_modscript_alias('Tgen.sh', 'wbia.templates.template_generator')"  # NOQA
    sh Tgen.sh --key part --invert --Tcfg with_getters=True with_setters=True --modfname manual_part_funcs --funcname-filter=age_m  # NOQA
    sh Tgen.sh --key part --invert --Tcfg with_getters=True with_setters=True --modfname manual_part_funcs --funcname-filter=is_  # NOQA
    sh Tgen.sh --key part --invert --Tcfg with_getters=True with_setters=True --modfname manual_part_funcs --funcname-filter=is_ --diff  # NOQA
"""
import logging
import uuid
import numpy as np
from wbia import constants as const
from wbia.control import accessor_decors, controller_inject
import utool as ut
from wbia.control.controller_inject import make_ibs_register_decorator
from wbia.web import routes_ajax

print, rrr, profile = ut.inject2(__name__)
logger = logging.getLogger('wbia')


CLASS_INJECT_KEY, register_ibs_method = make_ibs_register_decorator(__name__)


register_api = controller_inject.get_wbia_flask_api(__name__)


PART_NOTE = 'part_note'
PART_NUM_VERTS = 'part_num_verts'
PART_ROWID = 'part_rowid'
PART_TAG_TEXT = 'part_tag_text'
PART_THETA = 'part_theta'
PART_VERTS = 'part_verts'
PART_UUID = 'part_uuid'
PART_QUALITY = 'part_quality'
PART_STAGED_FLAG = 'part_staged_flag'
PART_STAGED_USER_ID = 'part_staged_user_identity'


# ==========
# IDERS
# ==========


# TODO CACHE THIS AND FIND WHAT IT SHOULD INVALIDATE IT
# ADD PARTS, DELETE PARTS ANYTHING ELSE?
@register_ibs_method
@accessor_decors.ider
def _get_all_part_rowids(ibs):
    r"""
    Returns:
        list_ (list):  all unfiltered part_rowids (part rowids)
    """
    all_part_rowids = ibs.db.get_all_rowids(const.PART_TABLE)
    if all_part_rowids is None:
        all_part_rowids = []
    return all_part_rowids


[docs]@register_ibs_method @accessor_decors.ider @register_api('/api/part/', methods=['GET']) def get_valid_part_rowids( ibs, include_only_aid_list=None, is_staged=False, viewpoint='no-filter', minqual=None ): part_rowid_list = ibs._get_all_part_rowids() part_rowid_list = ibs.filter_part_set( part_rowid_list, include_only_aid_list=include_only_aid_list, is_staged=is_staged, viewpoint=viewpoint, minqual=minqual, ) return part_rowid_list
[docs]@register_ibs_method def get_num_parts(ibs, **kwargs): r""" Number of valid parts """ part_rowid_list = ibs.get_valid_part_rowids(**kwargs) return len(part_rowid_list)
[docs]@register_ibs_method @register_api('/api/part/<rowid>/', methods=['GET']) def part_src_api(rowid=None): r""" Returns the base64 encoded image of part <rowid> RESTful: Method: GET URL: /api/part/<rowid>/ """ return routes_ajax.part_src(rowid)
[docs]@register_ibs_method def filter_part_set( ibs, part_rowid_list, include_only_aid_list=None, is_staged=False, viewpoint='no-filter', minqual=None, ): if not part_rowid_list: # no need to filter if empty return part_rowid_list # -- valid part_rowid filtering -- # filter by is_staged if is_staged is True: # corresponding unoptimized hack for is_staged flag_list = ibs.get_part_staged_flags(part_rowid_list) part_rowid_list = ut.compress(part_rowid_list, flag_list) elif is_staged is False: flag_list = ibs.get_part_staged_flags(part_rowid_list) part_rowid_list = ut.filterfalse_items(part_rowid_list, flag_list) if include_only_aid_list is not None: gid_list = ibs.get_part_gids(part_rowid_list) is_valid_gid = [gid in include_only_aid_list for gid in gid_list] part_rowid_list = ut.compress(part_rowid_list, is_valid_gid) if viewpoint != 'no-filter': viewpoint_list = ibs.get_part_viewpoints(part_rowid_list) is_valid_viewpoint = [viewpoint == flag for flag in viewpoint_list] part_rowid_list = ut.compress(part_rowid_list, is_valid_viewpoint) if minqual is not None: part_rowid_list = ibs.filter_part_rowids_to_quality( part_rowid_list, minqual, unknown_ok=True ) part_rowid_list = sorted(part_rowid_list) return part_rowid_list
# ========== # ADDERS # ==========
[docs]@register_ibs_method @accessor_decors.adder @register_api('/api/part/', methods=['POST']) def add_parts( ibs, aid_list, bbox_list=None, theta_list=None, detect_confidence_list=None, notes_list=None, vert_list=None, part_uuid_list=None, viewpoint_list=None, quality_list=None, type_list=None, staged_uuid_list=None, staged_user_id_list=None, **kwargs ): r""" Adds an part to annotations Args: aid_list (list): annotation rowids to add part to bbox_list (list): of [x, y, w, h] bounding boxes for each annotation (supply verts instead) theta_list (list): orientations of parts vert_list (list): alternative to bounding box Returns: list: part_rowid_list Ignore: detect_confidence_list = None notes_list = None part_uuid_list = None viewpoint_list = None quality_list = None type_list = None RESTful: Method: POST URL: /api/part/ """ # ut.embed() from vtool import geometry if ut.VERBOSE: logger.info('[ibs] adding parts') # Prepare the SQL input # For import only, we can specify both by setting import_override to True assert bool(bbox_list is None) != bool( vert_list is None ), 'must specify exactly one of bbox_list or vert_list' ut.assert_all_not_None(aid_list, 'aid_list') if vert_list is None: vert_list = geometry.verts_list_from_bboxes_list(bbox_list) elif bbox_list is None: bbox_list = geometry.bboxes_from_vert_list(vert_list) if theta_list is None: theta_list = [0.0 for _ in range(len(aid_list))] len_bbox = len(bbox_list) len_vert = len(vert_list) len_aid = len(aid_list) len_theta = len(theta_list) try: assert len_vert == len_bbox, 'bbox and verts are not of same size' assert len_aid == len_bbox, 'bbox and aid are not of same size' assert len_aid == len_theta, 'bbox and aid are not of same size' except AssertionError as ex: ut.printex(ex, key_list=['len_vert', 'len_aid', 'len_bbox' 'len_theta']) raise if len(aid_list) == 0: # nothing is being added logger.info('[ibs] WARNING: 0 parts are being added!') logger.info(ut.repr2(locals())) return [] if detect_confidence_list is None: detect_confidence_list = [0.0 for _ in range(len(aid_list))] if notes_list is None: notes_list = ['' for _ in range(len(aid_list))] if viewpoint_list is None: viewpoint_list = [-1.0] * len(aid_list) if type_list is None: type_list = [const.UNKNOWN] * len(aid_list) nVert_list = [len(verts) for verts in vert_list] vertstr_list = [str(verts) for verts in vert_list] xtl_list, ytl_list, width_list, height_list = list(zip(*bbox_list)) assert len(nVert_list) == len(vertstr_list) # Build ~~deterministic?~~ random and unique PART ids if part_uuid_list is None: part_uuid_list = [uuid.uuid4() for _ in range(len(aid_list))] if staged_uuid_list is None: staged_uuid_list = [None] * len(aid_list) is_staged_list = [staged_uuid is not None for staged_uuid in staged_uuid_list] if staged_user_id_list is None: staged_user_id_list = [None] * len(aid_list) # Define arguments to insert colnames = ( 'part_uuid', 'annot_rowid', 'part_xtl', 'part_ytl', 'part_width', 'part_height', 'part_theta', 'part_num_verts', 'part_verts', 'part_viewpoint', 'part_detect_confidence', 'part_note', 'part_type', 'part_staged_flag', 'part_staged_uuid', 'part_staged_user_identity', ) check_uuid_flags = [not isinstance(auuid, uuid.UUID) for auuid in part_uuid_list] if any(check_uuid_flags): pos = ut.list_where(check_uuid_flags) raise ValueError('positions %r have malformated UUIDS' % (pos,)) params_iter = list( zip( part_uuid_list, aid_list, xtl_list, ytl_list, width_list, height_list, theta_list, nVert_list, vertstr_list, viewpoint_list, detect_confidence_list, notes_list, type_list, is_staged_list, staged_uuid_list, staged_user_id_list, ) ) # Execute add PARTs SQL superkey_paramx = (0,) get_rowid_from_superkey = ibs.get_part_rowids_from_uuid part_rowid_list = ibs.db.add_cleanly( const.PART_TABLE, colnames, params_iter, get_rowid_from_superkey, superkey_paramx ) return part_rowid_list
[docs]@register_ibs_method # @register_api('/api/part/rows/', methods=['GET']) def get_part_rows(ibs, part_rowid_list): r""" Auto-docstr for 'get_part_rows' """ colnames = ( 'part_uuid', 'annot_rowid', 'part_xtl', 'part_ytl', 'part_width', 'part_height', 'part_theta', 'part_num_verts', 'part_verts', 'part_viewpoint', 'part_detect_confidence', 'part_note', 'part_quality', 'part_type', ) rows_list = ibs.db.get( const.PART_TABLE, colnames, part_rowid_list, unpack_scalars=False ) return rows_list
# ========== # DELETERS # ==========
[docs]@register_ibs_method @accessor_decors.deleter @accessor_decors.cache_invalidator(const.PART_TABLE, rowidx=0) @register_api('/api/part/', methods=['DELETE']) def delete_parts(ibs, part_rowid_list): r""" deletes parts from the database RESTful: Method: DELETE URL: /api/part/ Args: ibs (IBEISController): wbia controller object part_rowid_list (int): list of part ids """ if ut.VERBOSE: logger.info('[ibs] deleting %d parts' % len(part_rowid_list)) # delete parent rowid column if exists in part table return ibs.db.delete_rowids(const.PART_TABLE, part_rowid_list)
# ========== # GETTERS # ==========
[docs]@register_ibs_method @accessor_decors.getter_1to1 @register_api('/api/part/rowid/uuid/', methods=['GET']) def get_part_rowids_from_uuid(ibs, uuid_list): r""" Returns: list_ (list): part rowids RESTful: Method: GET URL: /api/part/rowid/uuid/ """ # FIXME: MAKE SQL-METHOD FOR NON-ROWID GETTERS part_rowids_list = ibs.db.get( const.PART_TABLE, (PART_ROWID,), uuid_list, id_colname=PART_UUID ) return part_rowids_list
[docs]@register_ibs_method @accessor_decors.getter_1to1 # @register_api('/api/part/uuid/missing/', methods=['GET']) def get_part_missing_uuid(ibs, uuid_list): r""" Returns: list_ (list): a list of missing part uuids """ part_rowid_list = ibs.get_part_rowids_from_uuid(uuid_list) zipped = zip(part_rowid_list, uuid_list) missing_uuid_list = [uuid for part_rowid, uuid in zipped if part_rowid is None] return missing_uuid_list
[docs]@register_ibs_method @ut.accepts_numpy @accessor_decors.getter_1toM @register_api('/api/part/bbox/', methods=['GET']) def get_part_bboxes(ibs, part_rowid_list): r""" Returns: bbox_list (list): part bounding boxes in image space RESTful: Method: GET URL: /api/part/bbox/ """ colnames = ( 'part_xtl', 'part_ytl', 'part_width', 'part_height', ) bbox_list = ibs.db.get(const.PART_TABLE, colnames, part_rowid_list) return bbox_list
[docs]@register_ibs_method @accessor_decors.getter_1to1 @register_api('/api/part/detect/confidence/', methods=['GET']) def get_part_detect_confidence(ibs, part_rowid_list): r""" Returns: list_ (list): a list confidences that the parts is a valid detection RESTful: Method: GET URL: /api/part/detect/confidence/ """ part_detect_confidence_list = ibs.db.get( const.PART_TABLE, ('part_detect_confidence',), part_rowid_list ) return part_detect_confidence_list
[docs]@register_ibs_method @ut.accepts_numpy @accessor_decors.getter_1to1 @register_api('/api/part/image/rowid/', methods=['GET']) def get_part_gids(ibs, part_rowid_list, assume_unique=False): r""" Get parent imageation rowids of parts Args: part_rowid_list (list): Returns: gid_list (list): image rowids RESTful: Method: GET URL: /api/part/image/rowid/ Example: >>> # ENABLE_DOCTEST >>> from wbia.control.manual_part_funcs import * # NOQA >>> import wbia >>> ibs = wbia.opendb('testdb1') >>> part_rowid_list = ibs.get_valid_part_rowids() >>> result = get_part_gids(ibs, part_rowid_list) >>> print(result) """ aid_list = ibs.get_part_aids(part_rowid_list) gid_list = ibs.get_annot_gids(aid_list) return gid_list
[docs]@register_ibs_method def get_part_image_rowids(ibs, part_rowid_list): return ibs.get_part_gids(part_rowid_list)
[docs]@register_ibs_method def get_part_image_uuids(ibs, part_rowid_list): gid_list = ibs.get_part_gids(part_rowid_list) image_uuid_list = ibs.get_image_uuids(gid_list) return image_uuid_list
[docs]@register_ibs_method @ut.accepts_numpy @accessor_decors.getter_1to1 @register_api('/api/part/annot/rowid/', methods=['GET']) def get_part_aids(ibs, part_rowid_list, assume_unique=False): r""" Get parent annotation rowids of parts Args: part_rowid_list (list): Returns: aid_list (list): annot rowids RESTful: Method: GET URL: /api/part/annot/rowid/ Example: >>> # ENABLE_DOCTEST >>> from wbia.control.manual_part_funcs import * # NOQA >>> import wbia >>> ibs = wbia.opendb('testdb1') >>> part_rowid_list = ibs.get_valid_part_rowids() >>> result = get_part_aids(ibs, part_rowid_list) >>> print(result) """ aid_list = ibs.db.get( const.PART_TABLE, ('annot_rowid',), part_rowid_list, assume_unique=assume_unique ) return aid_list
[docs]@register_ibs_method def get_part_annot_rowids(ibs, part_rowid_list): return ibs.get_part_aids(part_rowid_list)
[docs]@register_ibs_method def get_part_annot_uuids(ibs, part_rowid_list): aid_list = ibs.get_part_aids(part_rowid_list) annot_uuid_list = ibs.get_annot_uuids(aid_list) return annot_uuid_list
[docs]@register_ibs_method @accessor_decors.getter_1to1 @register_api('/api/part/theta/', methods=['GET']) def get_part_thetas(ibs, part_rowid_list): r""" Returns: theta_list (list): a list of floats describing the angles of each part CommandLine: python -m wbia.control.manual_part_funcs --test-get_part_thetas RESTful: Method: GET URL: /api/part/theta/ Example: >>> # ENABLE_DOCTEST >>> from wbia.control.manual_part_funcs import * # NOQA >>> import wbia >>> ibs = wbia.opendb('NAUT_test') >>> part_rowid_list = ibs.get_valid_part_rowids() >>> result = get_part_thetas(ibs, part_rowid_list) >>> print(result) [] """ theta_list = ibs.db.get(const.PART_TABLE, ('part_theta',), part_rowid_list) return theta_list
[docs]@register_ibs_method @accessor_decors.getter_1to1 @register_api('/api/part/uuid/', methods=['GET']) def get_part_uuids(ibs, part_rowid_list): r""" Returns: list: part_uuid_list a list of part uuids by part_rowid RESTful: Method: GET URL: /api/part/uuid/ """ part_uuid_list = ibs.db.get(const.PART_TABLE, ('part_uuid',), part_rowid_list) return part_uuid_list
[docs]@register_ibs_method @accessor_decors.getter_1to1 # @register_api('/api/part/uuid/valid/', methods=['GET']) def get_valid_part_uuids(ibs): r""" Returns: list: part_uuid_list a list of part uuids for all valid part_rowids """ part_rowid_list = ibs.get_valid_part_rowids() part_uuid_list = ibs.get_part_uuids(part_rowid_list) return part_uuid_list
[docs]@register_ibs_method @accessor_decors.getter_1to1 @register_api('/api/part/vert/', methods=['GET']) def get_part_verts(ibs, part_rowid_list): r""" Returns: vert_list (list): the vertices that form the polygon of each part RESTful: Method: GET URL: /api/part/vert/ """ from wbia.algo.preproc import preproc_part vertstr_list = ibs.db.get(const.PART_TABLE, ('part_verts',), part_rowid_list) vert_list = preproc_part.postget_part_verts(vertstr_list) # vert_list = [eval(vertstr, {}, {}) for vertstr in vertstr_list] return vert_list
[docs]@register_ibs_method @accessor_decors.getter_1to1 @register_api('/api/part/vert/rotated/', methods=['GET']) def get_part_rotated_verts(ibs, part_rowid_list): r""" Returns: rotated_vert_list (list): verticies after rotation by theta. RESTful: Method: GET URL: /api/part/vert/rotated/ """ import vtool as vt vert_list = ibs.get_part_verts(part_rowid_list) theta_list = ibs.get_part_thetas(part_rowid_list) # Convex bounding boxes for verticies bbox_list = vt.geometry.bboxes_from_vert_list(vert_list) rot_list = [ vt.rotation_around_bbox_mat3x3(theta, bbox) for theta, bbox in zip(theta_list, bbox_list) ] rotated_vert_list = [ vt.transform_points_with_homography(rot, np.array(verts).T).T.tolist() for rot, verts in zip(rot_list, vert_list) ] # vert_list = [eval(vertstr, {}, {}) for vertstr in vertstr_list] return rotated_vert_list
[docs]@register_ibs_method @accessor_decors.getter_1to1 @register_api('/api/part/note/', methods=['GET']) def get_part_notes(ibs, part_rowid_list): r""" Returns: part_notes_list (list): a list of part notes RESTful: Method: GET URL: /api/part/note/ """ part_notes_list = ibs.db.get(const.PART_TABLE, (PART_NOTE,), part_rowid_list) return part_notes_list
[docs]@register_ibs_method @accessor_decors.getter_1to1 @register_api('/api/part/type/', methods=['GET']) def get_part_types(ibs, part_rowid_list): r""" Returns: part_notes_list (list): a list of part notes RESTful: Method: GET URL: /api/part/note/ """ part_type_list = ibs.db.get(const.PART_TABLE, ('part_type',), part_rowid_list) return part_type_list
[docs]@register_ibs_method @accessor_decors.getter_1to1 @register_api('/api/part/viewpoint/', methods=['GET']) def get_part_viewpoints(ibs, part_rowid_list): r""" Returns: part_notes_list (list): a list of part notes RESTful: Method: GET URL: /api/part/note/ """ part_viewpoint_list = ibs.db.get( const.PART_TABLE, ('part_viewpoint',), part_rowid_list ) return part_viewpoint_list
[docs]@register_ibs_method @accessor_decors.getter_1to1 @register_api('/api/part/num/vert/', methods=['GET']) def get_part_num_verts(ibs, part_rowid_list): r""" Returns: nVerts_list (list): the number of vertices that form the polygon of each part RESTful: Method: GET URL: /api/part/num/vert/ """ nVerts_list = ibs.db.get(const.PART_TABLE, (PART_NUM_VERTS,), part_rowid_list) return nVerts_list
[docs]@register_ibs_method @accessor_decors.getter_1to1 @accessor_decors.cache_getter(const.PART_TABLE, PART_QUALITY) @register_api('/api/part/quality/', methods=['GET']) def get_part_qualities(ibs, part_rowid_list, eager=True): r""" part_quality_list <- part.part_quality[part_rowid_list] gets data from the "native" column "part_quality" in the "part" table Args: part_rowid_list (list): Returns: list: part_quality_list TemplateInfo: Tgetter_table_column col = part_quality tbl = part SeeAlso: wbia.const.QUALITY_INT_TO_TEXT RESTful: Method: GET URL: /api/part/quality/ Example: >>> # ENABLE_DOCTEST >>> from wbia.control.manual_part_funcs import * # NOQA >>> ibs, qreq_ = testdata_ibs() >>> part_rowid_list = ibs._get_all_part_rowids() >>> eager = True >>> part_quality_list = ibs.get_part_qualities(part_rowid_list, eager=eager) >>> print('part_quality_list = %r' % (part_quality_list,)) >>> assert len(part_rowid_list) == len(part_quality_list) """ id_iter = part_rowid_list colnames = (PART_QUALITY,) part_quality_list = ibs.db.get( const.PART_TABLE, colnames, id_iter, id_colname='rowid', eager=eager ) return part_quality_list
[docs]@register_ibs_method @accessor_decors.getter_1to1 @register_api('/api/part/quality/text/', methods=['GET']) def get_part_quality_texts(ibs, part_rowid_list): r""" Auto-docstr for 'get_part_quality_texts' RESTful: Method: GET URL: /api/part/quality/text/ """ quality_list = ibs.get_part_qualities(part_rowid_list) quality_text_list = ut.dict_take(const.QUALITY_INT_TO_TEXT, quality_list) return quality_text_list
[docs]@register_ibs_method @accessor_decors.getter_1to1 # @register_api('/api/part/isjunk/', methods=['GET']) def get_part_isjunk(ibs, part_rowid_list): r""" Auto-docstr for 'get_part_isjunk' """ qual_list = ibs.get_part_qualities(part_rowid_list) # isjunk_list = [qual == const.QUALITY_TEXT_TO_INT['junk'] for qual in qual_list] isjunk_list = [qual in const.QUALITY_TEXT_TO_INTS['junk'] for qual in qual_list] return isjunk_list
[docs]@register_ibs_method @accessor_decors.getter_1to1 @register_api('/api/part/reviewed/', methods=['GET']) def get_part_reviewed(ibs, part_rowid_list): r""" Returns: list_ (list): "All Instances Found" flag, true if all objects of interest (animals) have an PART in the part RESTful: Method: GET URL: /api/part/reviewed/ """ reviewed_list = ibs.db.get( const.PART_TABLE, ('part_toggle_reviewed',), part_rowid_list ) return reviewed_list
[docs]@register_ibs_method @accessor_decors.getter_1to1 def get_part_tag_text(ibs, part_rowid_list, **kwargs): r"""part_tags_list <- part.part_tags[part_rowid_list] gets data from the "native" column "part_tags" in the "part" table Args: part_rowid_list (list): Returns: list: part_tags_list Example: >>> # DISABLE_DOCTEST >>> from wbia.control.manual_part_funcs import * # NOQA >>> ibs, config2_ = testdata_ibs() >>> part_rowid_list = ibs._get_all_part_rowids() >>> eager = True >>> part_tags_list = ibs.get_part_tag_text(part_rowid_list, eager=eager) >>> assert len(part_rowid_list) == len(part_tags_list) """ part_type_list = ibs.get_part_types(part_rowid_list, **kwargs) part_type_list = [ part_type.lower().strip().replace(' ', '_') for part_type in part_type_list ] return part_type_list
[docs]@register_ibs_method @accessor_decors.getter_1to1 @register_api('/api/part/staged/', methods=['GET']) def get_part_staged_flags(ibs, part_rowid_list): r""" returns if an part is staged Args: ibs (IBEISController): wbia controller object part_rowid_list (int): list of part ids Returns: list: part_staged_flag_list - True if part is staged CommandLine: python -m wbia.control.manual_part_funcs --test-get_part_staged_flags RESTful: Method: GET URL: /api/part/staged/ Example: >>> # ENABLE_DOCTEST >>> from wbia.control.manual_part_funcs import * # NOQA >>> import wbia >>> ibs = wbia.opendb('testdb1') >>> part_rowid_list = ibs.get_valid_part_rowids() >>> gid_list = get_part_staged_flags(ibs, part_rowid_list) >>> result = str(gid_list) >>> print(result) """ part_staged_flag_list = ibs.db.get( const.PART_TABLE, (PART_STAGED_FLAG,), part_rowid_list ) return part_staged_flag_list
[docs]@register_ibs_method @accessor_decors.getter_1to1 @register_api('/api/part/staged/uuid/', methods=['GET']) def get_part_staged_uuids(ibs, aid_list): r""" Returns: list: part_uuid_list a list of image uuids by aid RESTful: Method: GET URL: /api/part/staged/uuid/ """ part_uuid_list = ibs.db.get(const.PART_TABLE, ('part_staged_uuid',), aid_list) return part_uuid_list
[docs]@register_ibs_method @accessor_decors.getter_1to1 @register_api('/api/part/staged/user/', methods=['GET']) def get_part_staged_user_ids(ibs, part_rowid_list): r""" returns if an part is staged Args: ibs (IBEISController): wbia controller object part_rowid_list (int): list of part ids Returns: list: part_staged_user_id_list - True if part is staged CommandLine: python -m wbia.control.manual_part_funcs --test-get_part_staged_user_ids RESTful: Method: GET URL: /api/part/staged/user/ Example: >>> # ENABLE_DOCTEST >>> from wbia.control.manual_part_funcs import * # NOQA >>> import wbia >>> ibs = wbia.opendb('testdb1') >>> part_rowid_list = ibs.get_valid_part_rowids() >>> gid_list = get_part_staged_user_ids(ibs, part_rowid_list) >>> result = str(gid_list) >>> print(result) """ part_staged_user_id_list = ibs.db.get( const.PART_TABLE, (PART_STAGED_USER_ID,), part_rowid_list ) return part_staged_user_id_list
[docs]@register_ibs_method @accessor_decors.getter_1to1 @register_api('/api/part/staged/metadata/', methods=['GET']) def get_part_staged_metadata(ibs, part_rowid_list, return_raw=False): r""" Returns: list_ (list): part metadata dictionary RESTful: Method: GET URL: /api/part/staged/metadata/ """ metadata_str_list = ibs.db.get( const.PART_TABLE, ('part_staged_metadata_json',), part_rowid_list ) metadata_list = [] for metadata_str in metadata_str_list: if metadata_str in [None, '']: metadata_dict = {} else: metadata_dict = metadata_str if return_raw else ut.from_json(metadata_str) metadata_list.append(metadata_dict) return metadata_list
#### SETTERS #### # NOQA def _update_part_rotate_fix_bbox(bbox): (xtl, ytl, w, h) = bbox diffx = int(round((w / 2.0) - (h / 2.0))) diffy = int(round((h / 2.0) - (w / 2.0))) xtl, ytl, w, h = xtl + diffx, ytl + diffy, h, w bbox = (xtl, ytl, w, h) return bbox
[docs]def update_part_rotate_90(ibs, part_rowid_list, direction): from wbia.constants import PI, TAU import vtool as vt if isinstance(direction, str): direction = direction.lower() if direction in ['left', 'l', -1]: val = 1.0 elif direction in ['right', 'r', 1]: val = -1.0 else: raise ValueError('Invalid direction supplied') theta_list = ibs.get_part_thetas(part_rowid_list) theta_list = [(theta + (val * PI / 2)) % TAU for theta in theta_list] ibs.set_part_thetas(part_rowid_list, theta_list) bbox_list = ibs.get_part_bboxes(part_rowid_list) bbox_list = [_update_part_rotate_fix_bbox(bbox) for bbox in bbox_list] ibs.set_part_bboxes(part_rowid_list, bbox_list) # Update part contours part_contours = ibs.get_part_contour(part_rowid_list) part_bboxes = ibs.get_part_bboxes(part_rowid_list) part_rowid_list_ = [] part_contours_ = [] zipped = zip(part_rowid_list, part_contours, part_bboxes) for part_rowid, part_contour, part_bbox in zipped: contour_data = part_contour.get('contour', {}) segment = contour_data.get('segment', []) if len(segment) > 0: xtl, ytl, w, h = part_bbox theta = -1.0 * val * PI / 2 bbox = (0.0, 0.0, 1.0, 1.0) R = vt.rotation_around_bbox_mat3x3(theta, bbox) for index, point in enumerate(segment): x = point.get('x', None) y = point.get('y', None) r = point.get('r', None) f = point.get('flag', None) if None not in [x, y, r, f]: points = [(x, y)] xyz_points = vt.add_homogenous_coordinate(np.array(points).T) trans_points = vt.remove_homogenous_coordinate(R.dot(xyz_points)) new_points = trans_points.T.tolist() x_, y_ = new_points[0] segment[index]['x'] = x_ segment[index]['y'] = y_ segment[index]['r'] = (r * h) / w part_contour['contour']['segment'] = segment part_rowid_list_.append(part_rowid) part_contours_.append(part_contour) ibs.set_part_contour(part_rowid_list_, part_contours_)
[docs]@register_ibs_method @register_api('/api/part/rotate/left/', methods=['POST']) def update_part_rotate_left_90(ibs, part_rowid_list): return update_part_rotate_90(ibs, part_rowid_list, 'left')
[docs]@register_ibs_method @register_api('/api/part/rotate/right/', methods=['POST']) def update_part_rotate_right_90(ibs, part_rowid_list): return update_part_rotate_90(ibs, part_rowid_list, 'right')
@register_ibs_method @accessor_decors.setter @register_api('/api/part/annot/rowid/', methods=['PUT']) def _set_part_aid(ibs, part_rowid_list, aid_list): r""" Sets part notes RESTful: Method: PUT URL: /api/part/annot/rowid """ id_iter = ((part_rowid,) for part_rowid in part_rowid_list) val_iter = ((confidence,) for confidence in aid_list) ibs.db.set(const.PART_TABLE, ('annot_rowid',), val_iter, id_iter)
[docs]@register_ibs_method @accessor_decors.setter @register_api('/api/part/bbox/', methods=['PUT']) def set_part_bboxes(ibs, part_rowid_list, bbox_list): r""" Sets bboxes of a list of parts by part_rowid, Args: part_rowid_list (list of rowids): list of part rowids bbox_list (list of (x, y, w, h)): new bounding boxes for each part_rowid Note: set_part_bboxes is a proxy for set_part_verts RESTful: Method: PUT URL: /api/part/bbox/ """ from vtool import geometry # changing the bboxes also changes the bounding polygon vert_list = geometry.verts_list_from_bboxes_list(bbox_list) # naively overwrite the bounding polygon with a rectangle - for now trust the user! ibs.set_part_verts(part_rowid_list, vert_list)
[docs]@register_ibs_method @accessor_decors.setter @register_api('/api/part/detect/confidence/', methods=['PUT']) def set_part_detect_confidence(ibs, part_rowid_list, confidence_list): r""" Sets part notes RESTful: Method: PUT URL: /api/part/detect/confidence/ """ id_iter = ((part_rowid,) for part_rowid in part_rowid_list) val_iter = ((confidence,) for confidence in confidence_list) ibs.db.set(const.PART_TABLE, ('part_detect_confidence',), val_iter, id_iter)
[docs]@register_ibs_method @accessor_decors.setter @register_api('/api/part/note/', methods=['PUT']) def set_part_notes(ibs, part_rowid_list, notes_list): r""" Sets part notes RESTful: Method: PUT URL: /api/part/note/ """ id_iter = ((part_rowid,) for part_rowid in part_rowid_list) val_iter = ((notes,) for notes in notes_list) ibs.db.set(const.PART_TABLE, (PART_NOTE,), val_iter, id_iter)
[docs]@register_ibs_method @accessor_decors.setter @register_api('/api/part/type/', methods=['PUT']) def set_part_types(ibs, part_rowid_list, type_list): r""" Sets part notes RESTful: Method: PUT URL: /api/part/note/ """ id_iter = ((part_rowid,) for part_rowid in part_rowid_list) val_iter = ((type_,) for type_ in type_list) ibs.db.set(const.PART_TABLE, ('part_type',), val_iter, id_iter)
[docs]@register_ibs_method @accessor_decors.setter @register_api('/api/part/viewpoint/', methods=['PUT']) def set_part_viewpoints(ibs, part_rowid_list, viewpoint_list): r""" Sets part notes RESTful: Method: PUT URL: /api/part/note/ """ id_iter = ((part_rowid,) for part_rowid in part_rowid_list) val_iter = ((viewpoint_,) for viewpoint_ in viewpoint_list) ibs.db.set(const.PART_TABLE, ('part_viewpoint',), val_iter, id_iter)
[docs]@register_ibs_method @accessor_decors.setter def set_part_tag_text(ibs, part_rowid_list, part_tags_list, duplicate_behavior='error'): r"""part_tags_list -> part.part_tags[part_rowid_list] Args: part_rowid_list part_tags_list """ # logger.info('[ibs] set_part_tag_text of part_rowid_list=%r to tags=%r' % (part_rowid_list, part_tags_list)) id_iter = part_rowid_list colnames = (PART_TAG_TEXT,) ibs.db.set( const.PART_TABLE, colnames, part_tags_list, id_iter, duplicate_behavior=duplicate_behavior, )
[docs]@register_ibs_method @accessor_decors.setter @register_api('/api/part/theta/', methods=['PUT']) def set_part_thetas(ibs, part_rowid_list, theta_list): r""" Sets thetas of a list of part_rowid_list RESTful: Method: PUT URL: /api/part/theta/ """ id_iter = ((part_rowid,) for part_rowid in part_rowid_list) val_list = ((theta,) for theta in theta_list) ibs.db.set(const.PART_TABLE, (PART_THETA,), val_list, id_iter)
[docs]@register_ibs_method @accessor_decors.setter @register_api('/api/part/vert/', methods=['PUT']) def set_part_verts( ibs, part_rowid_list, verts_list, delete_thumbs=True, notify_root=True ): r""" Sets the vertices [(x, y), ...] of a list of part_rowid_list RESTful: Method: PUT URL: /api/part/vert/ """ from vtool import geometry nInput = len(part_rowid_list) # Compute data to set if isinstance(verts_list, np.ndarray): verts_list = verts_list.tolist() for index, vert_list in enumerate(verts_list): if isinstance(vert_list, np.ndarray): verts_list[index] = vert_list.tolist() num_verts_list = list(map(len, verts_list)) verts_as_strings = list(map(str, verts_list)) id_iter1 = ((part_rowid,) for part_rowid in part_rowid_list) # also need to set the internal number of vertices val_iter1 = ( (num_verts, verts) for (num_verts, verts) in zip(num_verts_list, verts_as_strings) ) colnames = ( PART_NUM_VERTS, PART_VERTS, ) # SET VERTS in PART_TABLE ibs.db.set(const.PART_TABLE, colnames, val_iter1, id_iter1, nInput=nInput) # changing the vertices also changes the bounding boxes bbox_list = geometry.bboxes_from_vert_list(verts_list) # new bboxes xtl_list, ytl_list, width_list, height_list = list(zip(*bbox_list)) val_iter2 = zip(xtl_list, ytl_list, width_list, height_list) id_iter2 = ((part_rowid,) for part_rowid in part_rowid_list) colnames = ( 'part_xtl', 'part_ytl', 'part_width', 'part_height', ) # SET BBOX in PART_TABLE ibs.db.set(const.PART_TABLE, colnames, val_iter2, id_iter2, nInput=nInput) with ut.Timer('set_annot_verts...thumbs'): if delete_thumbs: ibs.delete_part_chips(part_rowid_list) # INVALIDATE THUMBNAILS with ut.Timer('set_annot_verts...roots'): if notify_root: ibs.depc_part.notify_root_changed(part_rowid_list, 'verts', force_delete=True)
[docs]@register_ibs_method @accessor_decors.setter @accessor_decors.cache_invalidator(const.PART_TABLE, [PART_QUALITY], rowidx=0) @register_api('/api/part/quality/', methods=['PUT']) def set_part_qualities(ibs, part_rowid_list, part_quality_list): r""" part_quality_list -> part.part_quality[part_rowid_list] A quality is an integer representing the following types: Args: part_rowid_list part_quality_list SeeAlso: wbia.const.QUALITY_INT_TO_TEXT RESTful: Method: PUT URL: /api/part/quality/ """ id_iter = part_rowid_list colnames = (PART_QUALITY,) ibs.db.set(const.PART_TABLE, colnames, part_quality_list, id_iter)
[docs]@register_ibs_method @register_api('/api/part/quality/text/', methods=['PUT']) def set_part_quality_texts(ibs, part_rowid_list, quality_text_list): r""" Auto-docstr for 'set_part_quality_texts' RESTful: Method: PUT URL: /api/part/quality/text/ """ if not ut.isiterable(part_rowid_list): part_rowid_list = [part_rowid_list] if isinstance(quality_text_list, str): quality_text_list = [quality_text_list] quality_list = ut.dict_take(const.QUALITY_TEXT_TO_INT, quality_text_list) ibs.set_part_qualities(part_rowid_list, quality_list)
[docs]@register_ibs_method @accessor_decors.setter @register_api('/api/part/reviewed/', methods=['PUT']) def set_part_reviewed(ibs, part_rowid_list, reviewed_list): r""" Sets the part all instances found bit RESTful: Method: PUT URL: /api/part/reviewed/ """ id_iter = ((part_rowid,) for part_rowid in part_rowid_list) val_list = ((reviewed,) for reviewed in reviewed_list) ibs.db.set(const.PART_TABLE, ('part_toggle_reviewed',), val_list, id_iter)
@register_ibs_method @accessor_decors.setter @accessor_decors.cache_invalidator(const.PART_TABLE, [PART_STAGED_FLAG], rowidx=0) @register_api('/api/part/staged/', methods=['PUT']) def _set_part_staged_flags(ibs, part_rowid_list, flag_list): r""" Sets if an part is staged RESTful: Method: PUT URL: /api/part/staged/ """ id_iter = ((part_rowid,) for part_rowid in part_rowid_list) val_iter = ((flag,) for flag in flag_list) ibs.db.set(const.PART_TABLE, (PART_STAGED_FLAG,), val_iter, id_iter)
[docs]@register_ibs_method @register_api('/api/part/staged/uuid/', methods=['PUT']) def set_part_staged_uuids(ibs, aid_list, part_uuid_list): r""" Returns: list_ (list): all nids of known animals (does not include unknown names) """ id_iter = ((aid,) for aid in aid_list) val_iter = ((part_uuid,) for part_uuid in part_uuid_list) ibs.db.set(const.PART_TABLE, ('part_staged_uuid',), val_iter, id_iter) flag_list = [part_uuid is not None for part_uuid in part_uuid_list] ibs._set_part_staged_flags(aid_list, flag_list)
[docs]@register_ibs_method @accessor_decors.setter @accessor_decors.cache_invalidator(const.PART_TABLE, [PART_STAGED_USER_ID], rowidx=0) @register_api('/api/part/staged/user/', methods=['PUT']) def set_part_staged_user_ids(ibs, part_rowid_list, user_id_list): r""" Sets the staged part user id RESTful: Method: PUT URL: /api/part/staged/user/ """ id_iter = ((part_rowid,) for part_rowid in part_rowid_list) val_iter = ((user_id,) for user_id in user_id_list) ibs.db.set(const.PART_TABLE, (PART_STAGED_USER_ID,), val_iter, id_iter)
[docs]@register_ibs_method @accessor_decors.setter @register_api('/api/part/staged/metadata/', methods=['PUT']) def set_part_staged_metadata(ibs, part_rowid_list, metadata_dict_list): r""" Sets the part's staged metadata using a metadata dictionary RESTful: Method: PUT URL: /api/part/staged/metadata/ CommandLine: python -m wbia.control.manual_part_funcs --test-set_part_staged_metadata Example: >>> # ENABLE_DOCTEST >>> from wbia.control.manual_part_funcs import * # NOQA >>> import wbia >>> import random >>> # build test data >>> ibs = wbia.opendb('testdb1') >>> aid_list = ibs.get_valid_aids()[0:1] >>> bbox_list = [[0, 0, 100, 100]] * len(aid_list) >>> part_rowid_list = ibs.add_parts(aid_list, bbox_list=bbox_list) >>> metadata_dict_list = [ >>> {'test': random.uniform(0.0, 1.0)}, >>> ] * len(part_rowid_list) >>> print(ut.repr2(metadata_dict_list)) >>> ibs.set_part_staged_metadata(part_rowid_list, metadata_dict_list) >>> # verify results >>> metadata_dict_list_ = ibs.get_part_staged_metadata(part_rowid_list) >>> print(ut.repr2(metadata_dict_list_)) >>> assert metadata_dict_list == metadata_dict_list_ >>> metadata_str_list = [ut.to_json(metadata_dict) for metadata_dict in metadata_dict_list] >>> print(ut.repr2(metadata_str_list)) >>> metadata_str_list_ = ibs.get_part_staged_metadata(part_rowid_list, return_raw=True) >>> print(ut.repr2(metadata_str_list_)) >>> assert metadata_str_list == metadata_str_list_ >>> ibs.delete_parts(part_rowid_list) """ id_iter = ((part_rowid,) for part_rowid in part_rowid_list) metadata_str_list = [] for metadata_dict in metadata_dict_list: metadata_str = ut.to_json(metadata_dict) metadata_str_list.append(metadata_str) val_list = ((metadata_str,) for metadata_str in metadata_str_list) ibs.db.set(const.PART_TABLE, ('part_staged_metadata_json',), val_list, id_iter)
[docs]@register_ibs_method @accessor_decors.getter_1to1 @register_api('/api/part/metadata/', methods=['GET']) def get_part_metadata(ibs, part_rowid_list, return_raw=False): r""" Returns: list_ (list): part metadata dictionary RESTful: Method: GET URL: /api/part/metadata/ """ metadata_str_list = ibs.db.get( const.PART_TABLE, ('part_metadata_json',), part_rowid_list ) metadata_list = [] for metadata_str in metadata_str_list: if metadata_str in [None, '']: metadata_dict = {} else: metadata_dict = metadata_str if return_raw else ut.from_json(metadata_str) metadata_list.append(metadata_dict) return metadata_list
[docs]@register_ibs_method @accessor_decors.setter @register_api('/api/part/metadata/', methods=['PUT']) def set_part_metadata(ibs, part_rowid_list, metadata_dict_list): r""" Sets the part's metadata using a metadata dictionary RESTful: Method: PUT URL: /api/part/metadata/ CommandLine: python -m wbia.control.manual_part_funcs --test-set_part_metadata Example: >>> # ENABLE_DOCTEST >>> from wbia.control.manual_part_funcs import * # NOQA >>> import wbia >>> import random >>> # build test data >>> ibs = wbia.opendb('testdb1') >>> aid_list = ibs.get_valid_aids()[0:1] >>> bbox_list = [[0, 0, 100, 100]] * len(aid_list) >>> part_rowid_list = ibs.add_parts(aid_list, bbox_list=bbox_list) >>> metadata_dict_list = [ >>> {'test': random.uniform(0.0, 1.0)}, >>> ] >>> print(ut.repr2(metadata_dict_list)) >>> ibs.set_part_metadata(part_rowid_list, metadata_dict_list) >>> # verify results >>> metadata_dict_list_ = ibs.get_part_metadata(part_rowid_list) >>> print(ut.repr2(metadata_dict_list_)) >>> assert metadata_dict_list == metadata_dict_list_ >>> metadata_str_list = [ut.to_json(metadata_dict) for metadata_dict in metadata_dict_list] >>> print(ut.repr2(metadata_str_list)) >>> metadata_str_list_ = ibs.get_part_metadata(part_rowid_list, return_raw=True) >>> print(ut.repr2(metadata_str_list_)) >>> assert metadata_str_list == metadata_str_list_ >>> ibs.delete_parts(part_rowid_list) """ id_iter = ((part_rowid,) for part_rowid in part_rowid_list) metadata_str_list = [] for metadata_dict in metadata_dict_list: metadata_str = ut.to_json(metadata_dict) metadata_str_list.append(metadata_str) val_list = ((metadata_str,) for metadata_str in metadata_str_list) ibs.db.set(const.PART_TABLE, ('part_metadata_json',), val_list, id_iter)
[docs]@register_ibs_method @accessor_decors.getter_1to1 @register_api('/api/part/contour/', methods=['GET']) def get_part_contour(ibs, part_rowid_list, return_raw=False): r""" Returns: list_ (list): part contour dictionary RESTful: Method: GET URL: /api/part/contour/ """ contour_str_list = ibs.db.get( const.PART_TABLE, ('part_contour_json',), part_rowid_list ) contour_list = [] for contour_str in contour_str_list: if contour_str in [None, '']: contour_dict = {} else: contour_dict = contour_str if return_raw else ut.from_json(contour_str) contour_list.append(contour_dict) return contour_list
[docs]@register_ibs_method @accessor_decors.setter @register_api('/api/part/contour/', methods=['PUT']) def set_part_contour(ibs, part_rowid_list, contour_dict_list): r""" Sets the part's contour using a contour dictionary RESTful: Method: PUT URL: /api/part/contour/ CommandLine: python -m wbia.control.manual_part_funcs --test-set_part_contour Example: >>> # ENABLE_DOCTEST >>> from wbia.control.manual_part_funcs import * # NOQA >>> import wbia >>> import random >>> # build test data >>> ibs = wbia.opendb('testdb1') >>> aid_list = ibs.get_valid_aids()[0:1] >>> bbox_list = [[0, 0, 100, 100]] * len(aid_list) >>> part_rowid_list = ibs.add_parts(aid_list, bbox_list=bbox_list) >>> contour_dict_list = [ >>> {'test': random.uniform(0.0, 1.0)}, >>> ] >>> print(ut.repr2(contour_dict_list)) >>> ibs.set_part_contour(part_rowid_list, contour_dict_list) >>> # verify results >>> contour_dict_list_ = ibs.get_part_contour(part_rowid_list) >>> print(ut.repr2(contour_dict_list_)) >>> assert contour_dict_list == contour_dict_list_ >>> contour_str_list = [ut.to_json(contour_dict) for contour_dict in contour_dict_list] >>> print(ut.repr2(contour_str_list)) >>> contour_str_list_ = ibs.get_part_contour(part_rowid_list, return_raw=True) >>> print(ut.repr2(contour_str_list_)) >>> assert contour_str_list == contour_str_list_ >>> ibs.delete_parts(part_rowid_list) """ id_iter = ((part_rowid,) for part_rowid in part_rowid_list) contour_str_list = [] for contour_dict in contour_dict_list: contour_str = ut.to_json(contour_dict) contour_str_list.append(contour_str) val_list = ((contour_str,) for contour_str in contour_str_list) ibs.db.set(const.PART_TABLE, ('part_contour_json',), val_list, id_iter)
# setting up the Wild Dog data for assigner training # def get_corresponding_aids(ibs, part_rowid_list, from_aids=None): # if from_aids is None: # from_aids = ibs.get_valid_aids() # def get_corresponding_aids_slow(ibs, part_rowid_list, from_aids): # part_bboxes = ibs.get_part_bboxes(part_rowid_list) # annot_bboxes = ibs.get_annot_bboxes(from_aids) # annot_gids = ibs.get_annot_gids(from_aids) # from collections import defaultdict # bbox_gid_to_aids = defaultdict(int) # for aid, gid, bbox in zip(from_aids, annot_gids, annot_bboxes): # bbox_gid_to_aids[(bbox[0], bbox[1], bbox[2], bbox[3], gid)] = aid # part_gids = ibs.get_part_image_rowids(parts) # part_rowid_to_aid = { # part_id: bbox_gid_to_aids[(bbox[0], bbox[1], bbox[2], bbox[3], gid)] # for part_id, gid, bbox in zip(part_rowid_list, part_gids, part_bboxes) # } # part_aids = [part_rowid_to_aid[partid] for partid in parts] # part_parent_aids = ibs.get_part_aids(part_rowid_list) # # parents might be non-unique so we gotta make a unique name for each parent # parent_aid_to_part_rowids = defaultdict(list) # for part_rowid, parent_aid in zip(part_rowid_list, part_parent_aids): # parent_aid_to_part_rowids[parent_aid] += [part_rowid] # part_annot_names = [ # ','.join(str(p) for p in parent_aid_to_part_rowids[parent_aid]) # for parent_aid in part_parent_aids # ] # # now assign names so we can associate the part annots with the non-part annots # new_part_names = ['part-%s' % part_rowid for part_rowid in part_rowid_list] # def sort_parts_by_tags(ibs, part_rowid_list): # tags = ibs.get_part_tag_text(part_rowid_list) # from collections import defaultdict # tag_to_rowids = defaultdict(list) # for tag, part_rowid in zip(tags, part_rowid_list): # tag_to_rowids[tag] += [part_rowid] # parts_by_tags = [tag_to_rowdids[tag] for tag in tag_to_rowdids.keys()] # return parts_by_tags # ========== # Testdata # ==========
[docs]def testdata_ibs(): r""" Auto-docstr for 'testdata_ibs' """ import wbia ibs = wbia.opendb('testdb1') qreq_ = None return ibs, qreq_