Skip to content
Snippets Groups Projects
Commit 68102af2 authored by Nicolas Aspert's avatar Nicolas Aspert
Browse files

week 4 exercise

parent d16a87de
No related branches found
No related tags found
No related merge requests found
%% Cell type:code id:faef2260 tags:
``` python
# Initialize Otter
import otter
grader = otter.Notebook("Deblurring.ipynb")
```
%% Cell type:markdown id:b8b107c5-c56c-4e5f-8cee-b970f8e10f8f tags:
# Matrix Analysis 2025 - EE312
## Week 4 - Image deblurring using projections
[LTS2](https://lts2.epfl.ch)
### Objectives
In this week's exercises you will need to use the properties of the four fundamental subspaces, as well as the projection operator on those subspaces. You will apply those to deblur an image.
## I. Exercises
%% Cell type:markdown id:3acf015e-a0ae-48a6-925f-7ef5e5b18c01 tags:
<!-- BEGIN QUESTION -->
### 1.
Let $A=\begin{pmatrix}1 & 1 & 1 &0\\1 & 2 & 2 & 1\\2 & 5 & 5 & 3\end{pmatrix}$
Compute a basis for each of its four fundamental subspaces.
%% Cell type:markdown id:c5974723 tags:otter_answer_cell
_Type your answer here, replacing this text._
%% Cell type:markdown id:5504f856-3edd-436f-b14f-4e660a7faf7c tags:
<!-- END QUESTION -->
<!-- BEGIN QUESTION -->
### 2.
Let $A \in \mathbb{R}^{m \times n}$ and suppose it is onto. Prove that $AA^T$ is nonsingular.
%% Cell type:markdown id:658270cd tags:otter_answer_cell
_Type your answer here, replacing this text._
%% Cell type:markdown id:44bf7882-513e-4c29-9619-96bd357670b0 tags:
<!-- END QUESTION -->
## II. Image deblurring
### Introduction
Since we will need to visualize images, just a brief reminder on how to use matplotlib for this task
%% Cell type:code id:a05d6e95-711e-41ce-bf8a-5b983d8999fd tags:
``` python
import numpy as np
import matplotlib.pyplot as plt
import skimage
import skimage.io
import os
```
%% Cell type:markdown id:f387c338-7c82-46cf-9950-def341903021 tags:
We will use the `imread` function from the `scikit-image` package (pre-installed on noto, make sure to install it if you are using a local environment)
%% Cell type:code id:97017b6f-fc95-4d94-b1f6-f7da6621444f tags:
``` python
filename = os.path.join(skimage.data_dir, 'camera.png')
camera = skimage.io.imread(filename)
```
%% Cell type:markdown id:6b4b81f7-6867-43b7-9fd5-9478d421db86 tags:
Some basic information regarding the contents of `camera`:
%% Cell type:code id:03e539bd-2d68-4240-9d72-ee4ef02b9081 tags:
``` python
camera.shape
```
%% Cell type:code id:3b723f81-ebf9-45e5-83a9-6e3d7048586b tags:
``` python
camera.dtype
```
%% Cell type:markdown id:f2c5f73f-bfee-47e7-b68d-d364f6478663 tags:
The type `uint8` means each value in `camera` is represented using a single byte, and is within $[0, 255]$.
Displaying the image is fairly straightforward :
%% Cell type:code id:04ce2927-48e4-41d6-961f-f1a5f0791cc3 tags:
``` python
plt.imshow(camera, cmap='gray')
```
%% Cell type:markdown id:18174a60-7b66-4ccf-a5f4-43ec56299c0e tags:
The image here is widely used in many image processing scientific publications.
The `cmap` parameter specifies the colormap used to display the image. Matplotlib default colormap not being grayscale, passing `cmap='gray'` is needed. You can find [several predefined colormaps](https://matplotlib.org/stable/tutorials/colors/colormaps.html) in Matplotlib.
You can also check the images distributed with `scikit-image` on their [github repository](https://github.com/scikit-image/scikit-image/tree/main/skimage/data). Feel free to use another image, or even one of your own.
%% Cell type:markdown id:30dbc6b0-be1f-43b6-a575-ffdedac904b8 tags:
## 1. Blurring operator
In order to efficiently deblur an image, let us design our own blurring operator. Since it will be entirely known, it will be possible to compute its inverse.
Let us consider an input vector $x=\begin{pmatrix}x_0 \\ x_1 \\ ... \\ x_{N-1}\end{pmatrix} \in \mathbb{R}^N$.
Our blurring operator $B$ will do two things:
- replace each value $x_k$ by the average of $2p+1$ values surrounding $x_k$, i.e. between $x_{k-p}$ and $x_{k+p}$.
- compute this average not for every $x_k$ but only every $s$ values, with $s$ being a subsampling factor, $s>0$.
Formally, if we denote by $y$ the output of the blurring operator on $x$, this means that
- $y\in\mathbb{R}^M$, with $M=\frac{N}{s}$ (NOTE: we will only consider the case where $N$ is a mutiple of $s$)
- $y_m = \frac{1}{2p+1}\sum_{k=sm-p}^{sm+p}x_k$
As you may have noticed, our summation indices in the definition of $y_m$ can be negative in some cases and bigger than $N-1$ in others. In those cases the missing value of $x_k$ is replaced by 0. This way of handling borders is often referred to as **zero-padding**, as it can be achieved by creating an extended version of $x$ with a number of leading and trailing zeros. There are other ways of handling borders, e.g. by using $x_0$ for negative indices and $x_{N-1}$ for indices greater than $N-1$, or even by mirroring the input vector.
%% Cell type:markdown id:63fecde4-7ee7-4692-b21e-dfc33e4a4de7 tags:
1. Write a function that creates the matrix $B$ that performs the operations described above.
Remember that in python the `//` operator performs the integer division.
**!!Warning!!** the automated tests are here to help you, they might however be incomplete and do not fully guarantee that your implementation is correct even if they all pass !
%% Cell type:code id:e40d4cba-1187-448d-96fb-d0033c129aaf tags:otter_answer_cell
``` python
def blur_matrix(N, p, s):
"""
Computes the blurring matrix
Parameters
----------
N : length of the input signal
p : half-length of the blurring filter
s: subsampling factor
Returns
-------
The blurring matrix
"""
...
```
%% Cell type:code id:73ed3a03 tags:
``` python
grader.check("q2p1")
```
%% Cell type:markdown id:af393d26-6c86-4ff0-b8fb-2f78fae94c57 tags:
<!-- BEGIN QUESTION -->
2. What is the rank of $B$ ?
Hint:
- row-rank might be easier to consider
- you might also need to add constraints on $s$ and $p$
%% Cell type:markdown id:d4849ba8 tags:otter_answer_cell
_Type your answer here, replacing this text._
%% Cell type:markdown id:67659a9b-5206-40da-a8ab-0f190884d901 tags:
<!-- END QUESTION -->
## 2. Blurring the image
We now have our blurring matrix ready, let us use it to blur the `camera` image.
As $B$ is designed to operate on vectors, we will need two steps to blur the image
- apply $B$ on each column of the input image
- apply $B$ on each row of the column-blurred image computed above
%% Cell type:markdown id:596b49e7-438a-42c6-b5e6-5ea1a7f338f2 tags:
3. Implement a function that blurs an image using the matrix defined in the previous question
%% Cell type:code id:0a8714b7-1dfa-4aa9-b09a-a5a9caa317bc tags:otter_answer_cell
``` python
def blur_image(img, B):
"""
Blurs the input image using the blur matrix
Parameters
----------
img : input image
B : blur matrix
Returns
-------
The blurred image
"""
...
```
%% Cell type:code id:6498302c tags:
``` python
grader.check("q2p3")
```
%% Cell type:code id:c167c207-66da-41a7-b536-5fc4577420e3 tags:
``` python
# build the blur matrix
B = blur_matrix(512, 3, 2)
```
%% Cell type:code id:42231cfd-b223-4f90-97c5-dec703aee5af tags:
``` python
# Blur on rows
camera_blurred = blur_image(camera, B)
```
%% Cell type:code id:78aa4a09-ff28-4e21-83f9-2b14c6d6ad83 tags:
``` python
plt.imshow(camera_blurred, cmap='gray') # check the result
```
%% Cell type:code id:492b6b43-abb8-49a1-a8cd-4a34c9b1a4eb tags:
``` python
# Display blurred and original side by side
fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(15, 7), dpi=80, sharey=True, sharex=True)
ax[1].imshow(camera_blurred, cmap='gray')
ax[0].imshow(camera, cmap='gray')
```
%% Cell type:markdown id:1d64733c-35eb-440b-a572-60bbdfd446e5 tags:
## 3. Deblurring
Now everything is setup, we can proceed with the image restoration.
%% Cell type:markdown id:c962b694-45b2-4c2b-b7f5-ee69ffd8e342 tags:
<!-- BEGIN QUESTION -->
4. Let us denote the result of a blur operation by $y=Bx$. Using the properties of the four fundamental subspaces, write $x^*$ as a sum, making use of projections operators those subspaces. Hint: you might need results from question 2.
%% Cell type:markdown id:c35a1228 tags:otter_answer_cell
_Type your answer here, replacing this text._
%% Cell type:markdown id:8f024ccc-04b6-4437-aa6a-daba627ed4d4 tags:
<!-- END QUESTION -->
<!-- BEGIN QUESTION -->
5. Using this result, find a possible solution for the complete blurring operation (on both rows and columns).
%% Cell type:markdown id:ab1c7611 tags:otter_answer_cell
_Type your answer here, replacing this text._
%% Cell type:markdown id:cf20cfff-0c77-4367-8b4e-92f41c41acad tags:
<!-- END QUESTION -->
6. Implement a function that computes the right inverse of the blur matrix, and uses it preform image restoration. Do not forget to consider row and columns blurring.
You can use `np.linalg.inv` to perform the inverse of a matrix.
%% Cell type:code id:32426413-a8ea-46ac-ae3e-968f480ff150 tags:otter_answer_cell
``` python
def inverse_blur(blurred_img, B):
...
```
%% Cell type:code id:f82aa4d6 tags:
``` python
grader.check("q2p6")
```
%% Cell type:markdown id:812c7443-3492-46d2-ad99-b2c83826163b tags:
Using this function, compute the reconstructed image from the blurred one
%% Cell type:code id:f270a921-f7c3-40fd-a969-d37010ad2954 tags:
``` python
camera_unblur = inverse_blur(camera_blurred, B)
```
%% Cell type:code id:75296a85-053c-407c-915f-b562ba9c8acd tags:
``` python
plt.imshow(camera_unblur) # check the result
```
%% Cell type:code id:0dfd3731-b40a-4425-b78d-e0b65590c9f3 tags:
``` python
# Let us compare the original image, the restored image and an upscaled version of the blurred image
fig, ax = plt.subplots(nrows=1, ncols=3, figsize=(15, 7), dpi=80, sharey=True, sharex=True)
ax[1].imshow(camera_unblur, cmap='gray')
ax[0].imshow(camera, cmap='gray')
ax[2].imshow(skimage.transform.resize(camera_blurred, (512,512)), cmap='gray')
```
%% Cell type:markdown id:ca9e1169-772a-402a-be66-8fd166826e54 tags:
<!-- BEGIN QUESTION -->
6. Evaluate the performance of the restoration method. What are its limitations for a real-world usage ? Check that the computed solution is valid by blurring the restored image.
%% Cell type:markdown id:2d3adde9 tags:otter_answer_cell
_Type your answer here, replacing this text._
%% Cell type:code id:3658f662-3832-4098-84f4-5d618b95fd02 tags:otter_answer_cell
``` python
...
```
%% Cell type:code id:54f26333 tags:
``` python
grader.check("q2p6")
```
%% Cell type:markdown id:650659df tags:
<!-- END QUESTION -->
%% Cell type:markdown id:0bd3e058 tags:
## Submission
Make sure you have run all cells in your notebook in order before running the cell below, so that all images/graphs appear in the output. The cell below will generate a zip file for you to submit. **Please save before exporting!**
%% Cell type:code id:d10563fe tags:
``` python
# Save your notebook first, then run this cell to export your submission.
grader.export(pdf=False, run_tests=True)
```
%% Cell type:markdown id:de374d0d tags:
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment