Source code for wbia.scripts.fix_annotation_orientation_issue

# -*- coding: utf-8 -*-
import logging
import utool as ut
import vtool as vt
import numpy as np

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


[docs]def fix_annotation_orientation(ibs, min_percentage=0.95): """ Fixes the annotations that are outside the bounds of the image due to a changed image orientation flag in the database CommandLine: python -m wbia.scripts.fix_annotation_orientation_issue fix_annotation_orientation Example: >>> # ENABLE_DOCTEST >>> import wbia >>> from wbia.scripts.fix_annotation_orientation_issue import * # NOQA >>> ibs = wbia.opendb() >>> unfixable_gid_list = fix_annotation_orientation(ibs) >>> assert len(unfixable_gid_list) == 0 """ from vtool import exif def bbox_overlap(bbox1, bbox2): ax1 = bbox1[0] ay1 = bbox1[1] ax2 = bbox1[0] + bbox1[2] ay2 = bbox1[1] + bbox1[3] bx1 = bbox2[0] by1 = bbox2[1] bx2 = bbox2[0] + bbox2[2] by2 = bbox2[1] + bbox2[3] overlap_x = max(0, min(ax2, bx2) - max(ax1, bx1)) overlap_y = max(0, min(ay2, by2) - max(ay1, by1)) return overlap_x * overlap_y orient_dict = exif.ORIENTATION_DICT_INVERSE good_orient_list = [ exif.ORIENTATION_UNDEFINED, exif.ORIENTATION_000, ] good_orient_key_list = [ orient_dict.get(good_orient) for good_orient in good_orient_list ] assert None not in good_orient_key_list gid_list = ibs.get_valid_gids() orient_list = ibs.get_image_orientation(gid_list) flag_list = [orient not in good_orient_key_list for orient in orient_list] # Filter based on based gids unfixable_gid_list = [] gid_list = ut.filter_items(gid_list, flag_list) if len(gid_list) > 0: args = (len(gid_list),) logger.info('Found %d images with non-standard orientations' % args) aids_list = ibs.get_image_aids(gid_list, is_staged=None) size_list = ibs.get_image_sizes(gid_list) invalid_gid_list = [] zipped = zip(gid_list, orient_list, aids_list, size_list) for gid, orient, aid_list, (w, h) in zipped: image = ibs.get_images(gid) h_, w_ = image.shape[:2] if h != h_ or w != w_: ibs._set_image_sizes([gid], [w_], [h_]) orient_str = exif.ORIENTATION_DICT[orient] image_bbox = (0, 0, w, h) verts_list = ibs.get_annot_rotated_verts(aid_list) invalid = False for aid, vert_list in zip(aid_list, verts_list): annot_bbox = vt.bbox_from_verts(vert_list) overlap = bbox_overlap(image_bbox, annot_bbox) area = annot_bbox[2] * annot_bbox[3] percentage = overlap / area if percentage < min_percentage: args = (gid, orient_str, aid, overlap, area, percentage) logger.info( '\tInvalid GID %r, Orient %r, AID %r: Overlap %0.2f, Area %0.2f (%0.2f %%)' % args ) invalid = True # break if invalid: invalid_gid_list.append(gid) invalid_gid_list = list(set(invalid_gid_list)) if len(invalid_gid_list) > 0: args = ( len(invalid_gid_list), len(gid_list), invalid_gid_list, ) logger.info('Found %d / %d images with invalid annotations = %r' % args) orient_list = ibs.get_image_orientation(invalid_gid_list) aids_list = ibs.get_image_aids(invalid_gid_list, is_staged=None) size_list = ibs.get_image_sizes(invalid_gid_list) zipped = zip(invalid_gid_list, orient_list, aids_list, size_list) for invalid_gid, orient, aid_list, (w, h) in zipped: orient_str = exif.ORIENTATION_DICT[orient] image_bbox = (0, 0, w, h) args = ( invalid_gid, len(aid_list), ) logger.info('Fixing GID %r with %d annotations' % args) theta = np.pi / 2.0 tx = 0.0 ty = 0.0 if orient == orient_dict.get(exif.ORIENTATION_090): theta *= 1.0 tx = w elif orient == orient_dict.get(exif.ORIENTATION_180): theta *= 2.0 tx = w ty = h elif orient == orient_dict.get(exif.ORIENTATION_270): theta *= -1.0 ty = h else: raise ValueError('Unrecognized invalid orientation') H = np.array( [ [np.cos(theta), -np.sin(theta), tx], [np.sin(theta), np.cos(theta), ty], [0.0, 0.0, 1.0], ] ) # logger.info(H) verts_list = ibs.get_annot_rotated_verts(aid_list) for aid, vert_list in zip(aid_list, verts_list): vert_list = np.array(vert_list) # logger.info(vert_list) vert_list = vert_list.T transformed_vert_list = vt.transform_points_with_homography( H, vert_list ) transformed_vert_list = transformed_vert_list.T # logger.info(transformed_vert_list) ibs.set_annot_verts( [aid], [transformed_vert_list], update_visual_uuids=False ) current_theta = ibs.get_annot_thetas(aid) new_theta = current_theta + theta ibs.set_annot_thetas(aid, new_theta, update_visual_uuids=False) fixed_vert_list = ibs.get_annot_rotated_verts(aid) fixed_annot_bbox = vt.bbox_from_verts(fixed_vert_list) fixed_overlap = bbox_overlap(image_bbox, fixed_annot_bbox) fixed_area = fixed_annot_bbox[2] * fixed_annot_bbox[3] fixed_percentage = fixed_overlap / fixed_area args = ( invalid_gid, orient_str, aid, fixed_overlap, fixed_area, fixed_percentage, ) logger.info( '\tFixing GID %r, Orient %r, AID %r: Overlap %0.2f, Area %0.2f (%0.2f %%)' % args ) if fixed_percentage < min_percentage: logger.info('\tWARNING: FIXING DID NOT CORRECT AID %r' % (aid,)) unfixable_gid_list.append(gid) logger.info('Un-fixable gid_list = %r' % (unfixable_gid_list,)) return unfixable_gid_list