def test_pytorch_grid(): c_dst = np.array([ [0., 0], [1., 0], [1, 1], [0, 1], ], dtype=np.float32) c_src = np.array([ [10., 10], [20., 10], [20, 20], [10, 20], ], dtype=np.float32) / 40. theta = tps.tps_theta_from_points(c_src, c_dst) theta_r = tps.tps_theta_from_points(c_src, c_dst, reduced=True) np_grid = tps.tps_grid(theta, c_dst, (20, 20)) np_grid_r = tps.tps_grid(theta_r, c_dst, (20, 20)) pth_theta = torch.tensor(theta).unsqueeze(0) pth_grid = tps.torch.tps_grid(pth_theta, torch.tensor(c_dst), (1, 1, 20, 20)).squeeze().numpy() pth_grid = (pth_grid + 1) / 2 # convert [-1,1] range to [0,1] pth_theta_r = torch.tensor(theta_r).unsqueeze(0) pth_grid_r = tps.torch.tps_grid(pth_theta_r, torch.tensor(c_dst), (1, 1, 20, 20)).squeeze().numpy() pth_grid_r = (pth_grid_r + 1) / 2 # convert [-1,1] range to [0,1] assert_allclose(np_grid, pth_grid) assert_allclose(np_grid_r, pth_grid_r) assert_allclose(np_grid_r, np_grid)
def tps_transform(img, dshape=None): while True: point1 = round(random.uniform(0.3, 0.7), 2) point2 = round(random.uniform(0.3, 0.7), 2) range_1 = round(random.uniform(-0.25, 0.25), 2) range_2 = round(random.uniform(-0.25, 0.25), 2) if math.isclose(point1 + range_1, point2 + range_2): continue else: break c_src = np.array([ [0.0, 0.0], [1., 0], [1, 1], [0, 1], [point1, point1], [point2, point2], ]) c_dst = np.array([ [0., 0], [1., 0], [1, 1], [0, 1], [point1 + range_1, point1 + range_1], [point2 + range_2, point2 + range_2], ]) dshape = dshape or img.shape theta = tps.tps_theta_from_points(c_src, c_dst, reduced=True) grid = tps.tps_grid(theta, c_dst, dshape) mapx, mapy = tps.tps_grid_to_remap(grid, img.shape) return cv2.remap(img, mapx, mapy, cv2.INTER_CUBIC)
def warp_dual_cv(img, mask, c_src, c_dst): dshape = img.shape theta = tps.tps_theta_from_points(c_src, c_dst, reduced=True) grid = tps.tps_grid(theta, c_dst, dshape) mapx, mapy = tps.tps_grid_to_remap(grid, img.shape) return cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR), cv2.remap(mask, mapx, mapy, cv2.INTER_NEAREST)
def test_numpy_densegrid(): # enlarges a small rectangle to full view import cv2 img = np.zeros((40, 40), dtype=np.uint8) img[10:21, 10:21] = 255 c_dst = np.array([ [0., 0], [1., 0], [1, 1], [0, 1], ]) c_src = np.array([ [10., 10], [20., 10], [20, 20], [10, 20], ]) / 40. theta = tps.tps_theta_from_points(c_src, c_dst) theta_r = tps.tps_theta_from_points(c_src, c_dst, reduced=True) grid = tps.tps_grid(theta, c_dst, (20, 20)) grid_r = tps.tps_grid(theta_r, c_dst, (20, 20)) mapx, mapy = tps.tps_grid_to_remap(grid, img.shape) warped = cv2.remap(img, mapx, mapy, cv2.INTER_CUBIC) assert img.min() == 0. assert img.max() == 255. assert warped.shape == (20, 20) assert warped.min() == 255. assert warped.max() == 255. assert np.linalg.norm(grid.reshape(-1, 2) - grid_r.reshape(-1, 2)) < 1e-3
def get_tps_thetas(self, num_images): c_src = np.array([ [0.0, 0.0], [1., 0], [1, 1], [0, 1], [0.2, 0.3], [0.6, 0.7], ]) theta_list = [] dst_list = [] for i in range(num_images): c_dst = c_src + np.random.uniform(-1, 1, (6, 2)) / 20 theta = tps.tps_theta_from_points(c_src, c_dst) theta_list.append(torch.from_numpy(theta).unsqueeze(0)) dst_list.append(torch.from_numpy(c_dst).unsqueeze(0)) theta = torch.cat(theta_list, dim=0).float() dst = torch.cat(dst_list, dim=0).float() return theta, dst
def warp_image_cv(img, c_src, c_dst, dshape=None): dshape = dshape or img.shape theta = tps.tps_theta_from_points(c_src, c_dst, reduced=True) grid = tps.tps_grid(theta, c_dst, dshape) mapx, mapy = tps.tps_grid_to_remap(grid, img.shape) return cv2.remap(img, mapx, mapy, cv2.INTER_CUBIC)