def test_fundamental_matrix_forward(): essential_matrix_tform = EssentialMatrixTransform( rotation=np.eye(3), translation=np.array([1, 0, 0])) tform = FundamentalMatrixTransform() tform.params = essential_matrix_tform.params src = np.array([[0, 0], [0, 1], [1, 1]]) assert_almost_equal(tform(src), [[0, -1, 0], [0, -1, 1], [0, -1, 1]])
def test_fundamental_matrix_residuals(): essential_matrix_tform = EssentialMatrixTransform(rotation=np.eye(3), translation=np.array([1, 0, 0])) tform = FundamentalMatrixTransform() tform.params = essential_matrix_tform.params src = np.array([[0, 0], [0, 0], [0, 0]]) dst = np.array([[2, 0], [2, 1], [2, 2]]) assert_almost_equal(tform.residuals(src, dst) ** 2, [0, 0.5, 2])
def test_fundamental_matrix_residuals(): essential_matrix_tform = EssentialMatrixTransform( rotation=np.eye(3), translation=np.array([1, 0, 0])) tform = FundamentalMatrixTransform() tform.params = essential_matrix_tform.params src = np.array([[0, 0], [0, 0], [0, 0]]) dst = np.array([[2, 0], [2, 1], [2, 2]]) assert_almost_equal(tform.residuals(src, dst)**2, [0, 0.5, 2])
def modify_FM(FM, n, matches): FM_with_error = [] FM_Matrix_original = FM.FM_Matrix.params epsilon_array = [i for i in range(-1 * n, n + 1)] epsilon_array = np.array(epsilon_array) epsilon_matrix = np.zeros((3, 3, 7)) for a in range(0, 3): for b in range(0, 3): for i in range(0, 7): epsilon_matrix[a][b][i] = epsilon_array[i] while (True): FM_Matrix_with_errors_k = np.zeros((3, 3)) for a in range(0, 3): for b in range(0, 3): random_epsilon = epsilon_matrix[a][b][np.random.randint(0, 7)] FM_Matrix_with_errors_k[a][b] = FM_Matrix_original[a][b] * ( 1 + 0.001 * random_epsilon) FM_with_errors_k = FundamentalMatrixTransform( matrix=FM_Matrix_with_errors_k) inliers_k = check_inliers(matches, FM_with_errors_k) if inliers_k <= FM.inliers: continue else: ##TODO Equality check FM_with_error_inliers = FundamentalMatrixInliers( FM_with_errors_k, inliers_k) FM_with_error.append(FM_with_error_inliers) if len(FM_with_error) == 20: break return FM_with_error
def transform_image(img, rotation=0, translation=(0, 0)): """Take a set of transformations and apply them to the image. Rotations occur around the center of the image, rather than the (0, 0). Parameters ---------- translation : 2-tuple, optional Translation parameters in (vert, horiz) order. rotation : float, optional Rotation in degrees. scale : 2-tuple, optional Scaling parameters in (vert, horiz) order. """ rot_center = (img.shape[1] / 2, img.shape[0] / 2) xy_trans = (translation[1], translation[0]) M0 = _transformation_matrix(tx=-rot_center[0], ty=-rot_center[1]) M1 = _transformation_matrix(r=np.radians(rotation), tx=xy_trans[0], ty=xy_trans[1]) M2 = _transformation_matrix(tx=rot_center[0], ty=rot_center[1]) # python 3.6 # M = M2 @ M1 @ M0 MT = np.dot(M1, M0) M = np.dot(M2, MT) tr = FundamentalMatrixTransform(M) out = warp(img, tr) return out
def initialize_matrix(icls, m, n, values, inliers): FM_Matrix = np.zeros((m, n)) inliers = inliers for i in range(m): for j in range(n): FM_Matrix[i][j] = values[i][j] FM_Matrix = FundamentalMatrixTransform(matrix=FM_Matrix) return icls(FM_Matrix, inliers)
class FundamentalMatrixInliers(object): FM_Matrix = FundamentalMatrixTransform() inliers = 0 # The class "constructor" - It's actually an initializer def __init__(self, FM, inliers): self.FM_Matrix = FM self.inliers = inliers
def one_point_row_crossover(ind1, ind2): cx = np.random.randint(0, 2) # selects a random value from [0,1,2] ind1 = ind1.FM_Matrix.params.copy() ind2 = ind2.FM_Matrix.params.copy() temp_ind1 = ind1.copy() temp_ind2 = ind2.copy() # single for loop takes care of all three cases where row == 0,1,2 (cx values) are selected for crossover for i in range(0, 3): ind1[cx][i] = temp_ind2[cx][i] ind2[cx][i] = temp_ind1[cx][i] ind_new_1 = FundamentalMatrixTransform(ind1) ind_new_2 = FundamentalMatrixTransform(ind2) inliers_1 = inliers(ind_new_1) inliers_2 = inliers(ind_new_2) return toolbox.individual( values=ind1, inliers=inliers_1), toolbox.individual(values=ind2, inliers=inliers_2)
def make_all_permuations(Matrix): epsilon = [-2,-1,0,1,2] mutated_matrices = [] for i in range(0, 3): for j in range(0, 3): for e in epsilon: new_matrix = Matrix.copy() new_matrix[i][j] = Matrix[i][j] + e * 0.01*Matrix[i][j] mutated_matrices.append(FundamentalMatrixTransform(new_matrix)) return mutated_matrices
def transform_image(img, rotation=0, translation=(0, 0), crop=False): """Take a set of transformations and apply them to the image. Rotations occur around the center of the image, rather than the (0, 0). Parameters ---------- translation : 2-tuple, optional Translation parameters in (vert, horiz) order. rotation : float, optional Rotation in degrees. scale : 2-tuple, optional Scaling parameters in (vert, horiz) order. crop : bool, optional If true (default), clip the dimensions of the image to avoid zero values. Returns ------- out : np.ndarray Similar to input array but transformed. Dimensions will be different if ``crop=True``. crops : 4-tuple The dimensions used for cropping in order (v_min, v_max, h_min, h_max) """ rot_center = (img.shape[1] / 2, img.shape[0] / 2) xy_trans = (translation[1], translation[0]) M0 = _transformation_matrix(tx=-rot_center[0], ty=-rot_center[1]) M1 = _transformation_matrix(r=np.radians(rotation), tx=xy_trans[0], ty=xy_trans[1]) M2 = _transformation_matrix(tx=rot_center[0], ty=rot_center[1]) # python 3.6 # M = M2 @ M1 @ M0 MT = np.dot(M1, M0) M = np.dot(M2, MT) tr = FundamentalMatrixTransform(M) out = warp(img, tr, preserve_range=True) # Calculate new boundaries if needed # Adjust for rotation h_min = 0.5 * img.shape[0] * np.tan(np.radians(rotation)) v_min = 0.5 * img.shape[1] * np.tan(np.radians(rotation)) # Adjust for translation v_max = min(img.shape[0], img.shape[0] - v_min - translation[0]) h_max = min(img.shape[1], img.shape[1] - h_min - translation[1]) v_min = max(0, v_min - translation[0]) h_min = max(0, h_min - translation[1]) crops = (int(v_min), int(v_max), int(h_min), int(h_max)) # Apply the cropping if crop: out = out[crops[0]:crops[1], crops[2]:crops[3]] return out, crops
def one_point_column_crossover(ind1, ind2): cx = np.random.randint(0, 2) ind1 = ind1.FM_Matrix.params.copy() ind2 = ind2.FM_Matrix.params.copy() temp_ind1 = ind1.copy() temp_ind2 = ind2.copy() if cx == 1: for i in range(cx + 1, cx + 2): for j in range(0, 3): ind1[j][i] = temp_ind2[j][i] ind2[j][i] = temp_ind1[j][i] elif cx == 0: for i in range(cx + 1): for j in range(0, 3): ind1[j][i] = temp_ind2[j][i] ind2[j][i] = temp_ind1[j][i] ind_new_1 = FundamentalMatrixTransform(ind1) ind_new_2 = FundamentalMatrixTransform(ind2) inliers_1 = inliers(ind_new_1) inliers_2 = inliers(ind_new_2) return toolbox.individual( values=ind1, inliers=inliers_1), toolbox.individual(values=ind2, inliers=inliers_2)
def one_point_diagonal_crossover(ind1, ind2): cx = np.random.randint(0, 1) # 0 for left diagonal and 1 for right diagonal ind1 = ind1.FM_Matrix.params.copy() ind2 = ind2.FM_Matrix.params.copy() temp_ind1 = ind1.copy() temp_ind2 = ind2.copy() matrix_size = 3 if cx == 1: for i in range(0, 3): ind1[i][i] = temp_ind2[i][i] ind2[i][i] = temp_ind1[i][i] elif cx == 0: for i in range(0, 3): ind1[matrix_size - 1 - i][i] = temp_ind2[matrix_size - 1 - i][i] ind2[matrix_size - 1 - i][i] = temp_ind1[matrix_size - 1 - i][i] ind_new_1 = FundamentalMatrixTransform(ind1) ind_new_2 = FundamentalMatrixTransform(ind2) inliers_1 = inliers(ind_new_1) inliers_2 = inliers(ind_new_2) return toolbox.individual( values=ind1, inliers=inliers_1), toolbox.individual(values=ind2, inliers=inliers_2)
def test_fundamental_matrix_forward(array_like_input): if array_like_input: rotation = [[1, 0, 0], [0, 1, 0], [0, 0, 1]] translation = (1, 0, 0) else: rotation = np.eye(3) translation = np.array([1, 0, 0]) essential_matrix_tform = EssentialMatrixTransform( rotation=rotation, translation=translation) if array_like_input: params = [list(p) for p in essential_matrix_tform.params] else: params = essential_matrix_tform.params tform = FundamentalMatrixTransform(matrix=params) src = np.array([[0, 0], [0, 1], [1, 1]]) assert_almost_equal(tform(src), [[0, -1, 0], [0, -1, 1], [0, -1, 1]])
def test_invalid_input(): with testing.raises(ValueError): ProjectiveTransform(np.zeros((2, 3))) with testing.raises(ValueError): AffineTransform(np.zeros((2, 3))) with testing.raises(ValueError): SimilarityTransform(np.zeros((2, 3))) with testing.raises(ValueError): EuclideanTransform(np.zeros((2, 3))) with testing.raises(ValueError): AffineTransform(matrix=np.zeros((2, 3)), scale=1) with testing.raises(ValueError): SimilarityTransform(matrix=np.zeros((2, 3)), scale=1) with testing.raises(ValueError): EuclideanTransform( matrix=np.zeros((2, 3)), translation=(0, 0)) with testing.raises(ValueError): PolynomialTransform(np.zeros((3, 3))) with testing.raises(ValueError): FundamentalMatrixTransform(matrix=np.zeros((3, 2))) with testing.raises(ValueError): EssentialMatrixTransform(matrix=np.zeros((3, 2))) with testing.raises(ValueError): EssentialMatrixTransform(rotation=np.zeros((3, 2))) with testing.raises(ValueError): EssentialMatrixTransform( rotation=np.zeros((3, 3))) with testing.raises(ValueError): EssentialMatrixTransform( rotation=np.eye(3)) with testing.raises(ValueError): EssentialMatrixTransform(rotation=np.eye(3), translation=np.zeros((2,))) with testing.raises(ValueError): EssentialMatrixTransform(rotation=np.eye(3), translation=np.zeros((2,))) with testing.raises(ValueError): EssentialMatrixTransform( rotation=np.eye(3), translation=np.zeros((3,)))
def make_initial_population(n_fundamental_matrices, matches): model, inliers, FundaMatrix_and_inliers_list = ransac( matches, FundamentalMatrixTransform, min_samples=8, residual_threshold=config.residual_threshold, max_trials=n_fundamental_matrices) FM_inlier_list = [] sorted_FM = sorted(FundaMatrix_and_inliers_list, key=lambda x: int(x[1]), reverse=True) top_10_FM = sorted_FM[:10] for item in top_10_FM: FM = FundamentalMatrixTransform(matrix=item[0]) FM_inlier = FundamentalMatrixInliers(FM, item[1]) FM_inlier_list.append(FM_inlier) epsiloned_FM = [] for FM in FM_inlier_list: epsiloned_FM = epsiloned_FM + modify_FM(FM, 3, matches) return epsiloned_FM
def test_fundamental_3d_not_implemented(): with pytest.raises(NotImplementedError): _ = FundamentalMatrixTransform(dimensionality=3) with pytest.raises(NotImplementedError): _ = FundamentalMatrixTransform(np.eye(4))
def estimate_fundamental(keypoints1, keypoints2): tform = FundamentalMatrixTransform() tform.estimate(keypoints1, keypoints2) return tform.params