2022-11-13 15:13:43 +01:00
|
|
|
|
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()
|
|
|
|
|
#two_b()
|
|
|
|
|
two_c()
|
|
|
|
|
|
|
|
|
|
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 two_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))).
|
|
|
|
|
"""
|
2022-11-13 18:36:38 +01:00
|
|
|
|
sigmas = [0.5, 1, 2]
|
|
|
|
|
for sigma in sigmas:
|
|
|
|
|
kernel = uz_image.gaussdx(sigma)
|
|
|
|
|
print(kernel)
|
2022-11-13 15:13:43 +01:00
|
|
|
|
|
|
|
|
|
def two_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)])
|
|
|
|
|
|
2022-11-13 18:36:38 +01:00
|
|
|
|
# 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)
|
|
|
|
|
|
|
|
|
|
|
2022-11-13 15:13:43 +01:00
|
|
|
|
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)
|
2022-11-13 18:36:38 +01:00
|
|
|
|
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')
|
2022-11-13 15:13:43 +01:00
|
|
|
|
|
|
|
|
|
plt.show()
|
|
|
|
|
|
|
|
|
|
# ######## #
|
|
|
|
|
# SOLUTION #
|
|
|
|
|
# ######## #
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
|
ex1()
|
|
|
|
|
#ex2()
|
|
|
|
|
#ex3()
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
main()
|