163 lines
6.2 KiB
Python
163 lines
6.2 KiB
Python
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
|
||
|
||
#################################################################
|
||
# EXCERCISE 1: Exercise 1: Global approach to image description #
|
||
#################################################################
|
||
|
||
def ex1():
|
||
#one_a()
|
||
#one_b()
|
||
#one_c()
|
||
one_d()
|
||
|
||
def one_a() -> None:
|
||
"""
|
||
Follow the equations above and derive the equations used to compute first and
|
||
second derivatives with respect to y: Iy(x, y), Iyy(x, y), as well as the mixed derivative
|
||
Ixy(x, y)
|
||
"""
|
||
|
||
def one_b() -> None:
|
||
"""
|
||
Implement a function that computes the derivative of a 1-D Gaussian kernel
|
||
Implement the function gaussdx(sigma) that works the same as function gauss
|
||
from the previous assignment. Don’t forget to normalize the kernel. Be careful as
|
||
the derivative is an odd function, so a simple sum will not do. Instead normalize the
|
||
kernel by dividing the values such that the sum of absolute values is 1. Effectively,
|
||
you have to divide each value by sum(abs(gx(x))).
|
||
"""
|
||
sigmas = [0.5, 1, 2]
|
||
for sigma in sigmas:
|
||
kernel = uz_image.gaussdx(sigma)
|
||
print(kernel)
|
||
|
||
def one_c() -> None:
|
||
"""
|
||
The properties of the filter can be analyzed by using an impulse response function.
|
||
This is performed as a convolution of the filter with a Dirac delta function. The
|
||
discrete version of the Dirac function is constructed as a finite image that has all
|
||
elements set to 0 except the central element, which is set to a high value (e.g. 1).
|
||
Generate a 1-D Gaussian kernel G and a Gaussian derivative kernel D.
|
||
What happens if you apply the following operations to the impulse image?
|
||
(a) First convolution with G and then convolution with GT
|
||
(b) First convolution with G and then convolution with DT
|
||
(c) First convolution with D and then convolution with GT
|
||
(d) First convolution with GT and then convolution with D.
|
||
(e) First convolution with DT and then convolution with G.
|
||
Is the order of operations important? Display the images of the impulse responses
|
||
for different combinations of operations.
|
||
"""
|
||
impulse = uz_image.generate_dirac_impulse(50)
|
||
gauss = np.array([uz_image.get_gaussian_kernel(3)])
|
||
gaussdx = np.array([uz_image.gaussdx(3)])
|
||
|
||
# Becouse CV2 applies the correlation instead of convolution, we need to flip the kernels
|
||
gauss = np.flip(gauss, axis=1)
|
||
gaussdx = np.flip(gaussdx, axis=1)
|
||
|
||
|
||
fig, axs = plt.subplots(2, 3)
|
||
|
||
# Plot impulse only
|
||
axs[0, 0].imshow(impulse, cmap='gray')
|
||
axs[0, 0].set_title('Impulse')
|
||
|
||
# Plot impulse after convolution with G and GT
|
||
g_gt_impulse = impulse.copy()
|
||
g_gt_impulse = cv2.filter2D(g_gt_impulse, cv2.CV_64F, gauss)
|
||
g_gt_impulse = cv2.filter2D(g_gt_impulse, cv2.CV_64F, gauss.T)
|
||
axs[1, 0].imshow(g_gt_impulse, cmap='gray')
|
||
axs[1, 0].set_title('impulse * G * GT')
|
||
|
||
# Plot impulse after convolution with G and DT
|
||
g_dt_impulse = impulse.copy()
|
||
g_dt_impulse = cv2.filter2D(g_dt_impulse, cv2.CV_64F, gauss)
|
||
g_dt_impulse = cv2.filter2D(g_dt_impulse, cv2.CV_64F, gaussdx.T)
|
||
axs[0, 1].imshow(g_dt_impulse, cmap='gray')
|
||
axs[0, 1].set_title('impulse * G * DT')
|
||
|
||
# Plot impulse after convolution with D and GT
|
||
d_gt_impulse = impulse.copy()
|
||
d_gt_impulse = cv2.filter2D(d_gt_impulse, cv2.CV_64F, gaussdx)
|
||
d_gt_impulse = cv2.filter2D(d_gt_impulse, cv2.CV_64F, gauss.T)
|
||
axs[0, 2].imshow(d_gt_impulse, cmap='gray')
|
||
axs[0, 2].set_title('impulse * D * GT')
|
||
|
||
# Plot impulse after convolution with GT and D
|
||
gt_d_impulse = impulse.copy()
|
||
gt_d_impulse = cv2.filter2D(gt_d_impulse, cv2.CV_64F, gauss.T)
|
||
gt_d_impulse = cv2.filter2D(gt_d_impulse, cv2.CV_64F, gaussdx)
|
||
axs[1, 1].imshow(gt_d_impulse, cmap='gray')
|
||
axs[1, 1].set_title('impulse * GT * D')
|
||
|
||
# Plot impulse after convolution with DT and G
|
||
dt_g_impulse = impulse.copy()
|
||
dt_g_impulse = cv2.filter2D(dt_g_impulse, cv2.CV_64F, gaussdx.T)
|
||
dt_g_impulse = cv2.filter2D(dt_g_impulse, cv2.CV_64F, gauss)
|
||
axs[1, 2].imshow(dt_g_impulse, cmap='gray')
|
||
axs[1, 2].set_title('impulse * DT * G')
|
||
|
||
plt.show()
|
||
|
||
|
||
def one_d() -> None:
|
||
"""
|
||
Implement a function that uses functions gauss and gaussdx to compute both
|
||
partial derivatives of a given image with respect to x and with respect to y.
|
||
Similarly, implement a function that returns partial second order derivatives of a
|
||
given image.
|
||
Additionally, implement the function gradient_magnitude that accepts a grayscale
|
||
image I and returns both derivative magnitudes and derivative angles. Magnitude
|
||
is calculated as m(x, y) = sqrt(Ix(x,y)^2 + Iy(x, y)^2) and angles are calculated as
|
||
φ(x, y) = arctan(Iy(x, y)/Ix(x, y))
|
||
Hint: Use function np.arctan2 to avoid division by zero for calculating the arctangent function.
|
||
Use all the implemented functions on the same image and display the results in the
|
||
same window.
|
||
"""
|
||
|
||
museum = uz_image.imread_gray('./images/museum.jpg', uz_image.ImageType.float64)
|
||
|
||
museum_x, museum_y = uz_image.derive_image_first_order(museum, 1)
|
||
(museum_xx, museum_xy) , (_, museum_yy) = uz_image.derive_image_second_order(museum, 1)
|
||
derivative_magnitude, derivative_angle = uz_image.gradient_magnitude(museum, 1)
|
||
|
||
fig, axs = plt.subplots(2, 4)
|
||
fig.suptitle('Museum')
|
||
|
||
axs[0,0].imshow(museum, cmap='gray')
|
||
axs[0,0].set_title('Original')
|
||
axs[0, 1].imshow(museum_x, cmap='gray')
|
||
axs[0, 1].set_title('I_x')
|
||
axs[0, 2].imshow(museum_y, cmap='gray')
|
||
axs[0, 2].set_title('I_y')
|
||
axs[1, 0].imshow(museum_xx, cmap='gray')
|
||
axs[1, 0].set_title('I_xx')
|
||
axs[1, 1].imshow(museum_xy, cmap='gray')
|
||
axs[1, 1].set_title('I_xy')
|
||
axs[1, 2].imshow(museum_yy, cmap='gray')
|
||
axs[1, 2].set_title('I_yy')
|
||
axs[0, 3].imshow(derivative_magnitude, cmap='gray')
|
||
axs[0, 3].set_title('I_mag')
|
||
axs[1, 3].imshow(derivative_angle, cmap='gray')
|
||
axs[1, 3].set_title('I_dir')
|
||
|
||
plt.show()
|
||
|
||
|
||
# ######## #
|
||
# SOLUTION #
|
||
# ######## #
|
||
|
||
def main():
|
||
ex1()
|
||
#ex2()
|
||
#ex3()
|
||
|
||
if __name__ == '__main__':
|
||
main()
|