{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Histogram Equalization\n",
    "Students: Sam van Kampen, Robin Wacanno\n",
    "\n",
    "Studentnrs: 11874716, 11741163"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Pre-questions: testing the HE code given in the Lecture Notes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Populating the interactive namespace from numpy and matplotlib\n"
     ]
    }
   ],
   "source": [
    "%pylab inline\n",
    "from skimage.io import imread as skimread"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "def histogramEqualization(f, bins=100):\n",
    "    his, be = histogram(f, range=(0,1), bins=bins)\n",
    "    his = his.astype(float)/sum(his)\n",
    "    return interp(f, be, hstack((zeros((1)), cumsum(his))))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "f = imread(\"data/standard_images/cameraman.png\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x7f8984d3cf60>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 129100 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "imshow(f)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "f_eq = histogramEqualization(f)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x7f8984ce4e10>"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 133256 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "imshow(f_eq)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<BarContainer object of 100 artists>"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 7632 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "bar(range(100), histogram(f_eq, range=(0,1), bins=100)[0], width=1, alpha=0.8)\n",
    "bar(range(100), histogram(f, range=(0,1), bins=100)[0], width=1, alpha=0.8)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Question 1: Equalization. Let f:D→[0,M]∈R. Give the expression for the function ψ in this case.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "def discreteHistogramEqualization(f, M=255, bins=100):\n",
    "    his, be = histogram(f, range=(0,M), bins=bins)\n",
    "    his = M*his.astype(float)/sum(his)\n",
    "    return interp(f, be, hstack((zeros((1)), cumsum(his)))).round()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "f2 = skimread('data/standard_images/cameraman.png', pilmode='L') # Automatically reads as uint8."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "f2_eq = discreteHistogramEqualization(f2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x7f8984184cc0>"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 129100 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "imshow(f2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x7f898415a860>"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 133272 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "imshow(f2_eq.astype(uint8))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Question 2: Discrete Histogram Equalization, the LUT way"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "def generateHELUT(f, M=255, bins=100):\n",
    "    his, be = histogram(f, range=(0,M), bins=bins)\n",
    "    his = M * his.astype(float)/sum(his)\n",
    "    LUT = interp(range(256), be, hstack((zeros(1), cumsum(his)))).round()\n",
    "    return LUT"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "LUT = generateHELUT(f2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([  0.,   2.,   5.,   8.,  13.,  17.,  20.,  22.,  25.,  29.,  33.,\n",
       "        36.,  39.,  43.,  48.,  54.,  57.,  60.,  62.,  64.,  65.,  66.,\n",
       "        67.,  68.,  68.,  68.,  69.,  69.,  70.,  70.,  70.,  70.,  71.,\n",
       "        71.,  71.,  71.,  72.,  72.,  72.,  72.,  73.,  73.,  73.,  73.,\n",
       "        74.,  74.,  74.,  74.,  75.,  75.,  75.,  76.,  76.,  76.,  77.,\n",
       "        77.,  77.,  77.,  78.,  78.,  78.,  78.,  78.,  79.,  79.,  79.,\n",
       "        79.,  79.,  79.,  79.,  80.,  80.,  80.,  80.,  80.,  81.,  81.,\n",
       "        81.,  81.,  82.,  82.,  82.,  82.,  82.,  82.,  83.,  83.,  83.,\n",
       "        83.,  83.,  84.,  84.,  84.,  84.,  84.,  85.,  85.,  85.,  85.,\n",
       "        85.,  85.,  85.,  86.,  86.,  86.,  86.,  86.,  86.,  86.,  87.,\n",
       "        87.,  87.,  87.,  87.,  87.,  87.,  88.,  88.,  88.,  88.,  88.,\n",
       "        88.,  89.,  89.,  89.,  89.,  89.,  89.,  90.,  90.,  90.,  91.,\n",
       "        91.,  91.,  91.,  92.,  92.,  92.,  93.,  93.,  94.,  94.,  94.,\n",
       "        95.,  95.,  96.,  96.,  97.,  97.,  98.,  99.,  99., 100., 100.,\n",
       "       101., 102., 102., 103., 104., 105., 105., 106., 107., 108., 109.,\n",
       "       110., 110., 112., 113., 114., 115., 116., 117., 118., 119., 121.,\n",
       "       122., 123., 125., 126., 128., 130., 131., 132., 133., 135., 137.,\n",
       "       138., 139., 141., 143., 145., 147., 149., 151., 154., 157., 160.,\n",
       "       162., 164., 167., 171., 173., 175., 177., 181., 184., 188., 191.,\n",
       "       195., 197., 200., 203., 207., 210., 213., 215., 218., 220., 223.,\n",
       "       225., 226., 228., 231., 233., 235., 236., 237., 239., 240., 242.,\n",
       "       243., 244., 245., 245., 246., 247., 248., 248., 249., 249., 249.,\n",
       "       250., 250., 250., 251., 251., 251., 251., 252., 252., 253., 254.,\n",
       "       255., 255., 255.])"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "LUT"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "f2_eq_lut = LUT[f2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x7f89840c8208>"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 133272 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "imshow(f2_eq_lut)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "(f2_eq_lut == f2_eq).all()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<BarContainer object of 100 artists>"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 7640 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "bar(range(100), histogram(f2_eq, range=(0,255), bins=100)[0], width=1, alpha=0.8)\n",
    "bar(range(100), histogram(f2, range=(0,255), bins=100)[0], width=1, alpha=0.8)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Question 3: Practical Use"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "from skimage.color import rgb2gray\n",
    "\n",
    "puzzle_imgs = [(rgb2gray(skimread('data/hpuzzle%d.jpg' % i))*255).astype(uint8) for i in range(1, 6)]\n",
    "equalized_imgs = []\n",
    "for img in puzzle_imgs:\n",
    "    lut = generateHELUT(img)\n",
    "    equalized_imgs.append(lut[img])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 397908 characters]\n",
      "text/plain": [
       "<Figure size 1080x576 with 10 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "f, ax_array = plt.subplots(2, 5, figsize=(15, 8))\n",
    "for n, row in enumerate(ax_array):\n",
    "    for m, axes in enumerate(row):\n",
    "        if (n == 0): axes.imshow(puzzle_imgs[m], cmap='gray')\n",
    "        else: axes.imshow(equalized_imgs[m], cmap='gray')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "I don't think it works particularly well, as the top circular disk is significantly darker in the last two images."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Question 4: Interpolation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The order would be $O(\\log N)$, for binary search can be used to determine between which two values in $xs$ $x$ is situated since $xs$ is ordered. The actual interpolation between those points is $O(1)$, and $O(\\log N + 1) = O(\\log N)$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "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.7.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
