To be able to edit code and run cells, you need to run the notebook yourself. Where would you like to run the notebook?

In the cloud (experimental)

Binder is a free, open source service that runs scientific notebooks in the cloud! It will take a while, usually 2-7 minutes to get a session.

On your computer

(Recommended if you want to store your changes.)

  1. Copy the notebook URL:
  2. Run Pluto

    (Also see: How to install Julia and Pluto)

  3. Paste URL in the Open box

Frontmatter

If you are publishing this notebook on the web, you can set the parameters below to provide HTML metadata. This is useful for search engines and social media.

Author 1

Submission by: Jazzy Doe (jazz@mit.edu)

👀 Reading hidden code
10.6 ms

Homework 1 - convolutions

18.S191, Spring 2021

This notebook contains built-in, live answer checks! In some exercises you will see a coloured box, which runs a test case on your code, and provides feedback based on the result. Simply edit the code, run it, and the check runs again.

For MIT students: there will also be some additional (secret) test cases that will be run as part of the grading process, and we will look at your notebook and write comments.

Feel free to ask questions!

👀 Reading hidden code
20.8 ms
👀 Reading hidden code
# edit the code below to set your name and kerberos ID (i.e. email without @mit.edu)

student = (name = "Jazzy Doe", kerberos_id = "jazz")

# press the ▶ button in the bottom right of this cell to run your edits
# or use Shift+Enter

# you might need to wait until all other cells in this notebook have completed running.
# scroll down the page to see what's up
15.4 μs

Let's create a package environment:

👀 Reading hidden code
247 μs
👀 Reading hidden code
begin
import Pkg
Pkg.activate(mktempdir())
Pkg.add([
Pkg.PackageSpec(name="Images", version="0.23"),
Pkg.PackageSpec(name="ImageMagick", version="1"),
Pkg.PackageSpec(name="PlutoUI", version="0.7"),
Pkg.PackageSpec(name="HypertextLiteral", version="0.5")
])

using Images
using PlutoUI
using HypertextLiteral
: @htl, @htl_str

end
❔
  Activating new project at `/tmp/jl_bDiBzx`
    Updating registry at `~/.julia/registries/General.toml`
   Resolving package versions...
    Updating `/tmp/jl_bDiBzx/Project.toml`
  [ac1192a8] + HypertextLiteral v0.5.2
  [6218d12a] + ImageMagick v1.3.0
  [916415d5] + Images v0.23.3
  [7f904dfe] + PlutoUI v0.7.9
    Updating `/tmp/jl_bDiBzx/Manifest.toml`
  [621f4979] + AbstractFFTs v1.5.0
  [79e6a3ab] + Adapt v4.3.0
  [13072b0f] + AxisAlgorithms v1.0.1
  [39de3d68] + AxisArrays v0.4.7
  [aafaddc9] + CatIndices v0.2.2
  [d360d2e6] + ChainRulesCore v1.25.1
  [9e997f8a] + ChangesOfVariables v0.1.10
  [3da002f7] + ColorTypes v0.10.12
  [c3611d14] + ColorVectorSpace v0.8.7
  [5ae59095] + Colors v0.12.11
  [34da2185] + Compat v4.16.0
  [ed09eef8] + ComputationalResources v0.3.2
  [150eb455] + CoordinateTransformations v0.6.3
  [dc8bdbbb] + CustomUnitRanges v1.0.2
  [9a962f9c] + DataAPI v1.16.0
  [864edb3b] + DataStructures v0.18.22
  [b4f34e82] + Distances v0.10.12
  [ffbed154] + DocStringExtensions v0.9.5
  [4f61f5a4] + FFTViews v0.3.2
  [7a1cc6ca] + FFTW v1.9.0
  [5789e2e9] + FileIO v1.17.0
  [53c48c17] + FixedPointNumbers v0.8.5
  [a2bd30eb] + Graphics v1.1.3
  [ac1192a8] + HypertextLiteral v0.5.2
  [bbac6d45] + IdentityRanges v0.3.1
  [2803e5a7] + ImageAxes v0.6.9
  [f332f351] + ImageContrastAdjustment v0.3.7
  [a09fc81d] + ImageCore v0.8.22
  [51556ac3] + ImageDistances v0.2.13
  [6a3955dd] + ImageFiltering v0.6.21
  [6218d12a] + ImageMagick v1.3.0
  [bc367c6b] + ImageMetadata v0.9.5
  [787d08f9] + ImageMorphology v0.2.11
  [2996bd0c] + ImageQualityIndexes v0.2.2
  [4e3cecfd] + ImageShow v0.2.3
  [02fcd773] + ImageTransformations v0.8.13
  [916415d5] + Images v0.23.3
  [9b13fd28] + IndirectArrays v0.5.1
  [a98d9a8b] + Interpolations v0.13.6
  [8197267c] + IntervalSets v0.7.11
  [3587e190] + InverseFunctions v0.1.17
  [92d709cd] + IrrationalConstants v0.1.1
  [c8e1da08] + IterTools v1.4.0
  [692b3bcd] + JLLWrappers v1.7.0
  [682c06a0] + JSON v0.21.4
  [2ab3a3ac] + LogExpFunctions v0.3.28
  [1914dd2f] + MacroTools v0.5.16
  [dbb5928d] + MappedArrays v0.4.2
  [e1d29d7a] + Missings v1.2.0
  [e94cdb99] + MosaicViews v0.3.4
  [77ba4419] + NaNMath v1.0.3
  [6fe1bfb0] + OffsetArrays v1.17.0
  [bac558e1] + OrderedCollections v1.8.1
  [5432bcbf] + PaddedViews v0.5.12
  [d96e819e] + Parameters v0.12.3
  [69de0a69] + Parsers v2.8.3
  [7f904dfe] + PlutoUI v0.7.9
  [aea7be01] + PrecompileTools v1.2.1
  [21216c6a] + Preferences v1.4.3
  [94ee1d12] + Quaternions v0.7.6
  [b3c3ace0] + RangeArrays v0.3.2
  [c84ed2f1] + Ratios v0.4.5
  [c1ae055f] + RealDot v0.1.0
  [3cdcf5f2] + RecipesBase v1.3.4
  [189a3867] + Reexport v1.2.2
  [ae029012] + Requires v1.3.1
  [6038ab10] + Rotations v1.7.1
  [699a6c99] + SimpleTraits v0.9.4
  [a2af1166] + SortingAlgorithms v1.2.1
  [276daf66] + SpecialFunctions v1.8.8
  [cae243ae] + StackViews v0.1.2
  [90137ffa] + StaticArrays v1.9.13
  [1e83bf80] + StaticArraysCore v1.4.3
  [82ae8749] + StatsAPI v1.7.1
  [2913bbd2] + StatsBase v0.33.21
  [fd094767] + Suppressor v0.2.8
  [06e1c1a7] + TiledIteration v0.3.1
  [3a884ed6] + UnPack v1.0.2
  [efce3f68] + WoodburyMatrices v0.5.6
  [f5851436] + FFTW_jll v3.3.11+0
  [c73af94c] + ImageMagick_jll v6.9.10-12+3
  [1d5cc7b8] + IntelOpenMP_jll v2025.0.4+0
  [aacddb02] + JpegTurbo_jll v3.1.1+0
  [88015f11] + LERC_jll v3.0.0+1
  [89763e89] + Libtiff_jll v4.4.0+0
  [856f044c] + MKL_jll v2025.0.1+1
  [efe28fd5] + OpenSpecFun_jll v0.5.6+0
  [3161d3a3] + Zstd_jll v1.5.7+1
  [b53b4c65] + libpng_jll v1.6.49+0
  [1317d2d5] + oneTBB_jll v2022.0.0+0
  [0dad84c5] + ArgTools
  [56f22d72] + Artifacts
  [2a0f44e3] + Base64
  [ade2ca70] + Dates
  [8ba89e20] + Distributed
  [f43a241f] + Downloads
  [7b1f6079] + FileWatching
  [b77e0a4c] + InteractiveUtils
  [4af54fe1] + LazyArtifacts
  [b27032c2] + LibCURL
  [76f85450] + LibGit2
  [8f399da3] + Libdl
  [37e2e46d] + LinearAlgebra
  [56ddb016] + Logging
  [d6f4376e] + Markdown
  [a63ad114] + Mmap
  [ca575930] + NetworkOptions
  [44cfe95a] + Pkg
  [de0858da] + Printf
  [3fa0cd96] + REPL
  [9a3f8284] + Random
  [ea8e919c] + SHA
  [9e88b42a] + Serialization
  [1a1011a3] + SharedArrays
  [6462fe0b] + Sockets
  [2f01184e] + SparseArrays
  [10745b16] + Statistics
  [fa267f1f] + TOML
  [a4e569a6] + Tar
  [8dfed614] + Test
  [cf7118a7] + UUIDs
  [4ec0a83e] + Unicode
  [e66e0078] + CompilerSupportLibraries_jll
  [deac9b47] + LibCURL_jll
  [29816b5a] + LibSSH2_jll
  [c8ffd9c3] + MbedTLS_jll
  [14a3606d] + MozillaCACerts_jll
  [4536629a] + OpenBLAS_jll
  [05823500] + OpenLibm_jll
  [83775a58] + Zlib_jll
  [8e850b90] + libblastrampoline_jll
  [8e850ede] + nghttp2_jll
  [3f19e933] + p7zip_jll
5.8 s





👀 Reading hidden code
8.5 μs

Exercise 1 - Manipulating vectors (1D images)

A Vector is a 1D array. We can think of that as a 1D image.

👀 Reading hidden code
5.0 ms
👀 Reading hidden code
14.1 μs
colored_line(example_vector)
👀 Reading hidden code
13.3 μs

Exerise 1.1

👉 Make a random vector random_vect of length 10 using the rand function.

👀 Reading hidden code
4.9 ms
random_vect = rand(10) # replace this with your code!
👀 Reading hidden code
14.4 μs
👀 Reading hidden code
13.0 μs

Got it!

Well done! You can run the cell above again to generate a new vector!

👀 Reading hidden code
113 ms

Hint

You can find out more about any function (like rand) by clicking on the Live Docs in the bottom right of this Pluto window, and typing it in the top.

image

image

We recommend that you leave the window open while you work on Julia code. It will continually look up documentation for anything you type!

Help, I don't see the Live Docs!

Try the following:

🙋 Are you viewing a static preview? The Live Docs only work if you run the notebook. If you are reading this on our course website, then click the button in the top right to run the notebook.

🙋 Is your screen to small? Try resizing your window or zooming out.

👀 Reading hidden code
45.3 ms

TODO

We should include more pointers to basic Julia tutorials
👀 Reading hidden code
16.2 μs

👉 Make a function mean using a for loop, which computes the mean/average of a vector of numbers.

👀 Reading hidden code
204 μs
mean (generic function with 1 method)
function mean(x)
return missing
end
👀 Reading hidden code
363 μs
missing
mean([1, 2, 3])
👀 Reading hidden code
13.4 μs

Here we go!

Replace missing with your answer.

👀 Reading hidden code
139 μs

👉 Define m to be the mean of random_vect.

👀 Reading hidden code
212 μs
missing
m = missing
👀 Reading hidden code
12.2 μs

Here we go!

Replace missing with your answer.

👀 Reading hidden code
5.2 ms

👉 Write a function demean, which takes a vector x and subtracts the mean from each value in x.

👀 Reading hidden code
193 μs
demean (generic function with 1 method)
function demean(x)
return missing
end
👀 Reading hidden code
355 μs

Let's check that the mean of the demean(random_vect) is 0:

Due to floating-point round-off error it may not be exactly 0.

👀 Reading hidden code
6.6 ms
👀 Reading hidden code
2.4 ms
missing
mean(demean(copy_of_random_vect))
👀 Reading hidden code
12.5 μs
copy_of_random_vect = copy(random_vect); # in case demean modifies `x`
👀 Reading hidden code
13.9 μs

TODO

In the demean exercise, we should talk about mutation. Can we have them discover the problem with mutation instead of saying it?

Idea

We could have an exercise to write two visual tranformations: flip180 and invert. If you show those, applied to the same image, next to eachother, the second image will be flipped and inverted.

👀 Reading hidden code
110 ms

Exercise 1.2

👉 Generate a vector of 100 elements. Where:

  • the center 20 elements are set to 1, and

  • all other elements are 0.

👀 Reading hidden code
8.3 ms
create_bar (generic function with 1 method)
function create_bar()
return missing
end
👀 Reading hidden code
341 μs
👀 Reading hidden code
12.5 μs

Here we go!

Replace missing with your answer.

👀 Reading hidden code
163 μs

TODO

Last year these next exercises proved too difficult, but we should still do something to introduce 2D arrays

👀 Reading hidden code
4.5 ms

Exercise 1.3

👉 Write a function that turns a Vector of Vectors into a Matrix.

👀 Reading hidden code
324 μs
vecvec_to_matrix (generic function with 1 method)
function vecvec_to_matrix(vecvec)
return missing
end
👀 Reading hidden code
374 μs
missing
vecvec_to_matrix([[1,2], [3,4]])
👀 Reading hidden code
15.8 μs

Here we go!

Replace missing with your answer.

👀 Reading hidden code
144 μs

👉 Write a function that turns a Matrix into aVector of Vectors .

👀 Reading hidden code
199 μs
matrix_to_vecvec (generic function with 1 method)
function matrix_to_vecvec(matrix)
return missing
end
👀 Reading hidden code
339 μs
missing
matrix_to_vecvec([6 7; 8 9])
👀 Reading hidden code
21.5 μs

Here we go!

Replace missing with your answer.

👀 Reading hidden code
148 μs
colored_line (generic function with 2 methods)
👀 Reading hidden code
845 μs





👀 Reading hidden code
8.1 μs

Exercise 2 - Manipulating images

In this exercise we will get familiar with matrices (2D arrays) in Julia, by manipulating images. Recall that in Julia images are matrices of RGB color objects.

Let's load a picture of Philip again.

👀 Reading hidden code
359 μs
"https://user-images.githubusercontent.com/6933510/107239146-dcc3fd00-6a28-11eb-8c7b-41aaf6618935.png"
url = "https://user-images.githubusercontent.com/6933510/107239146-dcc3fd00-6a28-11eb-8c7b-41aaf6618935.png"
👀 Reading hidden code
13.8 μs
"/tmp/jl_44gbyL"
philip_filename = download(url) # download to a local file. The filename is returned
👀 Reading hidden code
402 ms
philip = load(philip_filename)
👀 Reading hidden code
874 ms

Hi there Philip

👀 Reading hidden code
206 μs
philip_head = philip[470:800, 140:410]
👀 Reading hidden code
242 μs

TODO

Let's first have them play around with this image
👀 Reading hidden code
12.3 μs

TODO

I don't like that we are returning a tuple here instead of a color
👀 Reading hidden code
12.0 μs

Exercise 2.1

👉 Write a function mean_color that accepts an object called image. It should calculate the mean (average) amounts of red, green and blue in the image and return a tuple (r, g, b) of those means.

👀 Reading hidden code
283 μs
mean_color (generic function with 1 method)
function mean_color(image)
return missing
end
👀 Reading hidden code
345 μs
missing
mean_color(philip)
👀 Reading hidden code
12.1 μs

Here we go!

Replace missing with your answer.

👀 Reading hidden code
18.4 ms

Exercise 2.2

👉 Look up the documentation on the floor function. Use it to write a function quantize(x::Number) that takes in a value x (which you can assume is between 0 and 1) and "quantizes" it into bins of width 0.1. For example, check that 0.267 gets mapped to 0.2.

👀 Reading hidden code
4.7 ms
quantize (generic function with 1 method)
function quantize(x::Number)
return missing
end
👀 Reading hidden code
353 μs
quantize(0.267), quantize(0.91)
👀 Reading hidden code
11.8 μs

Here we go!

Replace missing with your answer.

👀 Reading hidden code
119 μs

Exercise 2.3

👉 Write the second method of the function quantize, i.e. a new version of the function with the same name. This method will accept a color object called color, of the type AbstractRGB.

Here, ::AbstractRGB is a type annotation. This ensures that this version of the function will be chosen when passing in an object whose type is a subtype of the AbstractRGB abstract type. For example, both the RGB and RGBX types satisfy this.

The method you write should return a new RGB object, in which each component (r, g and b) are quantized.

👀 Reading hidden code
594 μs
quantize (generic function with 2 methods)
function quantize(color::AbstractRGB)
return missing
end
👀 Reading hidden code
353 μs

Exercise 2.4

👉 Write a method quantize(image::AbstractMatrix) that quantizes an image by quantizing each pixel in the image. (You may assume that the matrix is a matrix of color objects.)

👀 Reading hidden code
236 μs
quantize (generic function with 3 methods)
function quantize(image::AbstractMatrix)
return missing
end
👀 Reading hidden code
332 μs

Let's apply your method!

👀 Reading hidden code
187 μs
missing
quantize(philip)
👀 Reading hidden code
13.2 μs

Exercise 2.5

👉 Write a function invert that inverts a color, i.e. sends (r,g,b) to (1r,1g,1b).

👀 Reading hidden code
264 μs
invert (generic function with 1 method)
function invert(color::AbstractRGB)
return missing
end
👀 Reading hidden code
367 μs

Let's invert some colors:

👀 Reading hidden code
173 μs
color_black = RGB(0.0, 0.0, 0.0)
👀 Reading hidden code
14.2 μs
missing
invert(color_black)
👀 Reading hidden code
10.9 μs
color_red = RGB(0.8, 0.1, 0.1)
👀 Reading hidden code
13.4 μs
missing
invert(color_red)
👀 Reading hidden code
10.5 μs

Can you invert the picture of Philip?

👀 Reading hidden code
173 μs
missing
philip_inverted = missing
👀 Reading hidden code
10.7 μs

Exercise 2.6

👉 Write a function noisify(x::Number, s) to add randomness of intensity s to a value x, i.e. to add a random value between s and +s to x. If the result falls outside the range (0,1) you should "clamp" it to that range. (Note that Julia has a clamp function, but you should write your own function myclamp(x).)

👀 Reading hidden code
282 μs
noisify (generic function with 1 method)
function noisify(x::Number, s)

return missing
end
👀 Reading hidden code
346 μs

Hint

The rand function generates (uniform) random floating-point numbers between 0 and 1.

👀 Reading hidden code
273 μs

👉 Write the second method noisify(c::AbstractRGB, s) to add random noise of intensity s to each of the (r,g,b) values in a colour.

👀 Reading hidden code
202 μs
noisify (generic function with 2 methods)
function noisify(color::AbstractRGB, s)
return missing
end
👀 Reading hidden code
801 μs
0.0
👀 Reading hidden code
249 ms
Error message

MethodError: no method matching noisify(::typeof(ColorTypes.red), ::Float64)

Closest candidates are:

noisify(::Number, ::Any) at ~/work/disorganised-mess/disorganised-mess/homework1.jl#==#f38b198d-39cf-456f-a841-1ba08f206010:1

noisify(::ColorTypes.AbstractRGB, ::Any) at ~/work/disorganised-mess/disorganised-mess/homework1.jl#==#db4bad9f-df1c-4640-bb34-dd2fe9bdce18:1

noisify(::AbstractMatrix, ::Any) at ~/work/disorganised-mess/disorganised-mess/homework1.jl#==#21a5885d-00ab-428b-96c3-c28c98c4ca6d:1

Stack trace

Here is what happened, the most recent locations are first:

  1. noisify(red, color_noise)
noisify(red, color_noise)
👀 Reading hidden code
---
👀 Reading hidden code
61.2 μs

👉 Write the third method noisify(image::AbstractMatrix, s) to noisify each pixel of an image.

👀 Reading hidden code
189 μs
noisify (generic function with 3 methods)
function noisify(image::AbstractMatrix, s)
return missing
end
👀 Reading hidden code
363 μs
0.0
@bind philip_noise Slider(0:0.01:8, show_value=true)
👀 Reading hidden code
762 μs
missing
noisify(philip, philip_noise)
👀 Reading hidden code
11.2 μs
👀 Reading hidden code
58.4 μs

👉 For which noise intensity does it become unrecognisable?

You may need noise intensities larger than 1. Why?

👀 Reading hidden code
219 μs

The image is unrecognisable with intensity ...

answer_about_noise_intensity = md"""
The image is unrecognisable with intensity ...
"""
👀 Reading hidden code
221 μs





👀 Reading hidden code
8.5 μs

Exercise 3 - Convolutions

As we have seen in the videos, we can produce cool effects using the mathematical technique of convolutions. We input one image M and get a new image M back.

Conceptually we think of M as a matrix. In practice, in Julia it will be a Matrix of color objects, and we may need to take that into account. Ideally, however, we should write a generic function that will work for any type of data contained in the matrix.

A convolution works on a small window of an image, i.e. a region centered around a given point (i,j). We will suppose that the window is a square region with odd side length 2+1, running from ,,0,,.

The result of the convolution over a given window, centred at the point (i,j) is a single number; this number is the value that we will use for Mi,j. (Note that neighbouring windows overlap.)

To get started let's restrict ourselves to convolutions in 1D. So a window is just a 1D region from to .

👀 Reading hidden code
717 μs

Let's create a vector v of random numbers of length n=100.

👀 Reading hidden code
208 μs
100
n = 100
👀 Reading hidden code
10.2 μs
v = rand(n)
👀 Reading hidden code
14.3 μs

Feel free to experiment with different values!

👀 Reading hidden code
246 μs

Exercise 3.1

You've seen some colored lines in this notebook to visualize arrays. Can you make another one?

👉 Try plotting our vector v using colored_line(v).

👀 Reading hidden code
300 μs

👀 Reading hidden code
59.3 μs

Try changing n and v around. Notice that you can run the cell v = rand(n) again to regenerate new random values.

👀 Reading hidden code
229 μs

Exercise 3.2

We need to decide how to handle the boundary conditions, i.e. what happens if we try to access a position in the vector v beyond 1:n. The simplest solution is to assume that vi is 0 outside the original vector; however, this may lead to strange boundary effects.

A better solution is to use the closest value that is inside the vector. Effectively we are extending the vector and copying the extreme values into the extended positions. (Indeed, this is one way we could implement this; these extra positions are called ghost cells.)

👉 Write a function extend(v, i) that checks whether the position i is inside 1:n. If so, return the ith component of v; otherwise, return the nearest end value.

👀 Reading hidden code
490 μs
extend (generic function with 1 method)
function extend(v::AbstractVector, i)
return missing
end
👀 Reading hidden code
368 μs

Some test cases:

👀 Reading hidden code
210 μs
missing
extend(v, 1)
👀 Reading hidden code
11.1 μs
missing
extend(v, -8)
👀 Reading hidden code
11.1 μs
missing
extend(v, n + 10)
👀 Reading hidden code
13.4 μs

Extended with 0:

👀 Reading hidden code
187 μs
👀 Reading hidden code
34.4 ms

Extended with your extend:

👀 Reading hidden code
200 μs
missing
👀 Reading hidden code
31.2 μs

Here we go!

Replace missing with your answer.

👀 Reading hidden code
109 μs

Exercise 3.3

👉 Write a function blur_1D(v, l) that blurs a vector v with a window of length l by averaging the elements within a window from to . This is called a box blur.

👀 Reading hidden code
298 μs
blur_1D (generic function with 1 method)
function blur_1D(v, l)
return missing
end
👀 Reading hidden code
356 μs
👀 Reading hidden code
26.3 ms

Exercise 3.4

👉 Apply the box blur to your vector v. Show the original and the new vector by creating two cells that call colored_line. Make the parameter interactive, and call it l_box instead of just l to avoid a variable naming conflict.

👀 Reading hidden code
261 μs

👀 Reading hidden code
59.3 μs

Hint

Have a look at Exercise 2 to see an example of adding interactivity with a slider. You can read the Interactivity and the PlutoUI sample notebooks (right click -> Open in new tab) to learn more.

👀 Reading hidden code
361 μs

Exercise 3.5

The box blur is a simple example of a convolution, i.e. a linear function of a window around each point, given by

vi=nvinkn,

where k is a vector called a kernel.

Again, we need to take care about what happens if vin falls off the end of the vector.

👉 Write a function convolve_vector(v, k) that performs this convolution. You need to think of the vector k as being centred on the position i. So n in the above formula runs between and , where 2+1 is the length of the vector k. You will need to do the necessary manipulation of indices.

👀 Reading hidden code
568 μs
convolve_vector (generic function with 1 method)
function convolve_vector(v, k)
return missing
end
👀 Reading hidden code
359 μs

Hint

l = (length(k) - 1) ÷ 2

👀 Reading hidden code
217 μs
👀 Reading hidden code
11.3 μs
missing
test_convolution = let
v = [1, 10, 100, 1000, 10000]
k = [0, 1, 0]
convolve_vector(v, k)
end
👀 Reading hidden code
33.8 μs

Edit the cell above, or create a new cell with your own test cases!

👀 Reading hidden code
221 μs

Here we go!

Replace missing with your answer.

👀 Reading hidden code
197 μs

Exercise 3.6

👉 Write a function gaussian_kernel.

The definition of a Gaussian in 1D is

G(x)=12πσ2exp(x22σ2)

We need to sample (i.e. evaluate) this at each pixel in a region of size n2, and then normalize so that the sum of the resulting kernel is 1.

For simplicity you can take σ=1.

👀 Reading hidden code
447 μs
gaussian_kernel (generic function with 1 method)
function gaussian_kernel(n)
return missing
end
👀 Reading hidden code
329 μs

Let's test your kernel function!

👀 Reading hidden code
178 μs
3
gaussian_kernel_size_1D = 3 # change this value, or turn me into a slider!
👀 Reading hidden code
11.6 μs
👀 Reading hidden code
12.0 μs
test_gauss_1D_a = let
v = random_vect
k = gaussian_kernel(gaussian_kernel_size_1D)
if k !== missing
convolve_vector(v, k)
end
end
👀 Reading hidden code
33.2 μs
👀 Reading hidden code
11.5 μs
test_gauss_1D_b = let
v = create_bar()
k = gaussian_kernel(gaussian_kernel_size_1D)
if k !== missing
convolve_vector(v, k)
end
end
👀 Reading hidden code
34.2 μs





👀 Reading hidden code
8.7 μs

Exercise 4 - Convolutions of images

Now let's move to 2D images. The convolution is then given by a kernel matrix K:

Mi,j=k,lMik,jlKk,l,

where the sum is over the possible values of k and l in the window. Again we think of the window as being centered at (i,j).

A common notation for this operation is :

M=MK.

👀 Reading hidden code
490 μs

Exercise 4.1

👉 Write a function extend that takes a matrix M and indices i and j, and returns the closest element of the matrix.

👀 Reading hidden code
254 μs
extend (generic function with 2 methods)
function extend(M::AbstractMatrix, i, j)
return missing
end
👀 Reading hidden code
381 μs

Hint

num_rows, num_columns = size(M)

👀 Reading hidden code
197 μs

Let's test it!

👀 Reading hidden code
209 μs
small_image = Gray.(rand(5,5))
👀 Reading hidden code
64.0 ms

Extended with 0:

👀 Reading hidden code
184 μs
👀 Reading hidden code
146 ms

Extended with your extend:

👀 Reading hidden code
183 μs
9×9 Matrix{Missing}:
 missing  missing  missing  missing  missing  missing  missing  missing  missing
 missing  missing  missing  missing  missing  missing  missing  missing  missing
 missing  missing  missing  missing  missing  missing  missing  missing  missing
 missing  missing  missing  missing  missing  missing  missing  missing  missing
 missing  missing  missing  missing  missing  missing  missing  missing  missing
 missing  missing  missing  missing  missing  missing  missing  missing  missing
 missing  missing  missing  missing  missing  missing  missing  missing  missing
 missing  missing  missing  missing  missing  missing  missing  missing  missing
 missing  missing  missing  missing  missing  missing  missing  missing  missing
👀 Reading hidden code
22.3 ms

Oopsie!

Make sure that you define a variable called extend_mat

👀 Reading hidden code
21.8 ms
283×223 Matrix{Missing}:
 missing  missing  missing  missing  missing  …  missing  missing  missing  missing
 missing  missing  missing  missing  missing     missing  missing  missing  missing
 missing  missing  missing  missing  missing     missing  missing  missing  missing
 missing  missing  missing  missing  missing     missing  missing  missing  missing
 missing  missing  missing  missing  missing     missing  missing  missing  missing
 missing  missing  missing  missing  missing  …  missing  missing  missing  missing
 missing  missing  missing  missing  missing     missing  missing  missing  missing
 ⋮                                            ⋱           ⋮                 
 missing  missing  missing  missing  missing     missing  missing  missing  missing
 missing  missing  missing  missing  missing     missing  missing  missing  missing
 missing  missing  missing  missing  missing     missing  missing  missing  missing
 missing  missing  missing  missing  missing  …  missing  missing  missing  missing
 missing  missing  missing  missing  missing     missing  missing  missing  missing
 missing  missing  missing  missing  missing     missing  missing  missing  missing
👀 Reading hidden code
20.5 ms

Exercise 4.2

👉 Implement a function convolve_image(M, K).

👀 Reading hidden code
223 μs
convolve_image (generic function with 1 method)
function convolve_image(M::AbstractMatrix, K::AbstractMatrix)
return missing
end
👀 Reading hidden code
385 μs

Hint

num_rows, num_columns = size(K)

👀 Reading hidden code
193 μs

Let's test it out! 🎃

👀 Reading hidden code
210 μs
👀 Reading hidden code
86.9 ms
3×3 Matrix{Float64}:
 0.0  0.0  0.0
 0.5  0.0  0.5
 0.0  0.0  0.0
K_test = [
0 0 0
1/2 0 1/2
0 0 0
]
👀 Reading hidden code
23.9 ms
missing
convolve_image(test_image_with_border, K_test)
👀 Reading hidden code
13.3 μs

Edit K_test to create your own test case!

👀 Reading hidden code
275 μs
missing
convolve_image(philip, K_test)
👀 Reading hidden code
11.8 μs

You can create all sorts of effects by choosing the kernel in a smart way. Today, we will implement two special kernels, to produce a Gaussian blur and a Sobel edge detect filter.

Make sure that you have watched the lecture about convolutions!

👀 Reading hidden code
437 μs

Exercise 4.3

👉 Apply a Gaussian blur to an image.

Here, the 2D Gaussian kernel will be defined as

G(x,y)=12πσ2e(x2+y2)2σ2

👀 Reading hidden code
331 μs
with_gaussian_blur (generic function with 1 method)
function with_gaussian_blur(image)
return missing
end
👀 Reading hidden code
332 μs

Let's make it interactive. 💫

👀 Reading hidden code
215 μs
Enable webcam
👀 Reading hidden code
45.1 ms
Error message

Another cell defining gauss_camera_image contains errors.

with_gaussian_blur(gauss_camera_image)
👀 Reading hidden code
---
Error message

MethodError: no method matching getindex(::Missing, ::String)

Stack trace

Here is what happened, the most recent locations are first:

  1. process_raw_camera_data(raw_camera_data::Missing)
    	# So to get the red values for each pixel, we take every 4th value, starting at 	# the 1st:	reds_flat = UInt8.(raw_camera_data["data"][1:4:end])	greens_flat = UInt8.(raw_camera_data["data"][2:4:end])	blues_flat = UInt8.(raw_camera_data["data"][3:4:end])
  2. Show more...
gauss_camera_image = process_raw_camera_data(gauss_raw_camera_data);
👀 Reading hidden code
---

Exercise 4.4

👉 Create a Sobel edge detection filter.

Here, we will need to create two separate filters that separately detect edges in the horizontal and vertical directions:

Gx=([121][1 0 1])A=[101202101]AGy=([101][1 2 1])A=[121000121]A

Here A is the array corresponding to your image. We can think of these as derivatives in the x and y directions.

Then we combine them by finding the magnitude of the gradient (in the sense of multivariate calculus) by defining

Gtotal=Gx2+Gy2.

For simplicity you can choose one of the "channels" (colours) in the image to apply this to.

👀 Reading hidden code
543 μs
with_sobel_edge_detect (generic function with 1 method)
function with_sobel_edge_detect(image)
return missing
end
👀 Reading hidden code
353 μs
Enable webcam
👀 Reading hidden code
739 μs
Error message

Another cell defining sobel_camera_image contains errors.

C'est la vie !
with_sobel_edge_detect(sobel_camera_image)
👀 Reading hidden code
---
Error message

MethodError: no method matching getindex(::Missing, ::String)

Stack trace

Here is what happened, the most recent locations are first:

  1. process_raw_camera_data(raw_camera_data::Missing)
    	# So to get the red values for each pixel, we take every 4th value, starting at 	# the 1st:	reds_flat = UInt8.(raw_camera_data["data"][1:4:end])	greens_flat = UInt8.(raw_camera_data["data"][2:4:end])	blues_flat = UInt8.(raw_camera_data["data"][3:4:end])
  2. Show more...
sobel_camera_image = Gray.(process_raw_camera_data(sobel_raw_camera_data));
👀 Reading hidden code
---





👀 Reading hidden code
8.1 μs

Exercise 5 - Lecture transcript

(MIT students only)

Please see the Canvas post for transcript document for week 1 here.

We need each of you to correct about 100 lines (see instructions in the beginning of the document.)

👉 Please mention the name of the video and the line ranges you edited:

👀 Reading hidden code
487 μs

Convolution, lines 100-0 (for example)

lines_i_edited = md"""
Convolution, lines 100-0 (_for example_)
"""
👀 Reading hidden code
273 μs





👀 Reading hidden code
8.8 μs

Oops!

Before you submit, remember to fill in your name and kerberos ID at the top of this notebook!

👀 Reading hidden code
252 μs





👀 Reading hidden code
8.3 μs

Function library

Just some helper functions used in the notebook.

👀 Reading hidden code
219 μs
hint (generic function with 1 method)
👀 Reading hidden code
447 μs
almost (generic function with 1 method)
👀 Reading hidden code
443 μs
still_missing (generic function with 2 methods)
👀 Reading hidden code
822 μs
keep_working (generic function with 2 methods)
👀 Reading hidden code
806 μs
👀 Reading hidden code
10.0 ms
correct (generic function with 2 methods)
👀 Reading hidden code
708 μs
not_defined (generic function with 1 method)
👀 Reading hidden code
773 μs
todo (generic function with 1 method)
👀 Reading hidden code
2.9 ms
👀 Reading hidden code
1.7 ms
camera_input (generic function with 1 method)
👀 Reading hidden code
1.3 ms
process_raw_camera_data (generic function with 1 method)
👀 Reading hidden code
1.3 ms

homework 1, version 5

👀 Reading hidden code
207 μs