|
1 | 1 | # Convolutions in 1D
|
2 |
| -For now, let's focus on one-dimensional convolutions, which are defined as: |
| 2 | +Though the act of applying a filter to an image is the most well-known application of convolutions, it is important to start with the funcamentals, so let us focus on one-dimensional convolutions for now. |
| 3 | +These are defined as: |
3 | 4 |
|
4 | 5 | $$(f*g)(x) = \int_{-\infty}^{\infty}f(\xi)g(x-\xi)d\xi = \int_{-\infty}^{\infty}f(x-\xi)g(\xi)d\xi$$
|
5 | 6 |
|
6 | 7 | Note that in this case, $$x$$ is not necessarily a spatial element.
|
7 |
| -Often times, it is time or something else entirely! |
8 |
| -The easiest way to think about this is that the function $$g(x)$$ is being shifted across all of space by the variable $$\xi$$. |
| 8 | +The easiest way to think about this is that the function $$g(x)$$ is reversed and then shifted across all of space by the variable $$\xi$$. |
9 | 9 | At every point $$x$$, we multiply $$f(x)$$ and $$g(x)$$ and integrate the multiplied output to find the convolutional output for that spatial step, $$(f*g)(x)$$.
|
10 | 10 | Note that in code, this is often discretized to look like:
|
11 | 11 |
|
12 | 12 | $$(f*g)[n] = \sum_{m = -\infty}^{\infty}f[m]g[n-m] = \sum_{m = -\infty}^{\infty}f[n-m]g[m]$$
|
13 | 13 |
|
14 | 14 | Where `f[n]` and `g[n]` are arrays of some form.
|
15 |
| -This means we basically just need to keep one array steady, flip the second array around, and move it through the first array one step at a time, performing a simple element-wise multiplication each step. |
| 15 | +Similar to the interpretation in continuous space, this means that we basically need to keep one array steady, reverse the second array, and move it through the first array one step at a time, performing a simple element-wise multiplication each step. |
16 | 16 |
|
17 |
| -This can be seen in the following animation: |
| 17 | +At this stage, the math and code might still be a little opaque, and it might help to think of the second signal as an array of weights, signalling how much of the convolutional output relies on any particular element within signal one. |
| 18 | +In this way a second signal is a filter, and will be called as such for the remainder of this chapter. |
| 19 | +For example, let's say that signal one is a square wave, and signal two is a filter composed of a three element triangle wave (`[1 2 1]`), as shown here: |
| 20 | + |
| 21 | +The simplest interpretation for this is that at every point $$x$$ along signal one, the convolutional output will be composed of one part $$x-1$$, two parts $$x$$, and one part $$x+1$$. |
| 22 | +If we perform a convolution with signal one and this filter, we will find that the square wave is smeared a little at the edges, like so: |
| 23 | + |
| 24 | +ADD ANIMATION |
| 25 | + |
| 26 | +In a sense, the convolution uses the filter as a guide to figure out how much of the signal to stir together at different points. |
| 27 | +Now let's extend this example a bit further with a square wave convolved with a relatively sharp Gaussian, which can be seen in the following animation: |
| 28 | + |
| 29 | +ADD ANIMATION |
| 30 | + |
| 31 | +Note that the final convolved image lookes a lot like the square, except that it's boundaries have been smoothed out or "blurred." |
| 32 | +In practice whenever a Gaussian filter is used, it will always blur the other convolved signal, which is why a convolution with a Gaussian is also called a *blurring operation*. |
| 33 | +This operation is used very often when dealing with two-dimensional images, and we will discuss common kernels found in the wild in the next section on [convolutions of images](../2d/2d.md). |
| 34 | + |
| 35 | +Finally, let's extend this concept to one final example of a square wave convolved with a triangular, saw-tooth function. |
18 | 36 |
|
19 | 37 | <div style="text-align:center">
|
20 | 38 | <video style="width:90%" controls loop>
|
21 |
| - <source src="../res/1d_gaussian_animation.mp4" type="video/mp4"> |
| 39 | + <source src="../res/1d_triangle_animation.mp4" type="video/mp4"> |
22 | 40 | Your browser does not support the video tag.
|
23 | 41 | </video>
|
24 | 42 | </div>
|
25 | 43 |
|
26 |
| -Note that in this case, the output array will be the size of `f[n]` and `g[n]` put together. |
27 |
| -Sometimes, though, we have an large size for `f[n]` and a small size for `g[n]`. |
28 |
| -In this case `g[n]` is often called a *filter*, and often times when we are using a filter on an array (that might represent an image or some form of data), we want the output array to be the same size as the input. |
29 |
| -In this case, rather than outputting a larger array, we often do something special at the borders of the array. |
30 |
| -Depending on the situation, this may be necessary. |
| 44 | +Here, the output is similar to both the triangle and the square in different ways. |
| 45 | +All of these examples show why people often call a convolution a blending operation, as it mixes two signals together. |
| 46 | + |
| 47 | +In all of these case, the output array is the size of `f[n]` and `g[n]` put together, and because the Gaussian had a large number of zeros on either side of it, the convolved output was twice as large as either input signal. |
| 48 | +If we were to trim the zeros from the Gaussian function, we would have a large size for `f[n]` and a small size for `g[n]`. |
| 49 | + |
| 50 | +Often times when we are using a filter on an array (that might represent an image or some form of data), we want the output of the convolution to be the same size as the input. |
| 51 | +Because of this, we may need to enforce specific conditions at the boundary of the array. |
31 | 52 | Note that there are different methods to deal with the edges in this case, so it's best to do whatever seems right when the situation arises.
|
| 53 | +In the following subsection, we will talk about two common boundaries: the simple bound, and periodic boundary conditions. |
32 | 54 |
|
33 |
| -At this stage, the math and code might still be a little opaque, and it might help to think of the second signal or filter as an array of weights, signalling how much of the convolutional output relies on any particular element within signal one. |
34 |
| -For example, let's say that signal one is a square wave, and signal two is a filter composed of a three element triangle wave (`[1 2 1]`), as shown here: |
| 55 | +## Simple boundaries |
35 | 56 |
|
36 |
| -ADD IMAGES |
| 57 | +Since we already know that a naive convolution will result in an array the length of both signals put together, we might now be tasked at providing a simple boundary for the case where the output convolution *must* be a defined size -- usually the size of the input signal. |
| 58 | +In this case, the simplest boundary would be to assume that whenever the filter hits the end of the image, it simply disappears. |
| 59 | +Another way to think about it is that the signal only exists for the domain we specify it over, and is all 0s outside of this domain; therefore, the filter does not sum any signal from elements beyond its scope |
37 | 60 |
|
38 |
| -The simplest interpretation for this is that at every point $$x$$ along signal one, the convolutional output will be composed of one part $$x-1$$, two parts $$x$$, and one part $$x+1$$. |
39 |
| -If we perform a convolution with signal one and this filter, we will find that the square wave is smeared a little at the edges, like so: |
| 61 | + |
| 62 | +## Periodic boundary conditions |
| 63 | + |
| 64 | +Another relatively simple boundary condition is the Periodic boundary condition. |
| 65 | +With the condition, the filter will wrap itself around to the other end of the signal whenever it hits a boundary. |
| 66 | +In this way, the signal is periodic, extending to infinity and beyond in both directions, and when the filter leaves one edge of the domain, it simply appears on the other, opposite edge. |
| 67 | +In code, this typically amounts to using some form of modulus operation... |
| 68 | + |
| 69 | +This particular convolution is known as a *cyclic* convolution and is also the most common output of convolutions that work via the [convolutional theorem](../convolutional_theorem/convolutional_theorem.md), which will be discussed in another section. |
40 | 70 |
|
41 | 71 | <div style="text-align:center">
|
42 | 72 | <video style="width:90%" controls loop>
|
43 |
| - <source src="../res/1d_triangle_animation.mp4" type="video/mp4"> |
| 73 | + <source src="../res/1d_gaussian_animation.mp4" type="video/mp4"> |
44 | 74 | Your browser does not support the video tag.
|
45 | 75 | </video>
|
46 | 76 | </div>
|
47 | 77 |
|
48 |
| -This specific case is similar to a Gaussian, which is a common kernel used for blurring images in two-dimensions. |
49 |
| -For this reason, we will discuss common kernels found in the wild in the next section on [convolutions of images](../2d/2d.md). |
| 78 | +As a final note before continuing: dealing with boundaries is tricky business and can dramatically change the behaviour of the output convolution. |
| 79 | +For this reason, it's important to think about what types of boundaries will work best for what you, the programmer, actually needs. |
| 80 | +The selection of correct boundary conditions will be a common trope for a large portion of computer graphics and physica algorithms where researchers often need to present and simulate data on an array of some sort. |
50 | 81 |
|
51 | 82 | In code, the one-dimensional convolution might look something like this::
|
52 | 83 |
|
|
0 commit comments