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
def transform_non_affine(self, input_xy): """ The input and output are Nx2 numpy arrays. """ import vtool as vt _xys = input_xy.T xy_t = vt.transform_points_with_homography(self.H, _xys) output_xy = xy_t.T return output_xy
def draw_keypoints(ax, kpts_, scale_factor=1.0, offset=(0.0, 0.0), rotation=0.0, ell=True, pts=False, rect=False, eig=False, ori=False, sifts=None, siftkw={}, H=None, **kwargs): """ draws keypoints extracted by pyhesaff onto a matplotlib axis FIXME: There is probably a matplotlib bug here. If you specify two different alphas in a collection, whatever the last alpha was gets applied to everything Args: ax (mpl.Axes): kpts (ndarray): keypoints [[x, y, a, c, d, theta], ...] scale_factor (float): offset (tuple): rotation (float): ell (bool): pts (bool): rect (bool): eig (bool): ori (bool): sifts (None): References: http://stackoverflow.com/questions/28401788/transforms-non-affine-patch CommandLine: python -m wbia.plottool.mpl_keypoint draw_keypoints --show Example: >>> # ENABLE_DOCTEST >>> from wbia.plottool.mpl_keypoint import * # NOQA >>> from wbia.plottool.mpl_keypoint import _draw_patches, _draw_pts # NOQA >>> import wbia.plottool as pt >>> import vtool as vt >>> imgBGR = vt.get_star_patch(jitter=True) >>> H = np.array([[1, 0, 0], [.5, 2, 0], [0, 0, 1]]) >>> H = np.array([[.8, 0, 0], [0, .8, 0], [0, 0, 1]]) >>> H = None >>> TAU = 2 * np.pi >>> kpts_ = vt.make_test_image_keypoints(imgBGR, scale=.5, skew=2, theta=TAU / 8.0) >>> scale_factor=1.0 >>> #offset=(0.0, -4.0) >>> offset=(0.0, 0.0) >>> rotation=0.0 >>> ell=True >>> pts=True >>> rect=True >>> eig=True >>> ori=True >>> # make random sifts >>> sifts = mpl_sift.testdata_sifts() >>> siftkw = {} >>> kwargs = dict(ori_color=[0, 1, 0], rect_color=[0, 0, 1], >>> eig_color=[1, 1, 0], pts_size=.1) >>> w, h = imgBGR.shape[0:2][::-1] >>> imgBGR_ = imgBGR if H is None else vt.warpAffine( >>> imgBGR, H, (int(w * .8), int(h * .8))) >>> fig, ax = pt.imshow(imgBGR_ * 255) >>> draw_keypoints(ax, kpts_, scale_factor, offset, rotation, ell, pts, ... rect, eig, ori, sifts, siftkw, H=H, **kwargs) >>> pt.iup() >>> pt.show_if_requested() """ import vtool.keypoint as ktool if kpts_.shape[1] == 2: # pad out structure if only xy given kpts = np.zeros((len(kpts_), 6)) kpts[:, 0:2] = kpts_ kpts[:, 2] = 1 kpts[:, 4] = 1 kpts_ = kpts if scale_factor is None: scale_factor = 1.0 # print('[mpl_keypoint.draw_keypoints] kwargs = ' + ut.repr2(kwargs)) # ellipse and point properties pts_size = kwargs.get('pts_size', 2) pts_alpha = kwargs.get('pts_alpha', 1.0) ell_alpha = kwargs.get('ell_alpha', 1.0) ell_linewidth = kwargs.get('ell_linewidth', 2) ell_color = kwargs.get('ell_color', None) if ell_color is None: ell_color = [1, 0, 0] # colors pts_color = kwargs.get('pts_color', ell_color) rect_color = kwargs.get('rect_color', ell_color) eig_color = kwargs.get('eig_color', ell_color) ori_color = kwargs.get('ori_color', ell_color) # linewidths eig_linewidth = kwargs.get('eig_linewidth', ell_linewidth) rect_linewidth = kwargs.get('rect_linewidth', ell_linewidth) ori_linewidth = kwargs.get('ori_linewidth', ell_linewidth) # Offset keypoints assert len(kpts_) > 0, 'cannot draw no keypoints1' kpts = ktool.offset_kpts(kpts_, offset, scale_factor) assert len(kpts) > 0, 'cannot draw no keypoints2' # Build list of keypoint shape transforms from unit circles to ellipes invVR_aff2Ds = get_invVR_aff2Ds(kpts, H=H) try: if sifts is not None: # SIFT descriptors pass_props( kwargs, siftkw, 'bin_color', 'arm1_color', 'arm2_color', 'arm1_lw', 'arm2_lw', 'stroke', 'arm_alpha', 'arm_alpha', 'multicolored_arms', ) mpl_sift.draw_sifts(ax, sifts, invVR_aff2Ds, **siftkw) if rect: # Bounding Rectangles rect_patches = rectangle_actors(invVR_aff2Ds) _draw_patches(ax, rect_patches, rect_color, ell_alpha, rect_linewidth) if ell: # Keypoint shape ell_patches = ellipse_actors(invVR_aff2Ds) _draw_patches(ax, ell_patches, ell_color, ell_alpha, ell_linewidth) if eig: # Shape eigenvectors eig_patches = eigenvector_actors(invVR_aff2Ds) _draw_patches(ax, eig_patches, eig_color, ell_alpha, eig_linewidth) if ori: # Keypoint orientation ori_patches = orientation_actors(kpts, H=H) _draw_patches(ax, ori_patches, ori_color, ell_alpha, ori_linewidth, ori_color) if pts: # Keypoint locations _xs, _ys = ktool.get_xys(kpts) if H is not None: # adjust for homogrpahy import vtool as vt _xs, _ys = vt.transform_points_with_homography( H, np.vstack((_xs, _ys))) pts_patches = _draw_pts(ax, _xs, _ys, pts_size, pts_color, pts_alpha) if pts_patches is not None: _draw_patches(ax, pts_patches, 'none', pts_alpha, pts_size, pts_color) except ValueError as ex: ut.printex(ex, '\n[mplkp] !!! ERROR') # print('_oris.shape = %r' % (_oris.shape,)) # print('_xs.shape = %r' % (_xs.shape,)) # print('_iv11s.shape = %r' % (_iv11s.shape,)) raise
def preproc_cropped_chips(depc, cid_list, tipid_list, config=None): """ CommandLine: python -m ibeis_flukematch.plugin --exec-preproc_cropped_chips --show Example: >>> # DISABLE_DOCTEST >>> from ibeis_flukematch.plugin import * # NOQA >>> ibs, aid_list = testdata_humpbacks() >>> config = CropChipConfig(crop_enabled=True) >>> cid_list = ibs.depc.get_rowids('chips', aid_list, config) >>> tipid_list = ibs.depc.get_rowids('Notch_Tips', aid_list, config) >>> depc = ibs.depc >>> list(preproc_cropped_chips(depc, cid_list, tipid_list, config)) >>> #cpid_list = ibs.depc.d.get_Cropped_Chips_rowids(aid_list, config) >>> #cpid_list = ibs.depc.w.Cropped_Chips.get_rowids(aid_list, config) >>> chip_list = ibs.depc.get('Cropped_Chips', aid_list, 'img', config) >>> notch_tips = ibs.depc.get('Cropped_Chips', aid_list, ('notch', 'left', 'right'), config) >>> import plottool as pt >>> ut.ensure_pylab_qt4() >>> for notch, chip, aid in ut.InteractiveIter(zip(notch_tips, chip_list, aid_list)): >>> pt.reset() >>> pt.imshow(chip) >>> print(ibs.depc.get('Cropped_Chips', [aid], 'img', config, read_extern=False)[0]) >>> kpts_ = np.array(notch) >>> pt.draw_kpts2(kpts_, pts=True, ell=False, pts_size=20) >>> pt.update() >>> ut.show_if_requested() """ # crop first img_list = depc.get_native_property(const.CHIP_TABLE, cid_list, 'img') tips_list = depc.get_native_property('Notch_Tips', tipid_list, ('left', 'notch', 'right')) #imgpath_list = depc.get_native_property(const.CHIP_TABLE, cid_list, 'img', # read_extern=False) cropped_chip_dpath = depc.controller.get_chipdir() + '_crop' ut.ensuredir(cropped_chip_dpath) #crop_path_list = [ut.augpath(path, '_crop' + config.get_hashid()) # for path in imgpath_list] #for img, tips, path in zip(img_list, tips_list, crop_path_list): for img, tips in zip(img_list, tips_list): left, notch, right = tips bbox = (0, 0, img.shape[1], img.shape[0] ) # default to bbox being whole image chip_size = (img.shape[1], img.shape[0]) if left[0] > right[0]: # HACK: Ugh, I don't like this # TODO: maybe move this to infer_kp? right, left = (left, right) if config['crop_enabled']: # figure out bbox (x, y, w, h) w/x, y on top left # assume left is on the left note: this may not be a good assumption # note: lol that's not a good assumption # what do when network predicts left on right and right on left? bbox = ( left[0], # leftmost x value 0, # top of the image (right[0] - left[0]), # width img.shape[0], # height ) if config['crop_dim_size'] is not None: # we're only resizing in x, but after the crop # as a result we need to make sure we use the image dimensions apparent to get the chip size # we want to preserve the aspect ratio of the crop, not the whole image new_x = config['crop_dim_size'] #ratio = bbox[2] / bbox[3] # w/h #new_y = int(new_x / ratio) #chip_size = (new_x, new_y) try: #print("[cropped-chips] %s: bbox: %r, l/n/r %r" % (path, bbox,tips)) chip_size = vt.get_scaled_size_with_width( new_x, bbox[2], bbox[3]) except OverflowError: print( "[cropped chip] WARNING: Probably got a bad keypoint prediction: bbox: %r" % (bbox, )) yield None M = vt.get_image_to_chip_transform(bbox, chip_size, 0) with ut.embed_on_exception_context: new_img = cv2.warpAffine(img, M[:-1, :], chip_size) notch_, left_, right_ = vt.transform_points_with_homography( M, np.array([notch, left, right]).T).T notch_ = bound_point(notch_, chip_size) left_ = bound_point(left_, chip_size) right_ = bound_point(right_, chip_size) #vt.imwrite(path, new_img) yield (new_img, bbox[2], bbox[3], M, notch_, left_, right_)
def wbia_plugin_kaggle7_chip_depc(depc, aid_list, config): r""" Refine localizations for CurvRank with Dependency Cache (depc) CommandLine: python -m wbia_kaggle7._plugin --test-wbia_plugin_kaggle7_chip_depc python -m wbia_kaggle7._plugin --test-wbia_plugin_kaggle7_chip_depc:0 Example: >>> # DISABLE_DOCTEST >>> from wbia_kaggle7._plugin import * # NOQA >>> import wbia >>> from wbia.init import sysres >>> dbdir = sysres.ensure_testdb_kaggle7() >>> ibs = wbia.opendb(dbdir=dbdir, allow_newdir=True) >>> aid_list = ibs.get_image_aids(1) >>> images = ibs.depc_annot.get('KaggleSevenChip', aid_list, 'image') >>> image = images[0] >>> assert ut.hash_data(image) in ['imlkoiskkykpbwozghmpidlqwbmglzhw'] """ padding = config['chip_padding'] tips_list = depc.get('Notch_Tips', aid_list) size_list = depc.get('chips', aid_list, ('width', 'height')) config_ = { 'dim_size': 1550, 'resize_dim': 'width', 'ext': '.jpg', } chip_list = depc.get('chips', aid_list, 'img', config=config_, ensure=True) tps = cv2.createThinPlateSplineShapeTransformer() zipped = list(zip(aid_list, tips_list, size_list, chip_list)) for aid, tip_list, size, chip in zipped: h0, w0, c0 = chip.shape notch = tip_list[0].copy() left = tip_list[1].copy() right = tip_list[2].copy() size = np.array(size, dtype=np.float32) notch /= size left /= size right /= size size = np.array([w0, h0], dtype=np.float32) notch *= size left *= size right *= size chip_ = chip.copy() h0, w0, c0 = chip_.shape left += padding notch += padding right += padding pad = np.zeros((h0, padding, 3), dtype=chip_.dtype) chip_ = np.hstack((pad, chip_, pad)) h, w, c = chip_.shape pad = np.zeros((padding, w, 3), dtype=chip_.dtype) chip_ = np.vstack((pad, chip_, pad)) h, w, c = chip_.shape delta = right - left radian = np.arctan2(delta[1], delta[0]) degree = np.degrees(radian) M = cv2.getRotationMatrix2D((left[1], left[0]), degree, 1) chip_ = cv2.warpAffine(chip_, M, (w, h), flags=cv2.INTER_LANCZOS4) H = np.vstack((M, [0, 0, 1])) vert_list = np.array([notch, left, right]) vert_list_ = vt.transform_points_with_homography(H, vert_list.T).T notch, left, right = vert_list_ left[0] -= padding // 2 left[1] -= padding // 2 notch[1] += padding // 2 right[0] += padding // 2 right[1] -= padding // 2 sshape = np.array([left, notch, right], np.float32) tshape = np.array([[0, 0], [w0 // 2, h0], [w0, 0]], np.float32) sshape = sshape.reshape(1, -1, 2) tshape = tshape.reshape(1, -1, 2) matches = [ cv2.DMatch(0, 0, 0), cv2.DMatch(1, 1, 0), cv2.DMatch(2, 2, 0), ] tps.clear() tps.estimateTransformation(tshape, sshape, matches) chip_ = tps.warpImage(chip_) chip_ = chip_[:h0, :w0, :] chip_h, chip_w = chip_.shape[:2] yield ( chip_, chip_w, chip_h, )
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 ibeis.scripts.fix_annotation_orientation_issue fix_annotation_orientation Example: >>> # ENABLE_DOCTEST >>> import ibeis >>> from ibeis.scripts.fix_annotation_orientation_issue import * # NOQA >>> ibs = ibeis.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), ) print('Found %d images with non-standard orientations' % args) aids_list = ibs.get_image_aids(gid_list, is_staged=None, __check_staged__=False) 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) print( '\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, ) print('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, __check_staged__=False) 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), ) print('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]]) # print(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) # print(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 # print(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) print( '\tFixing GID %r, Orient %r, AID %r: Overlap %0.2f, Area %0.2f (%0.2f %%)' % args) if fixed_percentage < min_percentage: print('\tWARNING: FIXING DID NOT CORRECT AID %r' % (aid, )) unfixable_gid_list.append(gid) print('Un-fixable gid_list = %r' % (unfixable_gid_list, )) return unfixable_gid_list
for location, color in zip(location_list, color_list): cv2.circle(chip1_, location, 5, color=color) chip_filename = 'img_aid_%d_1.png' % (aid, ) chip_filepath = join(notch_path, chip_filename) cv2.imwrite(chip_filepath, chip1_) delta = right - left radian = np.arctan2(delta[1], delta[0]) degree = np.degrees(radian) M = cv2.getRotationMatrix2D((left[1], left[0]), degree, 1) chip2 = cv2.warpAffine(chip1, M, (w, h), flags=cv2.INTER_LANCZOS4) H = np.vstack((M, [0, 0, 1])) vert_list = np.array([notch, left, right]) vert_list_ = vt.transform_points_with_homography(H, vert_list.T).T notch, left, right = vert_list_ location_list = [ tuple(map(int, np.around(notch))), tuple(map(int, np.around(left))), tuple(map(int, np.around(right))), ] chip2_ = chip2.copy() for location, color in zip(location_list, color_list): cv2.circle(chip2_, location, 5, color=color) chip_filename = 'img_aid_%d_2.png' % (aid, ) chip_filepath = join(notch_path, chip_filename) cv2.imwrite(chip_filepath, chip2_)
def preproc_cropped_chips(depc, cid_list, tipid_list, config=None): """ CommandLine: python -m ibeis_flukematch.plugin --exec-preproc_cropped_chips --show Example: >>> # DISABLE_DOCTEST >>> from ibeis_flukematch.plugin import * # NOQA >>> ibs, aid_list = testdata_humpbacks() >>> config = CropChipConfig(crop_enabled=True) >>> cid_list = ibs.depc.get_rowids('chips', aid_list, config) >>> tipid_list = ibs.depc.get_rowids('Notch_Tips', aid_list, config) >>> depc = ibs.depc >>> list(preproc_cropped_chips(depc, cid_list, tipid_list, config)) >>> #cpid_list = ibs.depc.d.get_Cropped_Chips_rowids(aid_list, config) >>> #cpid_list = ibs.depc.w.Cropped_Chips.get_rowids(aid_list, config) >>> chip_list = ibs.depc.get('Cropped_Chips', aid_list, 'img', config) >>> notch_tips = ibs.depc.get('Cropped_Chips', aid_list, ('notch', 'left', 'right'), config) >>> import plottool as pt >>> ut.ensure_pylab_qt4() >>> for notch, chip, aid in ut.InteractiveIter(zip(notch_tips, chip_list, aid_list)): >>> pt.reset() >>> pt.imshow(chip) >>> print(ibs.depc.get('Cropped_Chips', [aid], 'img', config, read_extern=False)[0]) >>> kpts_ = np.array(notch) >>> pt.draw_kpts2(kpts_, pts=True, ell=False, pts_size=20) >>> pt.update() >>> ut.show_if_requested() """ # crop first img_list = depc.get_native_property(const.CHIP_TABLE, cid_list, 'img') tips_list = depc.get_native_property('Notch_Tips', tipid_list, ('left', 'notch', 'right')) #imgpath_list = depc.get_native_property(const.CHIP_TABLE, cid_list, 'img', # read_extern=False) cropped_chip_dpath = depc.controller.get_chipdir() + '_crop' ut.ensuredir(cropped_chip_dpath) #crop_path_list = [ut.augpath(path, '_crop' + config.get_hashid()) # for path in imgpath_list] #for img, tips, path in zip(img_list, tips_list, crop_path_list): for img, tips in zip(img_list, tips_list): left, notch, right = tips bbox = (0, 0, img.shape[1], img.shape[0]) # default to bbox being whole image chip_size = (img.shape[1], img.shape[0]) if left[0] > right[0]: # HACK: Ugh, I don't like this # TODO: maybe move this to infer_kp? right, left = (left, right) if config['crop_enabled']: # figure out bbox (x, y, w, h) w/x, y on top left # assume left is on the left note: this may not be a good assumption # note: lol that's not a good assumption # what do when network predicts left on right and right on left? bbox = (left[0], # leftmost x value 0, # top of the image (right[0] - left[0]), # width img.shape[0], # height ) if config['crop_dim_size'] is not None: # we're only resizing in x, but after the crop # as a result we need to make sure we use the image dimensions apparent to get the chip size # we want to preserve the aspect ratio of the crop, not the whole image new_x = config['crop_dim_size'] #ratio = bbox[2] / bbox[3] # w/h #new_y = int(new_x / ratio) #chip_size = (new_x, new_y) try: #print("[cropped-chips] %s: bbox: %r, l/n/r %r" % (path, bbox,tips)) chip_size = vt.get_scaled_size_with_width(new_x, bbox[2], bbox[3]) except OverflowError: print("[cropped chip] WARNING: Probably got a bad keypoint prediction: bbox: %r" % (bbox,)) yield None M = vt.get_image_to_chip_transform(bbox, chip_size, 0) with ut.embed_on_exception_context: new_img = cv2.warpAffine(img, M[:-1, :], chip_size) notch_, left_, right_ = vt.transform_points_with_homography(M, np.array([notch, left, right]).T).T notch_ = bound_point(notch_, chip_size) left_ = bound_point(left_, chip_size) right_ = bound_point(right_, chip_size) #vt.imwrite(path, new_img) yield (new_img, bbox[2], bbox[3], M, notch_, left_, right_)
def draw_keypoints(ax, kpts_, scale_factor=1.0, offset=(0.0, 0.0), rotation=0.0, ell=True, pts=False, rect=False, eig=False, ori=False, sifts=None, siftkw={}, H=None, **kwargs): """ draws keypoints extracted by pyhesaff onto a matplotlib axis FIXME: There is probably a matplotlib bug here. If you specify two different alphas in a collection, whatever the last alpha was gets applied to everything Args: ax (mpl.Axes): kpts (ndarray): keypoints [[x, y, a, c, d, theta], ...] scale_factor (float): offset (tuple): rotation (float): ell (bool): pts (bool): rect (bool): eig (bool): ori (bool): sifts (None): References: http://stackoverflow.com/questions/28401788/using-homogeneous-transforms-non-affine-with-matplotlib-patches CommandLine: python -m plottool.mpl_keypoint --test-draw_keypoints --show Example: >>> # ENABLE_DOCTEST >>> from plottool.mpl_keypoint import * # NOQA >>> from plottool.mpl_keypoint import _draw_patches, _draw_pts # NOQA >>> import plottool as pt >>> import vtool as vt >>> imgBGR = vt.get_star_patch(jitter=True) >>> H = np.array([[1, 0, 0], [.5, 2, 0], [0, 0, 1]]) >>> H = None >>> TAU = 2 * np.pi >>> kpts_ = vt.make_test_image_keypoints(imgBGR, scale=.5, skew=2, theta=TAU / 8.0) >>> scale_factor=1.0 >>> offset=(0.0, 0.0) >>> rotation=0.0 >>> ell=True >>> pts=True >>> rect=True >>> eig=True >>> ori=True >>> # make random sifts >>> sifts = mpl_sift.testdata_sifts() >>> siftkw = {} >>> kwargs = dict(ori_color=[0, 1, 0], rect_color=[0, 0, 1], eig_color=[1, 1, 0], pts_size=.1) >>> w, h = imgBGR.shape[0:2][::-1] >>> imgBGR_ = imgBGR if H is None else vt.warpAffine(imgBGR, H, (w * 2, h * 2)) >>> fig, ax = pt.imshow(imgBGR_ * 255) >>> draw_keypoints(ax, kpts_, scale_factor, offset, rotation, ell, pts, ... rect, eig, ori, sifts, siftkw, H=H, **kwargs) >>> pt.iup() >>> pt.show_if_requested() """ if kpts_.shape[1] == 2: # pad out structure if only xy given kpts = np.zeros((len(kpts_), 6)) kpts[:, 0:2] = kpts_ kpts[:, 2] = 1 kpts[:, 4] = 1 kpts_ = kpts if scale_factor is None: scale_factor = 1.0 #print('[mpl_keypoint.draw_keypoints] kwargs = ' + ut.dict_str(kwargs)) # ellipse and point properties pts_size = kwargs.get('pts_size', 2) pts_alpha = kwargs.get('pts_alpha', 1.0) ell_alpha = kwargs.get('ell_alpha', 1.0) ell_linewidth = kwargs.get('ell_linewidth', 2) ell_color = kwargs.get('ell_color', None) if ell_color is None: ell_color = [1, 0, 0] # colors pts_color = kwargs.get('pts_color', ell_color) rect_color = kwargs.get('rect_color', ell_color) eig_color = kwargs.get('eig_color', ell_color) ori_color = kwargs.get('ori_color', ell_color) # linewidths eig_linewidth = kwargs.get('eig_linewidth', ell_linewidth) rect_linewidth = kwargs.get('rect_linewidth', ell_linewidth) ori_linewidth = kwargs.get('ori_linewidth', ell_linewidth) # Offset keypoints assert len(kpts_) > 0, 'cannot draw no keypoints1' kpts = ktool.offset_kpts(kpts_, offset, scale_factor) assert len(kpts) > 0, 'cannot draw no keypoints2' # Build list of keypoint shape transforms from unit circles to ellipes invVR_aff2Ds = get_invVR_aff2Ds(kpts, H=H) try: if sifts is not None: # SIFT descriptors pass_props(kwargs, siftkw, 'bin_color', 'arm1_color', 'arm2_color', 'arm1_lw', 'arm2_lw', 'arm_alpha', 'arm_alpha', 'multicolored_arms') mpl_sift.draw_sifts(ax, sifts, invVR_aff2Ds, **siftkw) if rect: # Bounding Rectangles rect_patches = rectangle_actors(invVR_aff2Ds) _draw_patches(ax, rect_patches, rect_color, ell_alpha, rect_linewidth) if ell: # Keypoint shape ell_patches = ellipse_actors(invVR_aff2Ds) _draw_patches(ax, ell_patches, ell_color, ell_alpha, ell_linewidth) if eig: # Shape eigenvectors eig_patches = eigenvector_actors(invVR_aff2Ds) _draw_patches(ax, eig_patches, eig_color, ell_alpha, eig_linewidth) if ori: # Keypoint orientation ori_patches = orientation_actors(kpts, H=H) _draw_patches(ax, ori_patches, ori_color, ell_alpha, ori_linewidth, ori_color) if pts: # Keypoint locations _xs, _ys = ktool.get_xys(kpts) if H is not None: # adjust for homogrpahy import vtool as vt _xs, _ys = vt.transform_points_with_homography(H, np.vstack((_xs, _ys))) pts_patches = _draw_pts(ax, _xs, _ys, pts_size, pts_color, pts_alpha) if pts_patches is not None: _draw_patches(ax, pts_patches, 'none', pts_alpha, pts_size, pts_color) except ValueError as ex: ut.printex(ex, '\n[mplkp] !!! ERROR') #print('_oris.shape = %r' % (_oris.shape,)) #print('_xs.shape = %r' % (_xs.shape,)) #print('_iv11s.shape = %r' % (_iv11s.shape,)) raise