<h1 align=center> Computer Vision: Assignment 2 </h1>

| [<br /><sub><b>Amr M. Kayid</b></sub>](https://github.com/AmrMKayid)| [<br /><sub><b>Abdullah ELkady</b></sub>](https://github.com/AbdullahKady) |
| :---: | :---: | 
| **37-15594** | **37-16401** |
| **T10** | **T10** |


```python
%reload_ext autoreload
%autoreload 2
%matplotlib inline
```


```python
import math
import numpy as np
import matplotlib.pyplot as plt

from PIL import Image

import math
import numpy as np
import matplotlib.pyplot as plot
import matplotlib.cm as cm
import sys
import pylab
from matplotlib.widgets import Slider
```


```python
cameraman_img = Image.open("Cameraman.tif")
plt.imshow(cameraman_img, cmap="gray")
```

# Problem 1


Implement a function to compute the **Laplacian of Gaussian (LoG) kernel** given the value of sigma (𝜎). 

Deliverables:
- Your code.
- The output edge image for 𝜎 = 2, 𝜎 = 3 and 𝜎 = 4. Name the edge images “LoG_2.jpg”, “Log_3.jpg” and “Log_4.jpg”. The treshold for all cases should be set to 0.1.

First, you are asked to compute the size of the kernel as per the following equation:
\begin{equation}
s=2 \times\lceil 3 \times \sigma\rceil+ 1
\end{equation}


```python
def compute_kernel_size(sigma: str) -> int:
    return int((2 * np.ceil(3 * sigma)) + 1)
```

Given the size of the kernel (𝑠 × 𝑠), implement a function to compute the values inside as per the following function ([0,0] is the middle cell):
\begin{equation}
\operatorname{LoG}(x, y)=\frac{-1}{\pi \sigma^{4}}\left(1-\frac{x^{2}+y^{2}}{2 \sigma^{2}}\right) e^{-\frac{x^{2}+y^{2}}{2 \sigma^{2}}}
\end{equation}


```python
def log_(x: float, y: float, sigma: float) -> float:
    n1 = (-1. / (math.pi * sigma**4))
    common = (x**2 + y**2) / (2 * sigma**2)
    n2 = (1. - common)
    n3 = math.exp(-common)
    return n1 * n2 * n3
```


```python
range_ = lambda start, end: range(start, end+1)
```


```python
def compute_log_mask(sigma: float) -> np.ndarray:
    mask_width = compute_kernel_size(sigma)
    
    log_mask = []
    w_range = int(math.floor(mask_width / 2.))
    print('Going from {} to range {}'.format(-w_range, w_range))
    for x in range_(-w_range, w_range):
        for y in range_(-w_range, w_range):
            log_mask.append(log_(x, y, sigma))
            
    log_mask = np.array(log_mask)
    log_mask = log_mask.reshape(mask_width, mask_width)
    return log_mask
```


```python
def convolve(image, mask):
    image = np.array(image)
    width = image.shape[1]
    height = image.shape[0]
    w_range = int(math.floor(mask.shape[0] / 2.))
    
    new_image = np.zeros((height, width))

    for i in range(w_range, width-w_range):
        for j in range(w_range, height-w_range):
            for k in range_(-w_range, w_range):
                for h in range_(-w_range,w_range):
                    new_image[j, i] += mask[w_range + h,w_range+k] * image[j + h, i + k]
    return new_image
```


```python
def prewitt(image):
    vertical = np.array([[-1, 0, 1], 
                         [-1, 0, 1],
                         [-1 ,0, 1]])
    horizontal = np.array([[-1, -1, -1], 
                         [0, 0, 0],
                         [1 ,1, 1]])
    vertical_image = convolve(image, vertical)    
    horizontal_image = convolve(image, horizontal)    
    gradient_magnitude = np.sqrt(vertical_image**2 + horizontal_image**2)
    
    return gradient_magnitude
```


```python
def normalize(image, min_val, max_val):
    min_ = np.min(image)
    max_ = np.max(image)
    normalized = ((image - min_) / (max_ - min_)) * (max_val - min_val) + min_val
    return normalized
```


```python
def run_log_edge_detection(image, sigma, threshold):
    image = np.array(image)
    
    print("creating mask")
    log_mask = compute_log_mask(sigma)
    
    print("smoothing the image by convolving with the log_ mask")
    log_image = convolve(image, log_mask)
    output_image = np.zeros_like(log_image)
    
    prewitt_image = normalize(prewitt(image), 0, 1)
    
    for i in range(1, log_image.shape[0] - 1):
        for j in range(1, log_image.shape[1] - 1):
            value = log_image[i][j]
            kernel = log_image[i-1:i+2, j-1:j+2]
            k_min = kernel.min()
            k_max = kernel.max()
            is_zero_crossing = False
            if (value > 0 and k_min < 0) or (value < 0 and k_max > 0) or (value == 0):
                is_zero_crossing = True
            
            if (prewitt_image[i][j] > threshold) and is_zero_crossing:
                output_image[i][j] = 1
            
    
    plt.imshow(prewitt_image, cmap ='gray')
    plt.imshow(output_image, cmap='gray')
```


```python
cameraman_img = Image.open("Cameraman.tif")
plt.imshow(cameraman_img, cmap="gray")
```


```python
run_log_edge_detection(cameraman_img, 2, 0.1)
plt.savefig('LoG_2.jpg')
```


```python
run_log_edge_detection(cameraman_img, 3, 0.1)
plt.savefig('LoG_3.jpg')
```


```python
run_log_edge_detection(cameraman_img, 4, 0.1)
plt.savefig('LoG_4.jpg')
```

# Problem 2


Implement a function to sharpen a gray-scale image as per the discussion provided in the tutorial. As a possible kernel for edge detection, consider the kernel provided below. Apply your function to the image “cameraman.tif”.

\begin{equation}
M=\left[\begin{array}{ccc}{-1} & {-1} & {-1} \\ {-1} & {8} & {-1} \\ {-1} & {-1} & {-1}\end{array}\right]
\end{equation}

Deliverables:
- Your code.
- The sharpened output image. Name the image “Sharpened.jpg”


```python
original_image = np.array(cameraman_img)
sharpening_layer = np.zeros_like(original_image)

sharpening_layer = convolve(original_image, np.array([[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]]))
output_sharpened =  0.1 * sharpening_layer + original_image

# Apply threshold so that the ranges stay within 0-255
output_sharpened[output_sharpened > 255] = 255
output_sharpened[output_sharpened < 0] = 0

plt.imshow(output_sharpened, cmap=cm.gray)
plt.savefig('Sharpened.jpg')
```

710aca70cfffc4c2b181bd62b895e31c8a2b1508
ipynb
Jupyter Notebook
Assignment2/Assignment2.ipynb
AmrMKayid/computer-vision
cdce82c2914631d46afe3cc9325893a7491222de
MIT
Assignment2/Assignment2.ipynb
AmrMKayid/computer-vision
cdce82c2914631d46afe3cc9325893a7491222de
MIT
Assignment2/Assignment2.ipynb
AmrMKayid/computer-vision
cdce82c2914631d46afe3cc9325893a7491222de
MIT
Qwen/Qwen-72B
1. YES
2. YES