diff --git a/assignment2/.png b/assignment2/.png new file mode 100644 index 0000000..799e680 Binary files /dev/null and b/assignment2/.png differ diff --git a/assignment2/solution.py b/assignment2/solution.py index f77c9d6..bb341b2 100644 --- a/assignment2/solution.py +++ b/assignment2/solution.py @@ -1,7 +1,6 @@ import numpy as np import numpy.typing as npt from matplotlib import pyplot as plt -import random import cv2 import uz_framework.image as uz_image import uz_framework.text as uz_text @@ -278,15 +277,89 @@ def two_e(): ################################ # EXCERCISE 3: Image Filtering # ################################ +def ex3(): + #three_a() + three_b() +def three_a(): + """ + Write a function gaussfilter that generates a Gaussian filter and applies it to a + 2-D image. You can use the function cv2.filter2D() to perform the convolution + using the desired kernel. Generate a 1-D Gaussian kernel and first use it to filter + the image along the first dimension, then convolve the result using the same kernel, + but transposed. + Hint: Numpy arrays have an attribute named T, which is used to access the transpose + of the array, e.g. k_transposed = k.T. + Test the function by loading the image lena.png and converting it to grayscale. + Then, corrupt the image with Gaussian noise (every pixel value is offset by a random number + sampled from the Gaussian distribution) and separately with saltand-pepper noise. + You can use the functions gauss_noise and sp_noise that are + included with the instructions (a2_utils.py). Use the function gaussfilter to try + and remove noise from both images + """ + lena = uz_image.imread('./data/images/lena.png', uz_image.ImageType.float64) + lena_grayscale = uz_image.transform_coloured_image_to_grayscale(lena.astype(np.float64)) + lena_gausssian_noise = uz_image.gauss_noise(lena_grayscale) + lena_salt_and_pepper = uz_image.sp_noise(lena_grayscale) + kernel = uz_image.get_gaussian_kernel(1) + + # Denoised + denosised_lena = cv2.filter2D(lena_gausssian_noise, cv2.CV_64F, kernel) + denosised_lena = cv2.filter2D(denosised_lena, cv2.CV_64F, kernel.T) + # Desalted + desalted_lena = cv2.filter2D(lena_salt_and_pepper, cv2.CV_64F, kernel) + desalted_lena = cv2.filter2D(desalted_lena, cv2.CV_64F, kernel.T) + + fig, axs = plt.subplots(2, 3) + axs[0, 0].imshow(lena_grayscale, cmap='gray') + axs[0, 0].set(title='Orginal image') + axs[0, 1].imshow(lena_gausssian_noise, cmap='gray') + axs[0, 1].set(title='Gaussian noise') + axs[1, 1].imshow(denosised_lena, cmap='gray') + axs[1, 1].set(title='Denoised lena') + axs[0, 2].imshow(lena_salt_and_pepper, cmap='gray') + axs[0, 2].set(title='Salt and Pepper') + axs[1, 2].imshow(desalted_lena, cmap='gray') + axs[1, 2].set(title='Desalted lena') + + plt.show() + +def three_b(): + """ + Convolution can also be used for image sharpening. Look at its definition in the + lecture slides and implement it. Test it on the image from file museum.jpg. + """ + museum_grayscale = cv2.imread('./data/images/museum.jpg', 0) + + #https://blog.demofox.org/2022/02/26/image-sharpening-convolution-kernels/ + # Pa tui na slajdih lepo pise + + kernel = np.array([[-1, -1, -1], + [-1, 17, -1], + [-1, -1,-1]]) + kernel = kernel * 1./9. + + museo = cv2.filter2D(museum_grayscale, cv2.CV_64F, kernel) + museo = cv2.filter2D(museo, cv2.CV_64F, kernel.T) + + fig, axs = plt.subplots(1, 2) + axs[0].imshow(museum_grayscale, cmap='gray') + axs[0].set(title='Original') + axs[1].imshow(museo, cmap='gray') + axs[1].set(title='Sharpened') + plt.savefig('.') + plt.show() + + # ######## # # SOLUTION # # ######## # def main(): #ex1() - ex2() + #ex2() + ex3() if __name__ == '__main__': main() diff --git a/assignment2/uz_framework/image.py b/assignment2/uz_framework/image.py index ec2984b..6282cd0 100644 --- a/assignment2/uz_framework/image.py +++ b/assignment2/uz_framework/image.py @@ -290,9 +290,16 @@ def get_gaussian_kernel(sigma: float): return result / np.sum(result) +def gaussfilter2D(imge: Union[npt.NDArray[np.float64], npt.NDArray[np.uint8]], sigma: float): + kernel = get_gaussian_kernel(sigma) + kernel = cv2.filter2D(kernel, cv2.CV_64F, kernel) + + + def gauss_noise(I, magnitude=.1): # input: image, magnitude of noise # output: modified image + I = I.copy() return I + np.random.normal(size=I.shape) * magnitude