{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from ipfml.processing.segmentation import divide_in_blocks\n",
    "from ipfml.processing import transform\n",
    "from ipfml import utils\n",
    "from PIL import Image\n",
    "from scipy import signal\n",
    "from skimage import color\n",
    "import scipy.stats as stats\n",
    "import seaborn as sns\n",
    "import cv2\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from numpy.linalg import svd\n",
    "import os"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "data_folder = \"../dataset\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Custom diff filter analysis"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Utils functions definition"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "def compute_images_path(dict_data):\n",
    "    \n",
    "    scene = dict_data['name']\n",
    "    prefix = dict_data['prefix']\n",
    "    indices = dict_data['indices']\n",
    "    \n",
    "    images_path = []\n",
    "    for index in indices:\n",
    "        path = os.path.join(data_folder, os.path.join(scene, prefix + index + \".png\"))\n",
    "        print(path)\n",
    "        images_path.append(path)\n",
    "    return images_path"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_images_zones(dict_data, images_path):\n",
    "    \n",
    "    id_zone = dict_data['zone']\n",
    "    \n",
    "    zones_img = []\n",
    "    for path in images_path:\n",
    "        img = Image.open(path)\n",
    "        zones = divide_in_blocks(img, (200, 200))\n",
    "        zones_img.append(zones[id_zone])\n",
    "        \n",
    "    return zones_img"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "def display_svd_reconstruction(interval, zones):\n",
    "    \n",
    "    output_images = []\n",
    "    begin, end = interval\n",
    "    for zone in zones:\n",
    "        lab_img = metrics.get_LAB_L(zone)\n",
    "        lab_img = np.array(lab_img, 'uint8')\n",
    "        \n",
    "        U, s, V = svd(lab_img, full_matrices=True)\n",
    "        \n",
    "        smat = np.zeros((end-begin, end-begin), dtype=complex)\n",
    "        smat[:, :] = np.diag(s[begin:end])\n",
    "        output_img = np.dot(U[:, begin:end],  np.dot(smat, V[begin:end, :]))\n",
    "        \n",
    "        print(output_img)\n",
    "        print(np.allclose(lab_img, output_img))\n",
    "        \n",
    "        output_img = np.array(output_img, 'uint8')\n",
    "        output_images.append(Image.fromarray(output_img))\n",
    "        \n",
    "    return output_images"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "def display_images(dict_data, rec_images):\n",
    "    \n",
    "    indices = dict_data['indices']\n",
    "    scene = dict_data['name']\n",
    "    \n",
    "    fig=plt.figure(figsize=(15, 8))\n",
    "    columns = len(zones)\n",
    "    rows = 1\n",
    "    for i in range(1, columns*rows +1):\n",
    "        index = i - 1\n",
    "        fig.add_subplot(rows, columns, i)\n",
    "        plt.imshow(rec_images[index], label=scene + '_' + str(indices[index]))\n",
    "        img_path = 'tmp_images/' + dict_data['prefix'] + 'zone'+ str(current_dict['zone']) + '_reconstruct_' + str(indices[index]) + '.png'\n",
    "        Image.fromarray(np.asarray(rec_images[index], 'uint8')).save(img_path)\n",
    "    plt.show()\n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Scenes information data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "# start 00020 - ref 00900 - step 10\n",
    "dict_appart = {'name': 'Appart1opt02', \n",
    "               'prefix': 'appartAopt_', \n",
    "               'indices': [\"00050\", \"00100\", \"00200\", \"00300\", \"00400\", \"00600\", \"00700\", \"00800\", \"00900\"],\n",
    "               'zone': 9}\n",
    "\n",
    "# start 00050 - ref 01200 - step 10\n",
    "dict_cuisine = {'name': 'Cuisine01', \n",
    "               'prefix': 'cuisine01_', \n",
    "               'indices': [\"00050\", \"00100\", \"00200\", \"00300\", \"00400\", \"00600\", \"00700\", \"00800\", \"00900\", \"01000\", \"01100\", \"01200\"],\n",
    "               'zone': 6}\n",
    "\n",
    "# start 00020 - ref 00950 - step 10\n",
    "dict_sdb_c = {'name': 'SdbCentre', \n",
    "               'prefix': 'SdB2_', \n",
    "               'indices': [\"00020\", \"00400\", \"00950\"],\n",
    "               'zone': 3}\n",
    "\n",
    "# start 00020 - ref 00950 - step 10\n",
    "dict_sdb_d = {'name': 'SdbDroite', \n",
    "               'prefix': 'SdB2_D_', \n",
    "               'indices': [\"00020\", \"00400\", \"00950\"],\n",
    "               'zone': 3}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Definition of parameters"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here we define parameters for the rest of this study :\n",
    "- the scene used\n",
    "- the reconstructed interval (give reduced information from SVD decomposition) \n",
    "- the displayed interval of SVD values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "current_dict = dict_appart\n",
    "displayed_interval = (50, 200)\n",
    "reconstructed_interval = (90, 200)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "../dataset/Appart1opt02/appartAopt_00050.png\n",
      "../dataset/Appart1opt02/appartAopt_00100.png\n",
      "../dataset/Appart1opt02/appartAopt_00200.png\n",
      "../dataset/Appart1opt02/appartAopt_00300.png\n",
      "../dataset/Appart1opt02/appartAopt_00400.png\n",
      "../dataset/Appart1opt02/appartAopt_00600.png\n",
      "../dataset/Appart1opt02/appartAopt_00700.png\n",
      "../dataset/Appart1opt02/appartAopt_00800.png\n",
      "../dataset/Appart1opt02/appartAopt_00900.png\n",
      "../dataset/Cuisine01/cuisine01_00050.png\n",
      "../dataset/Cuisine01/cuisine01_00100.png\n",
      "../dataset/Cuisine01/cuisine01_00200.png\n",
      "../dataset/Cuisine01/cuisine01_00300.png\n",
      "../dataset/Cuisine01/cuisine01_00400.png\n",
      "../dataset/Cuisine01/cuisine01_00600.png\n",
      "../dataset/Cuisine01/cuisine01_00700.png\n",
      "../dataset/Cuisine01/cuisine01_00800.png\n",
      "../dataset/Cuisine01/cuisine01_00900.png\n",
      "../dataset/Cuisine01/cuisine01_01000.png\n",
      "../dataset/Cuisine01/cuisine01_01100.png\n",
      "../dataset/Cuisine01/cuisine01_01200.png\n"
     ]
    }
   ],
   "source": [
    "images_path_appart = compute_images_path(dict_appart)\n",
    "images_path_cuisine = compute_images_path(dict_cuisine)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "zones_appart = get_images_zones(dict_appart, images_path_appart)\n",
    "zones_cuisine = get_images_zones(dict_cuisine, images_path_cuisine)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "def diff_kernel_filter(window, func=max):\n",
    "    \n",
    "    width, height = window.shape\n",
    "    \n",
    "    total_row_diff_list = []\n",
    "    total_col_diff_list = []\n",
    "    \n",
    "    for i in range(width):\n",
    "        \n",
    "        row_diff_list = []\n",
    "        col_diff_list = []\n",
    "        \n",
    "        for j in range(height):\n",
    "            \n",
    "            diff_row = 0\n",
    "            \n",
    "            if i == 0:\n",
    "                diff_row = abs(window[i][j] - window[i+1][j])\n",
    "                \n",
    "            elif i == width - 1:\n",
    "                diff_row = abs(window[i][j] - window[i-1][j])\n",
    "            \n",
    "            else:\n",
    "                diff1 = abs(window[i][j] - window[i-1][j])\n",
    "                diff2 = abs(window[i][j] - window[i+1][j])\n",
    "                diff_row = func(diff1, diff2)\n",
    "                \n",
    "            if j == 0:\n",
    "                diff_col = abs(window[i][j] - window[i][j+1])\n",
    "                \n",
    "            elif j == height - 1:\n",
    "                diff_col = abs(window[i][j] - window[i][j-1])\n",
    "            \n",
    "            else:\n",
    "                diff1 = abs(window[i][j] - window[i][j-1])\n",
    "                diff2 = abs(window[i][j] - window[i][j+1])\n",
    "                diff_col = func(diff1, diff2)\n",
    "            \n",
    "            row_diff_list.append(diff_row)\n",
    "            col_diff_list.append(diff_col)\n",
    "            \n",
    "        total_row_diff_list.append(sum(row_diff_list) / len(row_diff_list))\n",
    "        total_col_diff_list.append(sum(col_diff_list) / len(col_diff_list))\n",
    "        \n",
    "    row_diff = sum(total_row_diff_list) / len(total_row_diff_list)\n",
    "    col_diff = sum(total_col_diff_list) / len(total_col_diff_list)\n",
    "    \n",
    "    return func(row_diff, col_diff)\n",
    "    \n",
    "    \n",
    "        \n",
    "def diff_custom_filter(img, kernel=(5, 5), func=max):\n",
    "    \n",
    "    img = np.array(img)\n",
    "    \n",
    "    width, height = img.shape\n",
    "    \n",
    "    kernel_width, kernel_height = kernel\n",
    "    \n",
    "    if kernel_width % 2 == 0 or kernel_height % 2 == 0:\n",
    "        raise ValueError(\"Invalid kernel size, need to be of odd size\")\n",
    "        \n",
    "    padding_height = (kernel_width - 1) / 2\n",
    "    padding_width = (kernel_width - 1) / 2\n",
    "    \n",
    "    img_diff = []\n",
    "    for i in range(width):\n",
    "        \n",
    "        if i >= padding_width and i < (width - padding_width):\n",
    "            \n",
    "            row_diff = []\n",
    "            \n",
    "            for j in range (height):\n",
    "                \n",
    "                if j >= padding_height and j < (height - padding_height):\n",
    "                    \n",
    "                    # pixel in the center of kernel window size, need to extract window from img\n",
    "                    window = img[int(i-padding_width):int(i+padding_width + 1), int(j-padding_height):int(j+padding_height + 1)]\n",
    "                    \n",
    "                    diff = diff_kernel_filter(window, func)\n",
    "                    row_diff.append(diff)\n",
    "                    \n",
    "            img_diff.append(row_diff)\n",
    "        \n",
    "    return np.array(img_diff)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "def apply_on_zone(zone):\n",
    "    \n",
    "    sub_zones = divide_in_blocks(zone, (20, 20))\n",
    "\n",
    "    diff_list = []\n",
    "\n",
    "    for sub_zone in sub_zones:\n",
    "        l_img = transform.get_LAB_L(sub_zone)\n",
    "        diff = diff_custom_filter(utils.normalize_2D_arr(l_img), (5, 5), max)\n",
    "        global_diff = np.std(diff)\n",
    "        diff_list.append(global_diff)\n",
    "\n",
    "    diff_list = np.array(diff_list)\n",
    "    score = np.std(diff_list[0:int(len(sub_zones)/5)])\n",
    "    print(score)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x7f63b9a36e48>"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 128224 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.imshow(zones_appart[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x7f63b61ccc88>"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 127892 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.imshow(zones_cuisine[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.019411785375902203\n",
      "0.022010065900329633\n",
      "0.023538288175525304\n",
      "0.024255978068903696\n",
      "0.024555364941822696\n",
      "0.025371094905613262\n",
      "0.0257215863991888\n",
      "0.025645858204273037\n",
      "0.02586192220176574\n"
     ]
    }
   ],
   "source": [
    "for zone in zones_appart:\n",
    "    apply_on_zone(zone)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.016907859437032855\n",
      "0.022510883215429146\n",
      "0.02774428742446508\n",
      "0.030267113383204484\n",
      "0.032330051361439856\n",
      "0.032666832076238675\n",
      "0.03325133529876735\n",
      "0.033614614352306754\n",
      "0.03435194845496702\n",
      "0.035516845913060015\n",
      "0.035844373588709205\n",
      "0.03626505901706533\n"
     ]
    }
   ],
   "source": [
    "for zone in zones_cuisine:\n",
    "    apply_on_zone(zone)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 160,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.55 s ± 15.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "(194, 194)"
      ]
     },
     "execution_count": 160,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%timeit diff_img = diff_custom_filter(l_img, kernel=(3, 3), func=max)\n",
    "diff_img.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 123,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.6049964585730372"
      ]
     },
     "execution_count": 123,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.mean(diff_img)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "thesis-venv",
   "language": "python",
   "name": "thesis-venv"
  },
  "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.6.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
