# -*- 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
#### 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.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_