def kpts_matrices(kpts): # We are given the keypoint in invA format # invV = perdoch.invA # V = perdoch.A # Z = perdoch.E # invert into V #invV = kpts_to_invV(kpts) invV = ktool.get_invV_mats3x3(kpts) V = ktool.invert_invV_mats(invV) Z = ktool.get_Z_mats(V) return invV, V, Z
def check_kpts_in_bounds(kpts_, width, height): # Test to make sure the extents of the keypoints are in bounds unit_bbox = np.array([(-1, -1, 1), (-1, 1, 1), (1, -1, 1), (1, 1, 1)]).T #invV = kpts_to_invV(kpts_) invV = ktool.get_invV_mats3x3(kpts_) bbox_pts = [v.dot(unit_bbox)[0:2] for v in invV] maxx = np.array([pts[0].max() for pts in bbox_pts]) < width minx = np.array([pts[0].min() for pts in bbox_pts]) > 0 maxy = np.array([pts[1].max() for pts in bbox_pts]) < height miny = np.array([pts[1].min() for pts in bbox_pts]) > 0 isvalid = np.array(maxx * minx * maxy * miny, dtype=np.bool) return isvalid
def check_kpts_in_bounds(kpts_, width, height): # Test to make sure the extents of the keypoints are in bounds unit_bbox = np.array([(-1, -1, 1), (-1, 1, 1), ( 1, -1, 1), ( 1, 1, 1)]).T #invV = kpts_to_invV(kpts_) invV = ktool.get_invV_mats3x3(kpts_) bbox_pts = [v.dot(unit_bbox)[0:2] for v in invV] maxx = np.array([pts[0].max() for pts in bbox_pts]) < width minx = np.array([pts[0].min() for pts in bbox_pts]) > 0 maxy = np.array([pts[1].max() for pts in bbox_pts]) < height miny = np.array([pts[1].min() for pts in bbox_pts]) > 0 isvalid = np.array(maxx * minx * maxy * miny, dtype=np.bool) return isvalid
def sample_uniform(kpts, nSamples=128): """ SeeAlso: python -m pyhesaff.tests.test_ellipse --test-in_depth_ellipse --show """ nKp = len(kpts) # Get keypoint matrix forms invV_mats3x3 = ktool.get_invV_mats3x3(kpts) V_mats3x3 = ktool.invert_invV_mats(invV_mats3x3) #------------------------------- # Get uniform points on a circle circle_pts = homogenous_circle_pts(nSamples + 1)[0:-1] assert circle_pts.shape == (nSamples, 3) #------------------------------- # Get uneven points sample (get_uneven_point_sample) polygon1_list = matrix_multiply(invV_mats3x3, circle_pts.T).transpose(0, 2, 1) assert polygon1_list.shape == (nKp, nSamples, 3) # ------------------------------- # The transformed points are not sampled uniformly... Bummer # We will sample points evenly across the sampled polygon # then we will project them onto the ellipse dists = np.array([circular_distance(arr) for arr in polygon1_list]) assert dists.shape == (nKp, nSamples) # perimeter of the polygon perimeter = dists.sum(1) assert perimeter.shape == (nKp, ) # Take a perfect multiple of steps along the perimeter multiplier = 1 step_size = perimeter / (nSamples * multiplier) assert step_size.shape == (nKp, ) # Walk along edge num_steps_list = [] offset_list = [] total_dist = np.zeros(step_size.shape) # step_size.copy() dist_walked = np.zeros(step_size.shape) assert dist_walked.shape == (nKp, ) assert total_dist.shape == (nKp, ) distsT = dists.T assert distsT.shape == (nSamples, nKp) # This loops over the pt samples and performs the operation for every keypoint for count in range(nSamples): segment_len = distsT[count] # Find where your starting location is offset_list.append(total_dist - dist_walked) # How far can you possibly go? total_dist += segment_len # How many steps can you take? num_steps = (total_dist - dist_walked) // step_size num_steps_list.append(num_steps) # Log how much further youve gotten dist_walked += (num_steps * step_size) # Check for floating point errors # take an extra step if you need to num_steps_list[-1] += np.round((perimeter - dist_walked) / step_size) assert np.all(np.array(num_steps_list).sum(0) == nSamples) """ #offset_iter1 = zip(num_steps_list, distsT, offset_list) #offset_list = [((step_size - offset) / dist, ((num * step_size) - offset) / dist, num) #for num, dist, offset in zip(num_steps_list, distsT, offset_list)] #offset_iter2 = offset_list #cut_locs = [[ #np.linspace(off1, off2, n, endpoint=True) for (off1, off2, n) in zip(offset1, offset2, num)] #for (offset1, offset2, num) in offset_iter2 #] # store the percent location at each line segment where # the cut will be made """ # HERE IS NEXT cut_list = [] # This loops over the pt samples and performs the operation for every keypoint for num, dist, offset in zip(num_steps_list, distsT, offset_list): #if num == 0 #cut_list.append([]) #continue # This was a bitch to keep track of offset1 = (step_size - offset) / dist offset2 = ((num * step_size) - offset) / dist cut_locs = [ np.linspace(off1, off2, n, endpoint=True) for (off1, off2, n) in zip(offset1, offset2, num) ] # post check for divide by 0 cut_locs = [ np.array([0 if np.isinf(c) else c for c in cut]) for cut in cut_locs ] cut_list.append(cut_locs) cut_list = np.array(cut_list).T assert cut_list.shape == (nKp, nSamples) # ================= # METHOD 1 # ================= # Linearly interpolate between points on the polygons at the places we cut def interpolate(pt1, pt2, percent): # interpolate between point1 and point2 return ((1 - percent) * pt1) + ((percent) * pt2) def polygon_points(polygon_pts, dist_list): return np.array([ interpolate(polygon_pts[count], polygon_pts[(count + 1) % nSamples], loc) for count, locs in enumerate(dist_list) for loc in iter(locs) ]) new_locations = np.array([ polygon_points(polygon_pts, cuts) for polygon_pts, cuts in zip(polygon1_list, cut_list) ]) # ================= # ================= # METHOD 2 """ #from itertools import cycle as icycle #from itertools import islice #def icycle_shift1(iterable): #return islice(icycle(poly_pts), 1, len(poly_pts) + 1) #cutptsIter_list = [zip(iter(poly_pts), icycle_shift1(poly_pts), cuts) #for poly_pts, cuts in zip(polygon1_list, cut_list)] #new_locations = [[[((1 - cut) * pt1) + ((cut) * pt2) for cut in cuts] #for (pt1, pt2, cuts) in cutPtsIter] #for cutPtsIter in cutptsIter_list] """ # ================= # assert new_locations.shape == (nKp, nSamples, 3) # Warp new_locations to the unit circle #new_unit = V.dot(new_locations.T).T new_unit = np.array( [v.dot(newloc.T).T for v, newloc in zip(V_mats3x3, new_locations)]) # normalize new_unit new_mag = np.sqrt((new_unit**2).sum(-1)) new_unorm_unit = new_unit / np.dstack([new_mag] * 3) new_norm_unit = new_unorm_unit / np.dstack([new_unorm_unit[:, :, 2]] * 3) # Get angle (might not be necessary) #x_axis = np.array([1, 0, 0]) #arccos_list = x_axis.dot(new_norm_unit.T) #uniform_theta_list = np.arccos(arccos_list) # Maybe this? # Find the angle from the center of the circle theta_list2 = np.arctan2(new_norm_unit[:, :, 1], new_norm_unit[:, :, 0]) # assert uniform_theta_list.shape = (nKp, nSample) # Use this angle to unevenly sample the perimeter of the circle uneven_cicrle_pts = np.dstack( [np.cos(theta_list2), np.sin(theta_list2), np.ones(theta_list2.shape)]) # The uneven circle points were sampled in such a way that when they are # transformeed they will be approximately uniform along the boundary of the # ellipse. uniform_ell_hpts = [ v.dot(pts.T).T for (v, pts) in zip(invV_mats3x3, uneven_cicrle_pts) ] # Remove the homogenous coordinate and we're done ell_border_pts_list = [pts[:, 0:2] for pts in uniform_ell_hpts] return ell_border_pts_list
def sample_uniform(kpts, nSamples=128): """ SeeAlso: python -m pyhesaff.tests.test_ellipse --test-in_depth_ellipse --show """ nKp = len(kpts) # Get keypoint matrix forms invV_mats3x3 = ktool.get_invV_mats3x3(kpts) V_mats3x3 = ktool.invert_invV_mats(invV_mats3x3) #------------------------------- # Get uniform points on a circle circle_pts = homogenous_circle_pts(nSamples + 1)[0:-1] assert circle_pts.shape == (nSamples, 3) #------------------------------- # Get uneven points sample (get_uneven_point_sample) polygon1_list = matrix_multiply(invV_mats3x3, circle_pts.T).transpose(0, 2, 1) assert polygon1_list.shape == (nKp, nSamples, 3) # ------------------------------- # The transformed points are not sampled uniformly... Bummer # We will sample points evenly across the sampled polygon # then we will project them onto the ellipse dists = np.array([circular_distance(arr) for arr in polygon1_list]) assert dists.shape == (nKp, nSamples) # perimeter of the polygon perimeter = dists.sum(1) assert perimeter.shape == (nKp,) # Take a perfect multiple of steps along the perimeter multiplier = 1 step_size = perimeter / (nSamples * multiplier) assert step_size.shape == (nKp,) # Walk along edge num_steps_list = [] offset_list = [] total_dist = np.zeros(step_size.shape) # step_size.copy() dist_walked = np.zeros(step_size.shape) assert dist_walked.shape == (nKp,) assert total_dist.shape == (nKp,) distsT = dists.T assert distsT.shape == (nSamples, nKp) # This loops over the pt samples and performs the operation for every keypoint for count in range(nSamples): segment_len = distsT[count] # Find where your starting location is offset_list.append(total_dist - dist_walked) # How far can you possibly go? total_dist += segment_len # How many steps can you take? num_steps = (total_dist - dist_walked) // step_size num_steps_list.append(num_steps) # Log how much further youve gotten dist_walked += (num_steps * step_size) # Check for floating point errors # take an extra step if you need to num_steps_list[-1] += np.round((perimeter - dist_walked) / step_size) assert np.all(np.array(num_steps_list).sum(0) == nSamples) """ #offset_iter1 = zip(num_steps_list, distsT, offset_list) #offset_list = [((step_size - offset) / dist, ((num * step_size) - offset) / dist, num) #for num, dist, offset in zip(num_steps_list, distsT, offset_list)] #offset_iter2 = offset_list #cut_locs = [[ #np.linspace(off1, off2, n, endpoint=True) for (off1, off2, n) in zip(offset1, offset2, num)] #for (offset1, offset2, num) in offset_iter2 #] # store the percent location at each line segment where # the cut will be made """ # HERE IS NEXT cut_list = [] # This loops over the pt samples and performs the operation for every keypoint for num, dist, offset in zip(num_steps_list, distsT, offset_list): #if num == 0 #cut_list.append([]) #continue # This was a bitch to keep track of offset1 = (step_size - offset) / dist offset2 = ((num * step_size) - offset) / dist cut_locs = [np.linspace(off1, off2, n, endpoint=True) for (off1, off2, n) in zip(offset1, offset2, num)] # post check for divide by 0 cut_locs = [np.array([0 if np.isinf(c) else c for c in cut]) for cut in cut_locs] cut_list.append(cut_locs) cut_list = np.array(cut_list).T assert cut_list.shape == (nKp, nSamples) # ================= # METHOD 1 # ================= # Linearly interpolate between points on the polygons at the places we cut def interpolate(pt1, pt2, percent): # interpolate between point1 and point2 return ((1 - percent) * pt1) + ((percent) * pt2) def polygon_points(polygon_pts, dist_list): return np.array([interpolate(polygon_pts[count], polygon_pts[(count + 1) % nSamples], loc) for count, locs in enumerate(dist_list) for loc in iter(locs)]) new_locations = np.array([polygon_points(polygon_pts, cuts) for polygon_pts, cuts in zip(polygon1_list, cut_list)]) # ================= # ================= # METHOD 2 """ #from itertools import cycle as icycle #from itertools import islice #def icycle_shift1(iterable): #return islice(icycle(poly_pts), 1, len(poly_pts) + 1) #cutptsIter_list = [zip(iter(poly_pts), icycle_shift1(poly_pts), cuts) #for poly_pts, cuts in zip(polygon1_list, cut_list)] #new_locations = [[[((1 - cut) * pt1) + ((cut) * pt2) for cut in cuts] #for (pt1, pt2, cuts) in cutPtsIter] #for cutPtsIter in cutptsIter_list] """ # ================= # assert new_locations.shape == (nKp, nSamples, 3) # Warp new_locations to the unit circle #new_unit = V.dot(new_locations.T).T new_unit = np.array([v.dot(newloc.T).T for v, newloc in zip(V_mats3x3, new_locations)]) # normalize new_unit new_mag = np.sqrt((new_unit ** 2).sum(-1)) new_unorm_unit = new_unit / np.dstack([new_mag] * 3) new_norm_unit = new_unorm_unit / np.dstack([new_unorm_unit[:, :, 2]] * 3) # Get angle (might not be necessary) #x_axis = np.array([1, 0, 0]) #arccos_list = x_axis.dot(new_norm_unit.T) #uniform_theta_list = np.arccos(arccos_list) # Maybe this? # Find the angle from the center of the circle theta_list2 = np.arctan2(new_norm_unit[:, :, 1], new_norm_unit[:, :, 0]) # assert uniform_theta_list.shape = (nKp, nSample) # Use this angle to unevenly sample the perimeter of the circle uneven_cicrle_pts = np.dstack([np.cos(theta_list2), np.sin(theta_list2), np.ones(theta_list2.shape)]) # The uneven circle points were sampled in such a way that when they are # transformeed they will be approximately uniform along the boundary of the # ellipse. uniform_ell_hpts = [v.dot(pts.T).T for (v, pts) in zip(invV_mats3x3, uneven_cicrle_pts)] # Remove the homogenous coordinate and we're done ell_border_pts_list = [pts[:, 0:2] for pts in uniform_ell_hpts] return ell_border_pts_list