def get_affine_matrix(fixed_points, registering_points): print("\nGetting affine transform.") fixed_points = invert_xy_order(fixed_points) registering_points = invert_xy_order(registering_points) trans = affine6p.estimate(fixed_points, registering_points) warp_mtx = np.array(trans.get_matrix())[:2, :] return warp_mtx
def affine_calculate(p, p0): """ Takes two m x 2 lists or numpy arrays of points, calculated the affine transformation matrix to move p -> p0 """ p1 = np.array(p) p2 = np.array(p0) T = affine6p.estimate(p, p0).get_matrix() return T
def array_to_geotif(array_data, tif_name, tile_corner, save_folder=f"intermediate/geotifs", affine_option='4corners'): """Convert an array into a geoTIF, which is a format required to intersect with ROI polygon. """ if affine_option == '4corners': origin = [[1, 1], [1, array_data.shape[2]], [array_data.shape[1], array_data.shape[2]], [array_data.shape[1], 1]] convert = tile_corner trans_matrix = affine6p.estimate(origin, convert).get_matrix() transform = Affine(trans_matrix[0][1], trans_matrix[0][0], trans_matrix[0][2], trans_matrix[1][1], trans_matrix[1][0], trans_matrix[1][2]) elif affine_option == '4bounds': west = min(tile_corner[0][0], tile_corner[3][0]) south = min(tile_corner[2][1], tile_corner[3][1]) east = max(tile_corner[1][0], tile_corner[2][0]) north = max(tile_corner[0][1], tile_corner[1][1]) bearing = GetBearing(tile_corner[0], tile_corner[1]) transform = rasterio.transform.from_bounds( west, south, east, north, array_data.shape[1], array_data.shape[2]) #* Affine.rotation(bearing) #FIXME: to be further tested else: print(f"Affine option {affine_option} not supported...Aborting") return # Save png as geoTIF with rasterio.open(f"{bucket}/{save_folder}/{tif_name}", 'w', driver='GTiff', height=array_data.shape[1], width=array_data.shape[2], count=3, dtype=array_data.dtype, crs='EPSG:4326', transform=transform) as dst: dst.write(array_data) return transform
def transform_v1(phi_orig, largestCC): flip_shp_prior = 1 - largestCC # trans_dist returns the min distance between 1 to 0 in the matrix trans_dist, trans_idx = scipy.ndimage.distance_transform_edt( flip_shp_prior, sampling=[1, 1], return_indices=True) x_tar, y_tar = trans_idx[0], trans_idx[1] x_tar = (x_tar * phi_orig).astype('int32') y_tar = (y_tar * phi_orig).astype('int32') x_src = np.zeros(x_tar.shape) for row in range(x_src.shape[0]): x_src[row, :] = row y_src = np.zeros(y_tar.shape) for col in range(y_src.shape[1]): y_src[:, col] = col x_src = (x_src * phi_orig).astype('int32') y_src = (y_src * phi_orig).astype('int32') x_nonzero_idx, y_nonzero_idx = np.where(x_tar != 0) tar_pts_coor = np.array( [x_tar[np.where(x_tar != 0)], y_tar[np.where(x_tar != 0)]]).T src_pts_coor = np.array( [x_src[np.where(x_tar != 0)], y_src[np.where(x_tar != 0)]]).T trans = affine6p.estimate(src_pts_coor, tar_pts_coor) M = trans.get_matrix() M = np.array(M) print(M[0:2, :]) print(src_pts_coor.shape) rows, cols = phi_orig.shape dst_img = np.zeros((rows, cols)) for i in range(src_pts_coor.shape[0]): dst_pt = np.array(trans.transform(src_pts_coor[i])) dst_pt = dst_pt.astype('int32') if np.all(dst_pt >= 0) and dst_pt[0] < rows and dst_pt[1] < cols: dst_img[dst_pt[0], dst_pt[1]] = 1 return dst_img
def test_affine6p(self): ''' should affine6p correctly ''' for sple in samples: # check estimate t = affine6p.estimate(sple['a'], sple['b']) print("matrix = {0}".format(t.get_matrix())) for k in range(0, 6): msg = sple['id'] + ': ' + str(k) + '=' + str(t.params[k]) self.assertTrue( abs(t.params[k] - sple["params"][k]) < 0.001, msg) # check functions print("{0} -> {1}".format(sple['a'], sple['b'])) print("matrix = {0}".format(t.get_matrix())) print("rotation_x = {0}".format(t.get_rotation_x())) print("rotation_y = {0}".format(t.get_rotation_y())) print("scale_x = {0}".format(t.get_scale_x())) print("scale_y = {0}".format(t.get_scale_y())) print("scale = {0}".format(t.get_scale())) print("translation = {0}".format(t.get_translation())) print(" ") # check estimate_error e = affine6p.estimate_error(t, sple['a'], sple['b']) msg = sple['id'] + ': error =' + str(e) self.assertTrue(abs(e - sple["error"]) < 0.001, msg) # check transform_inv if len(sple['a']) == 3: for k in range(0, 3): b2 = t.transform_inv(sple['b'][k]) for l in range(0, 2): msg = sple['id'] + ': a2 =' + str(b2[l]) self.assertTrue( abs(b2[l] - sple["a"][k][l]) < 0.001, msg)
"y"]]) # extract the coordinates in meters for the same points m_coords # %% [markdown] # we determine the transform between the two, we know the two set of points do correspont to each other and there must be a transform between the two # we use an affine transform for this... via affine6p (or nudged library if you prefer) # %% #pip install affine6p --user if not installed already # %% import affine6p # using a complete affine transform is a little overkill in our case, but in the general situation migh be desirable, especially when workin on scanned imagery # %% T = affine6p.estimate(px_coords.tolist(), m_coords.tolist()) err = affine6p.estimate_error(T, px_coords.tolist(), m_coords.tolist()) # mean squared distance np.sqrt(err) # around 20 cm average error due to digitalization # %% [markdown] # we got a very low error, good! # %% [markdown] # we have our transform, now we work with the picture # # %% figure(figsize=(10, 10)) # fast inspection imshow(im)