File size: 4,333 Bytes
b78dbf0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import numpy as np


def create_Gaussian_kernel(cutoff_frequency):
    """
        Returns a 2D Gaussian kernel using the specified filter size standard
        deviation and cutoff frequency.

        The kernel should have:
        - shape (k, k) where k = cutoff_frequency * 4 + 1
        - mean = floor(k / 2)
        - standard deviation = cutoff_frequency
        - values that sum to 1

        Args:
        - cutoff_frequency: an int controlling how much low frequency to leave in
          the image.
        Returns:
        - kernel: numpy nd-array of shape (k, k)

        HINT:
        - The 2D Gaussian kernel here can be calculated as the outer product of two
          vectors with values populated from evaluating the 1D Gaussian PDF at each
          corrdinate.
    """
    k = cutoff_frequency * 4 + 1
    mean = np.floor(k / 2)
    std = cutoff_frequency
    gauss_1d = np.zeros((k, 1))

    total = 0
    index = 0
    for x in range(-int(mean), int(mean) + 1):
        x1 = 1 / np.sqrt(2 * np.pi * std ** 2)
        x2 = np.exp(-(x ** 2) / (2 * std ** 2))
        g = x1 * x2
        gauss_1d[index] = g
        index += 1
        total += g
    kernel = np.outer(gauss_1d, gauss_1d) / total ** 2
    return kernel


def my_imfilter(image, filter):
    """
    Apply a filter to an image. Return the filtered image.

    Args
    - image: numpy nd-array of shape (m, n, c)
    - filter: numpy nd-array of shape (k, j)
    Returns
    - filtered_image: numpy nd-array of shape (m, n, c)

    HINTS:
    - You may not use any libraries that do the work for you. Using numpy to work
    with matrices is fine and encouraged. Using OpenCV or similar to do the
    filtering for you is not allowed.
    - I encourage you to try implementing this naively first, just be aware that
    it may take an absurdly long time to run. You will need to get a function
    that takes a reasonable amount of time to run so that the TAs can verify
    your code works.
    """
    m = image.shape[0]
    n = image.shape[1]
    c = image.shape[2]

    padding_height = filter.shape[0] // 2
    padding_width = filter.shape[1] // 2

    # padding manually
    padded_image = np.zeros((m + padding_height * 2, n + padding_width * 2, c))
    padded_image[padding_height:padding_height + m, padding_width:padding_width + n, :] = image

    # convolution
    filtered_image = np.zeros((m, n, c))

    for a in range(0, c):
        for i in range(0, m):
            for j in range(0, n):
                x = np.multiply(padded_image[i: i + filter.shape[0], j:j + filter.shape[1], a], filter)
                filtered_image[i, j, a] = x.sum()

    return filtered_image


def create_hybrid_image(image1, image2, filter):
    """
    Takes two images and a low-pass filter and creates a hybrid image. Returns
    the low frequency content of image1, the high frequency content of image 2,
    and the hybrid image.

    Args
    - image1: numpy nd-array of dim (m, n, c)
    - image2: numpy nd-array of dim (m, n, c)
    - filter: numpy nd-array of dim (x, y)
    Returns
    - low_frequencies: numpy nd-array of shape (m, n, c)
    - high_frequencies: numpy nd-array of shape (m, n, c)
    - hybrid_image: numpy nd-array of shape (m, n, c)

    HINTS:
    - You will use your my_imfilter function in this function.
    - You can get just the high frequency content of an image by removing its low
      frequency content. Think about how to do this in mathematical terms.
    - Don't forget to make sure the pixel values of the hybrid image are between
      0 and 1. This is known as 'clipping'.
    - If you want to use images with different dimensions, you should resize them
      in the notebook code.
    """
    assert image1.shape[0] == image2.shape[0]
    assert image1.shape[1] == image2.shape[1]
    assert image1.shape[2] == image2.shape[2]
    assert filter.shape[0] <= image1.shape[0]
    assert filter.shape[1] <= image1.shape[1]
    assert filter.shape[0] % 2 == 1
    assert filter.shape[1] % 2 == 1

    image1_low = my_imfilter(image1, filter)
    image2_low = my_imfilter(image2, filter)
    image2_high = image2 - image2_low

    hybrid_image = np.clip(image1_low + image2_high, 0, 1)

    low_frequencies = image1_low
    high_frequencies = image2_high

    return low_frequencies, high_frequencies, hybrid_image