{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "3766f17e",
   "metadata": {},
   "source": [
    "# Exercise 1: Introduction to image manipulation using Python"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7b22ebe2",
   "metadata": {},
   "source": [
    "## 1.  Install dependencies if needed \n",
    "\n",
    "Run the commands below to install the dependencies"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "e309370a",
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install -q pillow matplotlib scikit-image scikit-learn"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1f6e399f",
   "metadata": {},
   "source": [
    "## 2. Read images\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "acbc9ca6",
   "metadata": {},
   "source": [
    "- Download the Sentinel-2 images from [here](https://drive.google.com/file/d/1oPmyt6jvYrSge2N_uJHRDPIfWWXVGC6a/view?usp=sharing). \n",
    "- Place the downloaded .zip file to the same folder as this notebook"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cf5e9fc3",
   "metadata": {},
   "outputs": [],
   "source": [
    "import zipfile\n",
    "import os\n",
    "\n",
    "with zipfile.ZipFile(\"image_week1_tif.zip\", 'r') as zip_ref:\n",
    "    zip_ref.extractall()\n",
    "    \n",
    "print(os.listdir(\"image_week1_tif\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dbc8bc0e",
   "metadata": {},
   "source": [
    "Read the images using the function ***imread*** of the ***skimage*** library"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "08991163",
   "metadata": {},
   "outputs": [],
   "source": [
    "from skimage.io import imread, imsave\n",
    "import numpy as np\n",
    "\n",
    "# TODO: Use the library skimage to read the images\n",
    "band2_array = \n",
    "band3_array = \n",
    "band4_array = \n",
    "band8_array = "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c51280d3",
   "metadata": {},
   "source": [
    "## 3. Save multi-band images on tif files, and visualize them\n",
    "\n",
    "Use the function below to save, in ***tif*** files, the following images:\n",
    "- Natural color image\n",
    "- False color composite image \n",
    "    - Near infrared → Red\n",
    "    - Red → Green\n",
    "    - Green → Blue"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1865df88",
   "metadata": {},
   "outputs": [],
   "source": [
    "def save_multiband_image_using_skimage(output_path, \n",
    "                         red_arr, green_arr, blue_arr):\n",
    "    \"\"\"\n",
    "    Save image with 3 bands, in a .tif file\n",
    "    \n",
    "    Parameters\n",
    "    ==================\n",
    "    output_path: str\n",
    "        Output file path with .tif extension\n",
    "    red_arr: 2D numpy array\n",
    "        Numpy array for the red band\n",
    "    green_arr: 2D numpy array\n",
    "        Numpy array for the green band\n",
    "    blue_arr: 2D numpy array\n",
    "        Numpy array for the blue band\n",
    "    \"\"\"\n",
    "    \n",
    "    multi_band_arr = np.array([red_arr, green_arr, blue_arr])\n",
    "    multi_band_arr = multi_band_arr.transpose(1, 2, 0)\n",
    "    imsave(output_path, multi_band_arr)\n",
    "\n",
    "    \n",
    "# TODO: Save natural color image using the function save_multiband_image\n",
    "\n",
    "\n",
    "# TODO: Save the false color composite image using the function save_multiband_image\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2325d385",
   "metadata": {},
   "source": [
    "Visualize the images using the ***matplotlib*** (normalize them first)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4ea7771d",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from skimage import exposure\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "def get_normalized_image(image, percentiles=(2, 98)):\n",
    "    \"\"\"\n",
    "    Rescale image to values between 0 to 255 (capping outlier values) \n",
    "    \n",
    "    Parameters\n",
    "    ==================\n",
    "    image: Numpy array\n",
    "        Image numpy array with shape (height, width, num_bands)\n",
    "    \n",
    "    percentiles: tuple\n",
    "        Tuple of min and max percentiles to cap outlier values\n",
    "    \n",
    "    Returns\n",
    "    ==================\n",
    "    output: Numpy array\n",
    "        Normalized image numpy array\n",
    "    \n",
    "    \"\"\"\n",
    "    output = np.zeros_like(image)\n",
    "    for k in range(image.shape[2]): # for each band\n",
    "        p_min, p_max = np.percentile(image[:, :, k], percentiles)\n",
    "        output[:, :, k] = exposure.rescale_intensity(image[:, :, k], \n",
    "                            in_range=(p_min, p_max), out_range=(0, 255))\n",
    "    return output.astype(np.uint8)\n",
    "\n",
    "# TODO: Read the images you saved before and get numpy arrays\n",
    "natural_color_arr = \n",
    "false_color_composite_arr = \n",
    "\n",
    "# TODO: normalize images for visualization\n",
    "natural_color_arr_norm = \n",
    "false_color_composite_arr_norm = "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "991ebd0c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO: visualize natural color image using matplotlib \n",
    "#       Note: before calling plt.imshow() \n",
    "#             you can change the size of the visualized image using the command \n",
    "#             plt.figure(figsize = (6,6)) \n",
    "#             use the value of figsize that you prefer\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cc97396f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO: visualize false color composite image using matplotlib \n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a56c7f4a",
   "metadata": {},
   "source": [
    "## 4. Crop images using bounding boxes\n",
    "\n",
    "Crop the natural color image, and the false composite color image, using the following bounding boxes (in pixel coordinates)\n",
    "- Region 1 → ***y_min***: 2500, ***x_min***: 3090, ***y_max***: 2590, ***x_max*** 3180\n",
    "- Region 2 → ***y_min***: 920,  ***x_min***: 1830, ***y_max***: 1120, ***x_max*** 2030"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "78701d58",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Remember to Run the cell that contains the function implementation before calling it\n",
    "def crop_and_save_image(image_array, \n",
    "                        y_min, x_min, y_max, x_max, \n",
    "                        output_path):\n",
    "    \n",
    "    \"\"\"\n",
    "    Save a crop of the image delimited by bounding box coordinates\n",
    "    and returns the numpy array of the cropped image, with shape (height, width, num_bands) \n",
    "    \n",
    "    Parameters\n",
    "    ==================\n",
    "    image_array: str\n",
    "        Image array\n",
    "    y_min: int\n",
    "        Minimum vertical coordinate of the bounding box\n",
    "    x_min: int\n",
    "        Minimum horizontal coordinate of the bounding box\n",
    "    y_max: int\n",
    "        Maximum vertical coordinate of the bounding box\n",
    "    x_max: int\n",
    "        Maximum horizontal coordinate of the bounding box\n",
    "    output_path: str\n",
    "        Output file path, with extension .tif\n",
    "    \n",
    "    Returns\n",
    "    ==================\n",
    "    out_image:\n",
    "        Numpy array of the cropped image, with shape (height, width, num_bands)\n",
    "    \n",
    "    \"\"\"\n",
    "    \n",
    "    cropped_image_array = image_array[y_min:y_max+1, x_min:x_max+1]\n",
    "    \n",
    "    imsave(output_path, cropped_image_array)\n",
    "    \n",
    "    return cropped_image_array"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f67675bd",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Bounding box coordinates of the Region 1 (pixel coordinates)\n",
    "region1_y_min = 2490\n",
    "region1_x_min = 3090\n",
    "region1_y_max = 2590\n",
    "region1_x_max = 3190\n",
    "\n",
    "# TODO: Use the function crop_and_save_image (defined above) to crop the Region 1,\n",
    "#       in the natural color image, and the false color composite image,\n",
    "#       using the bounding box coordinates defined abov\n",
    "region_1_natural_color_arr = \n",
    "region_1_false_composite_color_arr = "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a424078c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO: Visualize Region 1 in natural color\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6dc7df3d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO: Visualize Region 1 in false color composite\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "daf6fdb1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Bounding box coordinates of the Region 2 (pixel coordinates)\n",
    "region2_y_min = 920\n",
    "region2_x_min = 1830\n",
    "region2_y_max = 1120\n",
    "region2_x_max = 2030\n",
    "\n",
    "# TODO: Use the function crop_and_save_image (defined above) to crop the Region 2,\n",
    "#       in the natural color image, and the false color composite image,\n",
    "#       using the bounding box coordinates defined above\n",
    "region_2_natural_color_arr = \n",
    "region_2_false_composite_color_arr = "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a882d4fa",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO: Visualize Region 2 in natural color\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "540c5de6",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO: Visualize Region 1 in false color composite\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3f9e3d91",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO: Which is the shape of the numpy arrays of the two cropped regions?\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9f48d804",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO: The spatial resolution of the images is 10m. \n",
    "#       What is the area in square meters covered by each of the two cropped regions?\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
