diff --git a/assignment4/] b/assignment4/] new file mode 100644 index 0000000..7cb232a --- /dev/null +++ b/assignment4/] @@ -0,0 +1,111 @@ +import numpy as np +import numpy.typing as npt +from matplotlib import pyplot as plt +import cv2 +import uz_framework.image as uz_image +import uz_framework.text as uz_text +import os + +############################################## +# EXCERCISE 1: Exercise 1: Image derivatives # +############################################## + +def ex1(): + one_a() + one_b() + +def one_a() -> None: + img = uz_image.imread_gray("data/graf/graf_a.jpg", uz_image.ImageType.float64) + sigmas = [3, 6, 9, 12] + # Plot the points + fig, axs = plt.subplots(2, len(sigmas)) + fig.suptitle("Hessian corner detection") + + for i, sigma in enumerate(sigmas): + determinant, hessian_points = uz_image.hessian_points(img, sigma, 0.004) + # Plot determinant + axs[0, i].imshow(determinant) + axs[0, i].set_title(f"Sigma: {sigma}") + # Plot grayscale image + axs[1, i].imshow(img, cmap="gray") + # Plot scatter hessian points (x, y) + axs[1, i].scatter(hessian_points[:, 1], hessian_points[:, 0], s=20, c="r", marker="x") + + plt.show() + +def one_b() -> None: + img = uz_image.imread_gray("data/graf/graf_a.jpg", uz_image.ImageType.float64) + sigmas = [3, 6, 9] + # Plot the points + fig, axs = plt.subplots(2, len(sigmas)) + fig.suptitle("Harris corner detection") + + for i, sigma in enumerate(sigmas): + determinant, harris_points = uz_image.harris_detector(img, sigma, treshold=1e-6) + # Plot determinant + axs[0, i].imshow(determinant) + axs[0, i].set_title(f"Sigma: {sigma}") + # Plot grayscale image + axs[1, i].imshow(img, cmap="gray") + # Plot scatter hessian points + axs[1, i].scatter(harris_points[:, 1], harris_points[:, 0], s=20, c="r", marker="x") + + plt.show() + +def ex2(): + two_a() + +def two_a() -> None: + """ + Hello + """ + graph_a_small = uz_image.imread_gray("data/graf/graf_a_small.jpg", uz_image.ImageType.float64) + graph_b_small = uz_image.imread_gray("data/graf/graf_b_small.jpg", uz_image.ImageType.float64) + + # Get the keypoints + _, graph_a_keypoints = uz_image.harris_detector(graph_a_small, 3, treshold=1e-6) + _, graph_b_keypoints = uz_image.harris_detector(graph_b_small, 3, treshold=1e-6) + + # Get the descriptors + graph_a_descriptors = uz_image.simple_descriptors(graph_a_small, graph_a_keypoints[:,0], graph_a_keypoints[:,1]) + graph_b_descriptors = uz_image.simple_descriptors(graph_b_small, graph_b_keypoints[:,0], graph_b_keypoints[:,1]) + + # Find the correspondences + matches_a = uz_image.find_correspondences(graph_a_descriptors, graph_b_descriptors) + matches_b = uz_image.find_correspondences(graph_b_descriptors, graph_a_descriptors) + + matches_a_coordinates = [] + matche_b_coordinates = [] + for i, match in enumerate(matches_a): + if i % 2 == 0: # plot every second one + if np.flip(match) in matches_b: # Check if the match is reciprocal + print(match) + print(np.flip(match)) + print(matches_b) + print(np.argwhere(matches_b == np.flip(match))) + matches_a_coordinates.append(np.flip(graph_a_keypoints[match[0]])) + matche_b_coordinates.append(np.flip(graph_b_keypoints[match[1]])) + else: + print("Not reciprocal") + + # Plot the matches + uz_image.display_matches(graph_a_small, matches_a_coordinates, graph_b_small, matche_b_coordinates) + +def two_b() -> None: + """ + jjjjj + """ + + + + +# ######## # +# SOLUTION # +# ######## # + +def main(): + #ex1() + ex2() + +if __name__ == '__main__': + main() diff --git a/assignment4/datam/img1.jpg b/assignment4/datam/img1.jpg new file mode 100644 index 0000000..893728c Binary files /dev/null and b/assignment4/datam/img1.jpg differ diff --git a/assignment4/datam/img2.jpg b/assignment4/datam/img2.jpg new file mode 100644 index 0000000..027db34 Binary files /dev/null and b/assignment4/datam/img2.jpg differ diff --git a/assignment4/solution.py b/assignment4/solution.py index 90dc64a..002dc0c 100644 --- a/assignment4/solution.py +++ b/assignment4/solution.py @@ -53,7 +53,8 @@ def one_b() -> None: plt.show() def ex2(): - two_a() + #two_a() + two_b() def two_a() -> None: """ @@ -79,6 +80,7 @@ def two_a() -> None: for i, match in enumerate(matches_a): if i % 2 == 0: # plot every second one if np.flip(match) in matches_b: # Check if the match is reciprocal + print(np.argwhere(matches_b == np.flip(match))) matches_a_coordinates.append(np.flip(graph_a_keypoints[match[0]])) matche_b_coordinates.append(np.flip(graph_b_keypoints[match[1]])) else: @@ -91,8 +93,12 @@ def two_b() -> None: """ jjjjj """ + graph_a_small = uz_image.imread_gray("datam/img1.jpg", uz_image.ImageType.float64) + graph_b_small = uz_image.imread_gray("datam/img2.jpg", uz_image.ImageType.float64) + a, b = uz_image.find_matches(graph_a_small, graph_b_small) + uz_image.display_matches(graph_a_small, a, graph_b_small, b) # ######## # diff --git a/assignment4/uz_framework/image.py b/assignment4/uz_framework/image.py index 0442942..6517beb 100644 --- a/assignment4/uz_framework/image.py +++ b/assignment4/uz_framework/image.py @@ -1,4 +1,3 @@ - import numpy as np import cv2 as cv2 from matplotlib import pyplot as plt @@ -33,7 +32,6 @@ def imread(path: str, type: ImageType) -> Union[npt.NDArray[np.float64], npt.ND raise Exception(f"Unrecognized image format! {type}") - def imread_gray(path: str, type: ImageType) -> Union[npt.NDArray[np.float64], npt.NDArray[np.uint8]]: """ Reads an image in gray. Image type is transformed from uint8 to float, and @@ -289,7 +287,6 @@ def get_image_bins_gradient_magnitude_and_angles(image: Union[npt.NDArray[np.flo histogram = np.array(histogram) return histogram / np.sum(histogram) - def compare_two_histograms(h1: npt.NDArray[np.float64], h2: npt.NDArray[np.float64], method: DistanceMeasure) -> float: """ @@ -1034,8 +1031,6 @@ def find_correspondences(img_a_descriptors: npt.NDArray[np.float64], return np.array(correspondances) - - def display_matches(I1, pts1, I2, pts2): """ Displays matches between images. @@ -1061,3 +1056,71 @@ def display_matches(I1, pts1, I2, pts2): plt.show() +def find_matches(image_a: npt.NDArray[np.float64], + image_b: npt.NDArray[np.float64]): + """ + Finds matches between two images. + + image_a, image_b: Image in grayscale. + """ + + # Get the keypoints + _, image_a_keypoints = harris_detector(image_a, 6, treshold=1e-6) + _, image_b_keypoints = harris_detector(image_b, 6, treshold=1e-6) + + # Get the descriptors + image_a_descriptors = simple_descriptors(image_a, image_a_keypoints[:, 0], image_a_keypoints[:, 1]) + image_b_descriptors = simple_descriptors(image_b, image_b_keypoints[:, 0], image_b_keypoints[:, 1]) + + # Find correspondences + correspondences_a = find_correspondences(image_a_descriptors, image_b_descriptors) + correspondences_b = find_correspondences(image_b_descriptors, image_a_descriptors) + + def select_best_correspondences(c_a, d_a, c_b, d_b): + #Find correspondances that map into same index a->b (b) + unique, counts = np.unique(c_a[:, 1], return_counts=True) + # Find all b's + duplicates = unique[counts > 1] + for duplicate in duplicates: + # Find the indices of the duplicates find all a's + indices = np.where(c_a[:, 1] == duplicate)[0] + # Extract those from the descriptors + candidates = d_a[indices] + # Extract comparing distance from b's descriptors + comparing_distance = d_b[duplicate] + # Find the closest one using hellingers distance + dists = np.sqrt(0.5 * np.sum(np.square(np.sqrt(comparing_distance) - np.sqrt(candidates)), axis=1)) + # Select the best one + min_dist_idx = np.argmin(dists) + # and map that candidate back to the indces index + candidate = indices[min_dist_idx] + candidate = c_a[candidate] + #if np.flip(candidate) in c_b: + # # Remove it from the indices so it does not get removed in the next step + # indices = np.delete(indices, min_dist_idx) + #else: + # print(f'[i] select_best_correspondences -> Not reciprocal {np.flip(candidate)}') + #Remove remainig from the correspondences + c_a = np.delete(c_a, indices, axis=0) + + return c_a + + correspondences_a = select_best_correspondences(correspondences_a, image_a_descriptors, correspondences_b, image_b_descriptors) + correspondences_b = select_best_correspondences(correspondences_b, image_b_descriptors, correspondences_a, image_a_descriptors) + + def check_repciporacvbillity(c_a, c_b): + for _, match in enumerate(c_a): + if np.flip(match) not in c_b: + print(f'[i] check_repciporacvbillity -> Not reciprocal {match}') + index = np.where((c_a == match).all(axis=1))[0][0] + c_a = np.delete(c_a, index, axis=0) + return c_a + + correspondences_a = check_repciporacvbillity(correspondences_a, correspondences_b) + correspondences_b = check_repciporacvbillity(correspondences_b, correspondences_a) + + # Map correspondences to keypoints + image_a_keypoints = np.flip(image_a_keypoints[correspondences_a[:, 0]]) + image_b_keypoints = np.flip(image_b_keypoints[correspondences_b[:, 0]]) + + return image_a_keypoints, image_b_keypoints