From a2b30c7ed1798d57ae63a894fc594857f681a262 Mon Sep 17 00:00:00 2001 From: Gasper Spagnolo Date: Tue, 15 Nov 2022 23:31:05 +0100 Subject: [PATCH] Pusho za medolinjota --- assignment3/solution.py | 93 ++++++++++++++++++++++++++++++- assignment3/uz_framework/image.py | 86 +++++++++++++++++++++++++++- 2 files changed, 176 insertions(+), 3 deletions(-) diff --git a/assignment3/solution.py b/assignment3/solution.py index 13cc92c..b93fe72 100644 --- a/assignment3/solution.py +++ b/assignment3/solution.py @@ -227,8 +227,9 @@ def two_c(): ############################################ def ex3(): #three_a() - three_b() + #three_b() #three_c() + three_d() def three_a(): """ @@ -300,6 +301,96 @@ def three_b(): plt.show() +def three_c(): + """ + The sinusoids don’t usually intersect in only one point, resulting in more than one detected line. + Implement a function named nonmaxima_suppression_box that checks + the neighborhood of each pixel and set it to 0 if it is not the maximum value in the + neighborhood (only consider 8-neighborhood). If more neighbouring pixels have the + maximum value, keep only one. + """ + SIGMA = 1 + THETA = 0.02 + T_LOW = 0.04 + T_HIGH = 0.16 + + synthetic_image = np.zeros((100, 100)) + synthetic_image[10, 10] = 1 + synthetic_image[10, 20] = 1 + + oneline_image = uz_image.imread_gray('./images/oneline.png', uz_image.ImageType.float64) + rectangle_image = uz_image.imread_gray('./images/rectangle.png', uz_image.ImageType.float64) + + oneline_image_edges = uz_image.find_edges_canny(oneline_image, SIGMA, THETA, T_LOW, T_HIGH) + rectangle_image_edges = uz_image.find_edges_canny(rectangle_image, SIGMA, THETA, T_LOW, T_HIGH) + + synthetic_image_hough = uz_image.hough_find_lines(synthetic_image, 200, 200, 0.2) + oneline_image_hough = uz_image.hough_find_lines(oneline_image_edges, 200, 200, 0.2) + rectangle_image_hough = uz_image.hough_find_lines(rectangle_image_edges, 200, 200, 0.2) + + + fig, axs = plt.subplots(4, 3) + + axs[0, 0].imshow(synthetic_image, cmap='gray') + axs[0, 0].set_title('Synthetic image') + axs[2, 0].imshow(synthetic_image_hough) + axs[0, 1].imshow(oneline_image, cmap='gray') + axs[0, 1].set_title('Oneline image') + axs[1, 1].imshow(oneline_image_edges, cmap='gray') + axs[0, 2].imshow(rectangle_image, cmap='gray') + axs[0, 2].set_title('Rectangle image') + axs[1, 2].imshow(rectangle_image_edges, cmap='gray') + axs[1, 0].set_visible(False) + axs[2, 1].imshow(oneline_image_hough) + axs[2, 2].imshow(rectangle_image_hough) + axs[3, 0].imshow(uz_image.nonmaxima_suppression_box(synthetic_image_hough)) + axs[3, 1].imshow(uz_image.nonmaxima_suppression_box(oneline_image_hough)) + axs[3, 2].imshow(uz_image.nonmaxima_suppression_box(rectangle_image_hough)) + + plt.show() + + +def three_d(): + """ + Search the parameter space and extract all the parameter pairs (ρ, ϑ) whose corresponding accumulator cell value isgreater than a specified threshold threshold. + Draw the lines that correspond to the parameter pairs using the draw_line function + that you can find in the supplementary material. + """ + + SIGMA = 1 + THETA = 0.02 + T_LOW = 0.04 + T_HIGH = 0.16 + + synthetic_image = np.zeros((100, 100)) + synthetic_image[10, 10] = 1 + synthetic_image[10, 20] = 1 + + oneline_image = uz_image.imread_gray('./images/oneline.png', uz_image.ImageType.float64) + rectangle_image = uz_image.imread_gray('./images/rectangle.png', uz_image.ImageType.float64) + + oneline_image_edges = uz_image.find_edges_canny(oneline_image, SIGMA, THETA, T_LOW, T_HIGH) + rectangle_image_edges = uz_image.find_edges_canny(rectangle_image, SIGMA, THETA, T_LOW, T_HIGH) + + synthetic_image_hough = uz_image.hough_find_lines(synthetic_image, 360, 360, 0.2) + oneline_image_hough = uz_image.hough_find_lines(oneline_image_edges, 360, 360, 0.2) + rectangle_image_hough = uz_image.hough_find_lines(rectangle_image_edges, 360, 360 , 0.2) + + synthetic_image_hough_nonmax = uz_image.nonmaxima_suppression_box(synthetic_image_hough) + oneline_image_hough_nonmax = uz_image.nonmaxima_suppression_box(oneline_image_hough) + rectangle_image_hough_nonmax = uz_image.nonmaxima_suppression_box(rectangle_image_hough) + + fig, axs = plt.subplots(1, 3) + + axs[0].imshow(oneline_image) + neighbour_pairs = uz_image.retrieve_hough_pairs(oneline_image_hough_nonmax, np.max(oneline_image_hough_nonmax)*0.3, 360, 360) + for neighbour in neighbour_pairs: + xs, ys = uz_image.get_line_to_plot(neighbour[0], neighbour[1], oneline_image_hough_nonmax.shape[0], oneline_image_hough_nonmax.shape[1]) + axs[0].plot(xs, ys, 'r', linewidth=0.7) + + plt.show() + + # ######## # # SOLUTION # # ######## # diff --git a/assignment3/uz_framework/image.py b/assignment3/uz_framework/image.py index 10f2179..75cf006 100644 --- a/assignment3/uz_framework/image.py +++ b/assignment3/uz_framework/image.py @@ -589,9 +589,9 @@ def find_edges_nms(image: Union[npt.NDArray[np.float64], npt.NDArray[np.uint8]], if i == 0 or i == 7: return (0, 1), (0, -1) elif i == 1 or i == 2: - return (-1, 1), (1, -1) - elif i == 3 or i == 4: return (-1, 0), (1, 0) + elif i == 3 or i == 4: + return (-1, 1), (1, -1) elif i == 5 or i == 6: return (-1, -1), (1, 1) raise ValueError(f"Angle {angle} is not in range") @@ -692,3 +692,85 @@ def hough_find_lines(image: Union[npt.NDArray[np.float64], npt.NDArray[np.uint8] return accumulator +def nonmaxima_suppression_box(image: npt.NDArray[np.uint64]) -> npt.NDArray[np.uint64]: + """ + Accepts: image with sinusoids in hough space + Returns: image with sinusoids + """ + image = image.copy() + + def get_neighbours() -> list[tuple[int, int]]: + neighbours = [] + for i in range(-1, 2): + for j in range(-1, 2): + if i != 0 or j != 0: + neighbours.append((i, j)) + return neighbours + + for y in range(1, image.shape[0]-1): + for x in range(1, image.shape[1]-1): + for neighbour in get_neighbours(): + if image[y, x] < image[y+neighbour[0], x+neighbour[1]]: + image[y, x] = 0 + break + return image + + +def retrieve_hough_pairs(image: npt.NDArray[np.uint64], treshold: int, n_bins_theta: int, n_bins_rho) -> list[tuple[int, int]]: + """ + Accepts: image with sinusoids in hough space, treshold + Returns: list of pairs of sinusoids + """ + theta_values = np.linspace(-np.pi/2, np.pi/2, n_bins_theta) + rho_values = np.linspace(-np.sqrt(image.shape[0]**2 + image.shape[1]**2), np.sqrt(image.shape[0]**2 + image.shape[1]**2), n_bins_rho) + + image = image.copy() + image[image < treshold] = 0 + + y_s, x_s = np.nonzero(image) + pairs = [] + for i in range(len(x_s)): + x = x_s[i] # theta values + y = y_s[i] # rho values + + theta = theta_values[x] + rho = rho_values[y] + + pairs.append((rho, theta)) + return pairs + + +def get_line_to_plot(rho, theta, h, w): + """ + Accepts: rho, theta, image height h, image width w + Returns: line to plot + usage example: plt.plot(uz_image.get_line_to_plot(rho, theta, h, w), 'r', linewidth=.7) + """ + + c = np.cos(theta) + s = np.sin(theta) + + xs = [] + ys = [] + if s != 0: + y = int(rho / s) + if 0 <= y < h: + xs.append(0) + ys.append(y) + + y = int((rho - w * c) / s) + if 0 <= y < h: + xs.append(w - 1) + ys.append(y) + if c != 0: + x = int(rho / c) + if 0 <= x < w: + xs.append(x) + ys.append(0) + + x = int((rho - h * s) / c) + if 0 <= x < w: + xs.append(x) + ys.append(h - 1) + + return xs[:2], ys[:2]