---
jupytext:
  formats: content_md///md:myst,content///ipynb
  text_representation:
    extension: .md
    format_name: myst
    format_version: 0.13
    jupytext_version: 1.13.8
kernelspec:
  display_name: Python 3 (ipykernel)
  language: python
  name: python3
---

(exercises:managing-data:image-processing)=
# Image Processing with NumPy

Images can be represented by NumPy arrays with two (grayscale) or three (color) dimensions. Thus, basic image processing like color transforms and cropping reduce to operations on NumPy arrays. Before solving the exercises you should have read [](managing-data:numpy). Only use NumPy features, no additional modules.

To show results (images) on screen use Matplotlib.

```{code-cell} ipython3
import numpy as np
import matplotlib.pyplot as plt
```

Call the following function whenever you want to see an image:

```{code-cell} ipython3
def show_image(img):
    ''' Show 2d or 3d NumPy array img as image (color range 0...1). '''
    
    # check range
    if img.min() < 0 or img.max() > 1:
        print('Color values out of range!')
        return
    
    # check dims
    if img.ndim == 2:    # disable color normalization for grayscale
        plt.imshow(img, vmin=0, vmax=1, cmap='gray')
    elif img.ndim == 3:
        plt.imshow(img)
    else:
        print('Wrong number of dimensions!')
        return
        
    plt.show()
```

```{hint}
Start with the first exercise and complete exercises one by one. Each exercise will use results from the previous one.
```

## Load Images

Load all images (NumPy arrays) contained in `pasta.npz`. The file contains three color images. Name the arrays `img1`, `img2`, `img3`.

Print the images' shapes and show the images with `show_image`. What's the numeric range of the pixel values (floats 0...1 or integers 0...255)?

**Solution:**

```{code-cell} ipython3
# your solution
```

## Convert to Grayscale

Write a function `rgb2gray` which takes a color image (3d array) and returns a grayscale image (2d array). Calculate gray levels as pixelwise mean of red, green and blue values.

Apply the function to the three images and show results.

```{hint}
NumPy has a `mean` function. The `axis` parameter could be of interest.
```

**Solution:**

```{code-cell} ipython3
# your solution
```

## Cropping

Each image shows a piece of alphabet pasta on a perfect black background (color value 0). Write a function `auto_crop` which finds the bounding box of a grayscale image and returns a copy (not a view!) of the corresponding subarray. The bounding box is the rectangle that contains the pasta piece without black margin.

Apply the function to the grayscale pasta images and show the results.

**Solution:**

```{code-cell} ipython3
# your solution
```

## Centering

Write a function `center` which takes a grayscale image and an integer `n`. The return value shall be a grayscale image of size `n`x`n` with black background and the passed image positioned in the new images center (identical margin width at all sides).

Place each cropped pasta image in a 50x50 image and show the results.

**Solution:**

```{code-cell} ipython3
# your solution
```

## Vectorized Cropping

Implement the above `auto_crop` function without using loops, that is, fully vectorized. Compare execution times.

**Solution:**

```{code-cell} ipython3
# your solution
```
