image-multithresholding 1.0
A Python 3 library to find thresholds in the gray levels histogram of an image.
Requires Python: >=3.6

{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "da73becf",
   "metadata": {},
   "source": [
    "# Image Multithresholding\n",
    "#### A Python 3 library to find thresholds in the gray levels' histogram of an image, which may be used in segmentation.\n",
    "\n",
    "For more details, *Cf.* Reference: Andrea Rey and Claudio Delrieux. *Multithresholding techniques in SAR image classification*. Remote Sensing Applications: Society and Environment, 23:100540, 2021."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5053890b",
   "metadata": {},
   "source": [
    "#### Citation \n",
    "\n",
    "To cite this package in publications use: \n",
    "\n",
    "```\n",
    "@software{leon2022image,\n",
    "    author       = {Joaquin Leon and Andrea Rey},    \n",
    "    title        = {Image Multithresholding: A Python package},    \n",
    "    year         = 2022,    \n",
    "    publisher    = {PyPi},    \n",
    "    version      = {latest},    \n",
    "    url          = {https://github.com/image-multithresholding/Image-multithresholding}    \n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e61508b7",
   "metadata": {},
   "source": [
    "#### Installing the package\n",
    "Run the cell bellow to install the `image-multithresholding` package in your system."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "ffb8bf71",
   "metadata": {},
   "outputs": [],
   "source": [
    "python3 -m pip install image-multithresholding"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "402bf1af",
   "metadata": {},
   "source": [
    "### Histogram of gray levels\n",
    "For a grayscale image in the luminance range 1 (black) to $L$ (white), $H(i)$ denotes the number of pixels in the image with gray level $i \\in [1, \\dots,L]$. \n",
    "The normalized gray-level histogram is defined by\n",
    "$$p_i=\\frac{H(i)}{N},$$\n",
    "where $N$ is the total number of pixels."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c106e746",
   "metadata": {},
   "source": [
    "##### Importing the modules\n",
    "It is necessary to import the following modules in order to run the examples presented in this tutorial."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "70149143",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Run this cell to import the necessary packages to run the example.\n",
    "#!python3 -m pip install matplotlib numpy\n",
    "from IPython.display import Image\n",
    "from matplotlib import pyplot as plt\n",
    "import numpy as np\n",
    "from image_multi_thresholding.base import load_image"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2bfaee1d",
   "metadata": {},
   "source": [
    "##### Loading the image to analyze\n",
    "Load the image of interest using the `base.load_image` function.\n",
    "In what follows, the analysis is based on the reference image named **exImage**."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "26272031",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/jpeg": "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\n",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "execution_count": 31,
     "metadata": {
      "image/jpeg": {
       "height": 200,
       "width": 200
      }
     },
     "output_type": "execute_result"
    }
   ],
   "source": [
    "image = load_image('exImage.jpg')\n",
    "\n",
    "# Preview\n",
    "Image('exImage.jpg', width=200, height=200)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f144d563",
   "metadata": {},
   "source": [
    "##### Colors for segmentation\n",
    "Define colors to be used in the thresholded image obtained from **exImage**. Feel free to modify them."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "3f5b8447",
   "metadata": {},
   "outputs": [],
   "source": [
    "COLORS = [\n",
    "    (58, 3, 7),\n",
    "    (93, 46, 70),\n",
    "    (173, 106, 108),\n",
    "    (208, 173, 167),\n",
    "    (232, 214, 203),\n",
    "]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4d34ec9c",
   "metadata": {},
   "source": [
    "##### Example of histogram\n",
    "The code in the following cell produces and visualizes the histogram of the grays levels of the reference image. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "f7f1e008",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0, 0.5, 'Pixel count')"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "from image_multi_thresholding.base import _image_histogram\n",
    "\n",
    "histogram = _image_histogram(image)\n",
    "\n",
    "# Preview\n",
    "%matplotlib inline\n",
    "x = np.arange(0, len(histogram))\n",
    "fig = plt.figure()\n",
    "ax = fig.add_axes([0, 0, 1, 1])\n",
    "ax.plot(x, histogram)\n",
    "ax.set_title('Histogram')\n",
    "ax.set_xlabel('Gray level')\n",
    "ax.set_ylabel('Pixel count')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "77669f12",
   "metadata": {},
   "source": [
    "##### Example of probability density function (*pdf*)\n",
    "The code in the following cell produces and visualizes the *pdf* of the grays levels of the reference image. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "a05b613d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0, 0.5, '%')"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "from image_multi_thresholding.base import _image_probabilities\n",
    "\n",
    "prob = _image_probabilities(image)\n",
    "\n",
    "# Preview\n",
    "%matplotlib inline\n",
    "x = np.arange(0, len(prob))\n",
    "fig = plt.figure()\n",
    "ax = fig.add_axes([0, 0, 1, 1])\n",
    "ax.plot(x, prob)\n",
    "ax.set_title('Probabilities')\n",
    "ax.set_xlabel('Gray level')\n",
    "ax.set_ylabel('%')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d70e09a6",
   "metadata": {},
   "source": [
    "### Classes defined by a set of thresholds \n",
    "Given a set of gray levels $t_1, \\dots ,t_{k-1}$ and considering $t_0=0$ and $t_k=L$, the collection $[1, \\dots , L]$ can be partitioned into $k$ classes \n",
    "$$C_j=\\{t_{j-1}+1, \\dots ,t_j\\},$$\n",
    "for $j=1, \\dots, k$."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "54bc953c",
   "metadata": {},
   "source": [
    "### Basic statistical concepts\n",
    "Consider the class $C_j$, for $j \\in \\{1, \\dots, k\\}$. \n",
    "The following is defined:\n",
    "<ul>\n",
    "<li> The probability of occurrence $$w_j=\\sum_{i \\in C_j} p_i.$$ </li>\n",
    "<li> The mean of levels $$\\mu_j=\\sum_{i \\in C_j} \\frac{ip_i}{w_j}.$$ </li>\n",
    "<li> The variance of levels $$\\sigma_j^2=\\sum_{i \\in C_j} \\frac{(i-\\mu_j)^2p_i}{w_j}.$$ </li>\n",
    "<li> The $n$th central moment of levels $$(\\mu_n)_j=\\sum_{i \\in C_j} \\frac{(i-\\mu_j)^np_i}{w_j}.$$\n",
    "Notice that $(\\mu_2)_j=\\sigma_j^2$. </li>\n",
    "<li> The skewness of levels $(\\beta_1)_j=\\frac{(\\mu_3)_j}{(\\mu_2)_j^{3/2}}.$$ </li>\n",
    "</ul>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2ebb089a",
   "metadata": {},
   "source": [
    "### Otsu Method \n",
    "\n",
    "The between-class variance of gray levels is defined as:\n",
    "$$ \\sigma_B^2(s_1, \\dots, s_{k-1})=\\sum_{j=1}^k w_j (\\mu_j-\\mu_T)^2.$$\n",
    "\n",
    "The optimal thresholds are those which maximize the between class variance:\n",
    "$$(t_1,t_2, \\dots, t_{k-1}) = \\underset{1<s_1 < s_2 < \\cdots <s_{k-1}<L}{\\operatorname{argmax}} \\{\\sigma_B^2(s_1, s_2, \\dots ,s_{k-1})\\}.$$\n",
    "\n",
    "**Reference:** Nobuyuki Otsu. *A threshold selection method from gray-level histograms*. IEEE Transactions on Systems, Man, and Cybernetics, 9(1):62–66, 1979."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "cfad9108",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(67, 168, 227)"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from image_multi_thresholding.threshold.otsu import threshold_otsu\n",
    "\n",
    "th_otsu = threshold_otsu(image, k=3)\n",
    "th_otsu"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "c15412ad",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<PIL.Image.Image image mode=RGB size=201x251 at 0x7F66A69465E0>"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from image_multi_thresholding.utils import get_thresholded_image\n",
    "get_thresholded_image(image, th_otsu, COLORS)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "09037a5f",
   "metadata": {},
   "source": [
    "### Maximum Entropy Criterion \n",
    "\n",
    "The histogram total entropy of segmented classes is defined as:\n",
    "$$TE(s_1, \\dots , s_{k-1})=-\\sum_{j=1}^k \\sum_{i \\in C_j} \\frac{p_i}{w_j} \\ln \\left(\\frac{p_i}{w_j}\\right).$$\n",
    "\n",
    "The optimal thresholds are those which maximize total entropy:\n",
    "$$(t_1,t_2, \\dots, t_{k-1}) = \\underset{1<s_1 < s_2 < \\cdots <s_{k-1}<L}{\\operatorname{argmax}} \\{TE(s_1, s_2, \\dots ,s_{k-1})\\}.$$\n",
    "\n",
    "\n",
    "**Reference:** Jagat Narain Kapur, Prasanna K. Sahoo, and Andrew K. C. Wong. *A new method for gray-level picture thresholding using the entropy of the histogram*. Computer Vision, Graphics, and Image Processing, 29(3):273–285, 1985."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "c863d8c3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(133, 158, 194)"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from image_multi_thresholding.threshold.mec import threshold_mec\n",
    "\n",
    "th_mec = threshold_mec(image, k=3)\n",
    "th_mec"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "9ec6c94c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<PIL.Image.Image image mode=RGB size=201x251 at 0x7F66A680DB50>"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from image_multi_thresholding.utils import get_thresholded_image\n",
    "get_thresholded_image(image, th_mec, COLORS)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "438afd14",
   "metadata": {},
   "source": [
    "### Hill Clustering Approach \n",
    "\n",
    "Image histogram can be divided in equal intervals of different gray levels, called cells. The sum of all frequencies of gray levels belonging to cell $i$ is represented by $f_i$. For two adjacent cells, arrow direction at cell $i$ is defined as follows:\n",
    "$$d_i = \\begin{cases}\n",
    "1 & \\text{if $f_{i-1}>f_{i+1} \\wedge f_{i-1} \\ge f_i \\wedge f_i \\ne 0$,} \\\\\n",
    "-1 & \\text{if $f_{i+1}>f_{i-1} \\wedge f_{i+1} \\ge f_i \\wedge f_i \\ne 0$,} \\\\\n",
    "0 & \\text{otherwise.}\n",
    "\\end{cases}$$\n",
    "\n",
    "Peak identification holds in the following cases: 1.- cell $i$ is the peak of the hill if $d_i=0 \\wedge d_{i-1}=-1 \\wedge d_{i+1}=1$. 2.- there is a peak between cells $i$ and $i+1$ if $d_i=-1 \\wedge d_{i+1}=1$. In order to find the optimum cell size, it must be initialized in zero and peak identification process must be repeated until desired number of peaks is reached. Afterwards, for $j=1, \\dots , k-1$, the $j$th valley is located between cells $i_j$ and $h_j$ if $d_{i_j}=1 \\wedge d_{h_j}=-1$, with $h_j$ the first value to the right of $i_j$ that verifies $d_{h_j}\\ne 0$. Finally, if $a_{i_j}$ is the first gray level in cell $i_j$ and $b_{h_j}$ is the last gray level in cell $h_j$, the optimal thresholds are $t_j = a_{i_j} +(b_{h_j}-a_{i_j})/2$, for $j=1, \\dots , k-1$. \n",
    "\n",
    "**Reference:** Du-Ming Tsai and Ying-Hsiung Chen. *A fast histogram-clustering approach for multi-level thresholding*. Pattern Recognition Letters, 13(4):245–252, 1992.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "af35a670",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[24, 80, 176, 232]"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from image_multi_thresholding.threshold.hca import threshold_hca\n",
    "\n",
    "th_hca = threshold_hca(image, k=3)\n",
    "th_hca"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "6e4060f9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<PIL.Image.Image image mode=RGB size=201x251 at 0x7F66A682F0A0>"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from image_multi_thresholding.utils import get_thresholded_image\n",
    "get_thresholded_image(image, th_hca, COLORS)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "827fae50",
   "metadata": {},
   "source": [
    "### Maximum Likelihood Thresholding\n",
    "\n",
    "The extension of maximum likelihood thresholding to multi-thresholding is equivalent to obtain the optimum thresholds:\n",
    "$$ (t_1,t_2, \\dots, t_{k-1}) = \\underset{1<s_1 < s_2 < \\cdots <s_{k-1}<L}{\\operatorname{argmin}} \\left\\{\\sum_{j=1}^k w_j \\ln(\\sigma_j^2)\\right\\}.$$\n",
    "\n",
    "\n",
    "**Reference:** Takio Kurita, Nobuyuki Otsu, and N. Abdelmalek. *Maximum likelihood thresholding based on population mixture models*. Pattern Recognition, 25(10):1231–1240, 1992.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "24308b95",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(2, 247, 248)"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from image_multi_thresholding.threshold.mll import threshold_mll\n",
    "\n",
    "th_mll = threshold_mll(image, k=3)\n",
    "th_mll"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "7f5304f0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<PIL.Image.Image image mode=RGB size=201x251 at 0x7F66A6820F10>"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from image_multi_thresholding.utils import get_thresholded_image\n",
    "get_thresholded_image(image, th_mll, COLORS)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "891ccd55",
   "metadata": {},
   "source": [
    "### Linear Rational Approximation\n",
    "\n",
    "The peaks $P_1, \\dots, P_k$ are identified as explained in the method Hill Clustering Approach. Consider the sets of gray levels $X_1=\\{x \\in \\text{cell}_i \\text{ for some } i=P_1, \\dots, P_2\\}$, and $X_j=\\{x \\in \\text{cell}_i \\text{ for some } i=P_j+1$\\}, for $j=2, \\dots, k-1$. For each set, the algorithm can fit the points $(i,H(i))$ with $i \\in X_j$ by a real rational function of the form $R(x)=\\sum _{h=0}^n a_hx^h/(1+\\sum_{h=1}^m b_hx^h)$. Then, for $j=1, \\dots , k-1$, the optimal thresholds are as $t_j = \\operatorname{argmin}_{i \\in X_j} \\{R(i)\\}$.\n",
    "\n",
    "**Reference:** Nikos Papamarkos and Basilios Gatos. *A new approach for multilevel threshold selection*. CVGIP: Graphical Model and Image Processing, 56(5):357–370, 1994.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "88f5d53d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[120, 189, 247]"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from image_multi_thresholding.threshold.lra import threshold_lra\n",
    "\n",
    "th_lra = threshold_lra(image, k=3, n=1, m=1)\n",
    "th_lra"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "1ee5a8c4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<PIL.Image.Image image mode=RGB size=201x251 at 0x7F66A6820C40>"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from image_multi_thresholding.utils import get_thresholded_image\n",
    "get_thresholded_image(image, th_lra, COLORS)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "42b0f063",
   "metadata": {},
   "source": [
    "### Maximum Correlation Criterion\n",
    "\n",
    "Total correlation is defined by:\n",
    "$$TC(s_1, \\dots, s_{k-1})=-\\sum_{j=1}^k \\ln\\left(\\sum_{i \\in C_j} \\left(\\frac{p_i}{w_j}\\right)^2\\right).$$\n",
    "\n",
    "The optimal thresholds are those which maximize total correlation:\n",
    "$$(t_1,t_2, \\dots, t_{k-1}) = \\underset{1<s_1 < s_2 < \\cdots <s_{k-1}<L}{\\operatorname{argmax}} \\{TC(s_1, s_2, \\dots ,s_{k-1})\\}.$$\n",
    "\n",
    "\n",
    "**Reference:** Jui-Cheng Yen, Fu-Juay Chang, and Shyang Chang. *A new criterion for automatic multilevel thresholding*. IEEE Transactions on Image Processing, 4(3):370–378, 1995.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "21995ddb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(13, 106, 202)"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from image_multi_thresholding.threshold.mcc import threshold_mcc\n",
    "\n",
    "th_mcc = threshold_mcc(image, k=3)\n",
    "th_mcc"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "75a431ba",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<PIL.Image.Image image mode=RGB size=201x251 at 0x7F66A6820610>"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from image_multi_thresholding.utils import get_thresholded_image\n",
    "get_thresholded_image(image, th_mcc, COLORS)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "503dbae9",
   "metadata": {},
   "source": [
    "### Automatic Thresholding Criterion\n",
    "\n",
    "First, $s_1$ is found using the method Maximum Correlation Criterion for two classes. This produces the classes $\\{1, \\dots, s_1\\}$ and $\\{s_1+1, \\dots, L\\}$. The same method is then applied to the normalized class with the highest variance, in order to obtain $s_2$ and partitioning the histogram in three classes. This is repeated until $s_{k-1}$ is computed. The optimal thresholds are obtained sorting the set $\\{s_1, s_2, \\dots, s_{k-1}\\}$.\n",
    "\n",
    "\n",
    "**Reference:** Nikos Papamarkos and Basilios Gatos. *A new approach for multilevel threshold selection*. CVGIP: Graphical Model and Image Processing, 56(5):357–370, 1994."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "52481a16",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[42, 148, 198]"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from image_multi_thresholding.threshold.atc import threshold_atc\n",
    "\n",
    "th_atc = threshold_atc(image, k=3)\n",
    "th_atc"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "54e294c1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<PIL.Image.Image image mode=RGB size=201x251 at 0x7F66A6820B50>"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from image_multi_thresholding.utils import get_thresholded_image\n",
    "get_thresholded_image(image, th_atc, COLORS)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7234871c",
   "metadata": {},
   "source": [
    "### Fast Otsu Method\n",
    "\n",
    "For $u,v \\in \\{1,2, \\dots, L\\}$, $u$-$v$ interval zeroth-order and first-order moments are respectively defined by: $P(u,v)=\\sum_{i=u}^v p_i$, and $S(u,v)=\\sum_{i=u}^v ip_i$.\n",
    "Considering $s_0=0$ and $s_k=L$, the modified between-class variance per class is given by:\n",
    "$$\\widetilde{\\sigma}^2_B (s_1,\\dots,s_{k-1})= \\sum_{j=0}^{k-1} H(s_j+1,s_{j+1}),$$\n",
    "where $H(s_j+1,s_{j+1}) = [S(s_j+1,s_{j+1})]^2/P(s_j+1,s_{j+1})$. Thus, optimal thresholds are those which maximize modified between-class variance:\n",
    "$$(t_1,t_2, \\dots, t_{k-1}) = \\underset{1<s_1 < s_2 < \\cdots <s_{k-1}<L}{\\operatorname{argmax}} \\{\\widetilde{\\sigma}_B^2(s_1, s_2, \\dots ,s_{k-1})\\}.$$\n",
    "\n",
    "\n",
    "**Reference:** Ping-Sung Liao, Tse-Sheng Chen, Pau-Choo Chung, et al. *A fast algorithm for multilevel thresholding*. J. Inf. Sci. Eng., 17(5):713–727, 2001.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "6bc4f51c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(74, 168, 227)"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from image_multi_thresholding.threshold.otsu import threshold_fom\n",
    "\n",
    "th_fom = threshold_fom(image, k=3)\n",
    "th_fom"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "2528b007",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAMkAAAD7CAIAAABPFif0AAAHaklEQVR4nO3dQW7cNhiGYU1roAcZIBsDPUAdwAsDXecCvUDRe3llIBfIwkCy98abAL5LFjJYmqIoieJH8afeZ+XY45mx9YaiJM748vL0OAACvx39BNAt2oIKbUGFtqBCW1ChLajQFlRoCyq0BRXaggptQYW2oEJbUKEtqNAWVGgLKrQFFdqCCm1BhbagQltQoS2o0BZUaAsqtAUV2oIKbUGFtqBCW1ChLajQFlRoCyq0BRXaggptQYW2oEJbUKEtqNAWVGgLKrQFFdqCCm1BhbagQltQoS2o0BZUaAsqtAUV2oIKbUGFtqBCW1ChLajQFlRujn4CZbx9+zF+cH24O/aZwDHflqsq+s+RH1xwg+Itvn37Qd+jy8vT49HPYZdoTBm2BrHmcU8emY1xq1RA+216Jnuedgdd1h63Nk2M2knqKKYLq9GWNJHrw90ZErQYmbytozb8uDH6y85QZMK28rbrScahag5ssVhbBNGyQwrbdZxIT1aMW6pyYZenf/+r+Xg4VsG8or365wFoCxuC27SnsnHuFFJ+MXOdZcx/aAsfFJxDs8YGKrQFFdqCCm1BhbagQltQoS2o0BZUbLdlaDHTCVlt6/pwVycs8s3W1jWfxIu91nyLL/3tiVWp7g7Hr04X+Kev/6fvbaU+Fkgetg5CPR6kN3b0JSHTS7buxYbTe5vb/ImfK/rSyK0NGcquuTU2dfZBwStUp0ORf4PEMoHFRrMtRr//IdTa2icO+lffBxm5f85trbkVm9HXc483S9w4vYvs7HV1zY1bU2Ujm+7m5rb3yhnVSunpWsEHaoeBtuYUb67gvSUUXHzXOMNtjXYW1t8Wbcdh8609c4siIxZVqZVvSzQHL/4CFagVPi9fNizFyXfCqmbvuFXhdBQjllHb2hrPA1m8xEZV9S23FZRkKyySOtCHtmx1k0BSLbgx1BPF2NLc9cQAPdl1E1xWW9yWNcc5wjLt8vL0GN2EX7///PL5k/t4GAb3TyedY16FiSVTsOXD9cRpQ9Gq5lKLihYWXT6Fzry3tSmXnWo+Fg4UXwfhdohbO/D3pO7b87j7ke4iDS0RNmdhn7hSkFRwh0UwzpmjWr/lqvry+VPBwqamzc09HHVWltmWn07wmcZFC2PPqLBhjc3X7z+DgNyczEpYw8yzTYRl6LpFfelfTs64NXeqwpzxR0i8AjH6+TwnHBq3teUfP07PrFosLNhF5r0MeorTv0NGW8Fn1k+lW1Zkmr+mp1ONXmWOE6fDmGnZqXFa2LehrehEfvFmVvjnioNPRi3+mIkTfieJb1Vb6d+jxUl9xuwwGt8wc7E1+qXFr3ZmoS0rrexU8EAkuKvg0IdxaxhOU9V6ayaUiUZP0pPvw7pTekrEseaXk3Gbjpu7/PPn30c/h+ZM91/R3VziM3setxu0FZFoJb3559aDpL9l8MbLnvKirUzSCDIabZDV92k+XOWFQxbRVr7pkgoOhnzsE8voY6Qpq/XXvloxXSx5NtMxm7YKO8/pq8UJAG1prVmVZMv6OSVt1WZ377n1SIW2DmNlSMs++KWthqSvgtd5Dm5l7P7zKZyDMEmRWvGTc4xbJpWdtIlO+dKWbZsiCy6Hq68isE/sSmKBdX2MW10ZF1A0clmTa9W9aSSsgbagQ1tQoS2o0BZUaAsqtAUV2oIKbUGFtqBCW1ChLajQFlRoCyq0BRXaggptQYW2oEJbUKEtqNAWVGgLKrQFFdqCCm1BhbagQltQoS2o0BZUaAsqtAUV2oIKbUGFtqBCW5B4e33m/U5R2Nvr8/gBbSGfyyiKtrDB2+vz9fY+nZSza77lv5t5m3/nCKW4nlaGNST+dsH0bcrHeqJ/Paud951GKa6h9QNV4PLX73+4u4je9dT19j7oibw64G/x7J58/7e1SRAiTNufUVTmXH58NtOhbmdz6XvwHzT66/C/N/oM4ezfWIsyxy1fYmNHb+kT/Y9Z89Bns+kQr4gCbRlytsLmeqoT2bnacvqOzD/EGyruHAInbcvpMrKjYgqcva2R6cL8WXkjVY1o653FvOpPzzehrWXHZtd4QAm223K/dPWkdf1Fi2Pvsym223KOPSBCVCdtoUGdr2mOTpUsTtstOum4xT60gs7HrTlvr897LmYz8q1x3nFr5aAVzcjueYGaTtpWwN9F+tEE5zh8hLWItt5N136lb0Zbi2gr5I9VB16q62CfS1uN6qCtkx4nogLGLagwbkGFtqBCW8e43t53f3Kf+RZUGLe2yRhszjBERTFuQYVxq7xglFo5aI03m1twZnHkY9xql/VT87xvYBOCq5Zz6zJsYdw6UrD81V0dNxpTgHHrSNGG+ghrYNyCDseJUKEtqNAWVGgLKrQFFdqCCm1BhbagQltQoS2o0BZUaOss3DKeassMuVYNFcYtzNq5lppxCyqMW1ChLajQFlRoCyq0BRXaggptQYW2oEJbUKEtqNAWVGgLKrQFFdqCCm1BhbagQltQoS2o0BZUaAsqtAUV2oIKbUGFtqBCW1ChLajQFlRoCyq0BRXagsov58dl//TFi/8AAAAASUVORK5CYII=\n",
      "text/plain": [
       "<PIL.Image.Image image mode=RGB size=201x251 at 0x7F66A19C6580>"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from image_multi_thresholding.utils import get_thresholded_image\n",
    "get_thresholded_image(image, th_fom, COLORS)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "87ad26ad",
   "metadata": {},
   "source": [
    "### Deterministic Parameter Criterion\n",
    "\n",
    "Given $p > 0$, consider a Gaussian mask with bins $b_n = 0.5[1-\\cos(n\\pi/p)]$, for $n=1, \\dots ,2p+1$. Applying mask convolution to the original histogram $H(i)$,  \n",
    "$$\\tilde{H}(i)=\\begin{cases}\n",
    "\\frac{1}{2p+1} \\sum\\limits_{h=1-i}^p b_{h+p+1}H(i+h) & \\text{if $1 \\le i \\le p$,} \\\\\n",
    "\\frac{1}{2p+1} \\sum\\limits_{h=-p}^p b_{h+p+1}H(i+h) & \\text{if $p+1 \\le i \\le L-p$,} \\\\\n",
    "\\frac{1}{2p+1} \\sum\\limits_{h=-p}^{L-i} b_{h+p+1}H(i+h) & \\text{if $L-p+1 \\le i \\le L$.} \\end{cases}\n",
    "$$\n",
    "Given $i \\in \\{2, \\dots , L-1\\}$, we say that $\\tilde{H}(i)$ is a valley if $\\tilde{H}(i)<\\tilde{H}(i-1)$ and $\\tilde{H}(i)<\\tilde{H}(i+1)$, which is denoted by $V(i)$. Suppose there are $k-1$ valleys, then the smoothed histogram can be divided into the classes $C_j=\\{V(j-1), \\dots, V(j)-1\\}$, for $j=1,\\dots ,k$, where $V(0)=1$ and $V(k)=L+1$. For each class $C_j$, fix $l_j=\\max\\{z \\in \\mathbb{Z}/z \\le 0.5[V(j)-V(j-1)-1]\\}$. The searching windows of $C_j$ are defined by $W_j^h = \\{V(j-1)+h, \\dots , V(j-1)+h+l_j\\}$, for $0 \\le h \\le l_j$. If $(\\beta_1)_j^h$ is the skewness of the searching window $W_j^h$, the optimal window for the class $C_j$ is obtained as $W_j^{\\text{opt}} = \\operatorname{argmin}_{0 \\le h \\le l_j} \\{|(\\beta_1)_j^h|\\}$. Given class $C_j$, the mean is estimated by $\\widehat{m_j} = \\sum_{i \\in W_j^{\\text{opt}}} i\\tilde{H}(i)/\\sum_{i \\in W_j^{\\text{opt}}} \\tilde{H}(i)$, the variance by $\\widehat{\\sigma^2_j} = \\sum_{i \\in W_j^{\\text{opt}}} (i-\\widehat{m_j})^2 \\tilde{H}(i)/\\sum_{i \\in W_j^{\\text{opt}}} \\tilde{H}(i)$, and the proportion by $\\widehat{P_j} = \\sum_{i \\in W_j^{\\text{opt}}}  \\tilde{H}(i)/\\sum_{i=1}^L \\tilde{H}(i)$.\n",
    "\n",
    "If $m = \\underset{1 \\le j \\le k}{\\operatorname{argmax}} \\left\\{\\frac{\\widehat{P_j}}{\\sqrt{2\\pi} \\widehat{\\sigma_j}} \\exp \\left[ -\\frac{1}{2} \\left( \\frac{i-\\widehat{m_j}}{\\widehat{\\sigma_j}} \\right)^2\\right]\\right\\}$, the classification label is $i \\in C_m$ for $i=1, \\dots, L$ and $m=1, \\dots, k$. Thus, optimal thresholds are given by $t_j = \\max \\{i / i \\in C_j\\}$, for $j=1, \\dots, k-1$.\n",
    "\n",
    "\n",
    "**Reference:** Jeng-Horng Chang, Kuo-Chin Fan, and Yang-Lang Chang. *Multimodal gray-level histogram modeling and decomposition*. Image and Vision Computing, 20(3):203–216, 2002.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "b7e99828",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[86]"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from image_multi_thresholding.threshold.dpc import threshold_dpc\n",
    "\n",
    "th_dpc = threshold_dpc(image, mink=3)\n",
    "th_dpc"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "d58709e4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAMkAAAD7CAIAAABPFif0AAADrklEQVR4nO3dS27aYBhAUdJG6kI6rNQFdNJZd9HFsgiG7CUDV4jydDCXhzlnFCHFseHyGX5Z8dvfn38WEPhy7x1gtrRFRVtUtEVFW1S0RUVbVLRFRVtUtEVFW1S0RUVbVLRFRVtUtEVFW1S0RUVbVLRFRVtUtEVFW1S0RUVbVLRFRVtUtEVFW1S0RUVbVLRFRVtUtEVFW1S0RUVbVLRFRVtUtEVFW1S0RUVbVLRFRVtUtEVFW1S0RUVbVLRFRVtUtEVFW1S0RUVbVLRFRVtUtEVFW1S0RUVbVLRFRVtUtEVFW1S0RUVbVLRFRVtUtEVFW1S0RUVbVLRFRVtUtEVFW1S0RUVbVLRFRVtUtEVFW1S0RUVbVLRFRVtUtEVFW1S0RUVbVLRFRVtUtEVFW1S0RUVbVLRFRVtUtEVFW1S0RUVbVLRFRVtUtEVFW1S0RUVbVLRFRVtUtEVFW1S0RUVbVLRFRVtUtEVFW1S0RUVbXNl6tVyvlovF4v3ee8LcfP/xe/jB3OJyw3w6RltcbjOiDtIW1zfMM20xyunT345hnmmLUU6f/g7SFhVtUdEWFW1R0RYVbVHRFhVtUdEWFW1R0RYVbVHRFhVtUdEWFW1R0RYVbVHRFhVtUdEWFW1R0RYVbVHRFhVtUdEWFW1R0RYVbVHRFhVtUdEWFW1R0RYVbVHRFhVtkVivltriaob/Qe9eUUx18G4G2w+aW3zCzmQ6zdzivO2Sxt98RVsc9qkb+Bz0vr2J7Xu2nNj0Bbd24fEdK+Fib7++frvg1+Q1G9Pn0zEXtjXYn3NTmttsYXO0O1s7+yxcd39mbOfJifKa1NZg2MUx+7f/SndvmrN/+tWsV8vt9+0NXKGtJ/JShe2fB27stb4nHjvbzsyDHOZrza2Dnr2z4WS388i9dmabdflHeSWm2BzCyBXz2zC3/vMsM2zzwfyOH6fO0tZ5Z4P71HrH/ilszMafkbbGKlaDxi/fPKOZtPXIp4aXNZO2eEC+J1LRFhVtUdEWFW1R0dY/m+WrZ1maf3zWIKiYW1S0RUVbVLRFRVtUtEVFW1S0RUVbVLRFRVtUtEVFW/c072suXAdBxdyioi0q2qKiLSraoqItKtqioi0q2qKiLSraoqItKtp6OTe7+MJ1EFTMLY6aOOHMLSrmFhVtUdEWFW1R0RYVbVHRFhVtUdEWFW1R0RYVbVHRFhVtUdEWFW1R0RYVbVHRFhVtUdEWFW1R0RYVbVHRFhVtUdEWFW1R0RYVbVH5AHjEmOFjxF/CAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<PIL.Image.Image image mode=RGB size=201x251 at 0x7F66A1F50580>"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from image_multi_thresholding.utils import get_thresholded_image\n",
    "get_thresholded_image(image, th_dpc, COLORS)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b7975c71",
   "metadata": {},
   "source": [
    "### Differential Evolution Optimization \n",
    "\n",
    "Fix the following parameters: number of population $N$,  mutation scale factor $F\\in (0,1)$, crossover constant $C\\in [0,1]$, and  number of iterations $M$. Generate $N$ random possible solutions $t_i=t_{i,1}, \\dots ,t_{i,k-1}$ ($i=1, \\dots , N$), and register the best one $t^{\\text{best}}$. Repeat the following cycle $M$ times:\n",
    "<ol>\n",
    "<li>Apply mutation using two distinct random solutions $r_1\\ne r_2$, $t_i^{\\text{mutated}} = t^{\\text{best}} + F (t_{r_1}-t_{r_2})$.</li>\n",
    "<li>For a random uniform number $r$ and a random solution $j$, apply exponential crossover:\n",
    "$$t_i^{\\text{crossed}} = \\begin{cases}\n",
    "\tt_i^{\\text{mutated}} & \\text{if $r\\le C$ or $i=j$,}\\\\\n",
    "\tt_i & \\text{otherwise.}\n",
    "\t\\end{cases}$$</li>\n",
    "<li>Find new fitness function values and update solutions if this value is improved. If necessary, the best solution must also be updated.</li>\n",
    "</ol>\n",
    "Thus, optimal thresholds are equal to the global best solution among the $N$ ones obtained after the iteration process.\n",
    "\n",
    "\n",
    "**Reference:** Erik Cuevas, Daniel Zaldivar, and Marco Pérez-Cisneros. *A novel multi-threshold segmentation approach based on differential evolution optimization*. Expert Systems with Applications, 37(7):5265–5271, 2010.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "a25e10b4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[67, 168, 227]"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from image_multi_thresholding.threshold.deo import threshold_deo\n",
    "\n",
    "th_deo = threshold_deo(image, k=3)\n",
    "th_deo"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "2f52c094",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<PIL.Image.Image image mode=RGB size=201x251 at 0x7F66A1F505E0>"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from image_multi_thresholding.utils import get_thresholded_image\n",
    "get_thresholded_image(image, th_deo, COLORS)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1475822b",
   "metadata": {},
   "source": [
    "### Genetic Algorithm Approach\n",
    "\n",
    "Fix the following parameters: number of population $N$, $cr$ to represent the fraction of  crossover replacement, $mr$ to represent the  fraction of mutation replacement, and number of iterations $M$. Generate $N$ random possible chromosomes $t_i=t_{i,1}, \\dots ,t_{i,k-1}$ ($i=1, \\dots , N$). For crossover and mutation transformations, arguments must be converted to binary numbers and they will be denoted by $ch$. Repeat the following cycle $M$ times:\n",
    "<ol>\n",
    "\t<li>While number of new population is less than $N$, do the following:\n",
    "\t<ol>\n",
    "\t\t<li>Use roulette wheel selection to choose two chromosomes $ch_1$ and $ch_2$, conserving the number of desired thresholds to add to new population.</li>\n",
    "\t\t<li>Apply crossover for a random number $r_1 \\in [0,1]$\tand a random position $h$, if $r_1 < cr$ then: \n",
    "\t\t$$(ch_a^\\text{new})_i = \\begin{cases}\n",
    "\t\t(ch_a)_i & \\text{if $i<h$,} \\\\\n",
    "\t\t(ch_{\\sigma(a)})_i & \\text{if $i \\ge h$,} \\\\\n",
    "\t\t\\end{cases}$$\n",
    "        for $a=1,2$, $\\sigma(1)=2$, and $\\sigma(2)=1$.</li>\n",
    "\t\t<li>Apply mutation for a random number $ r_2 \\in [0,1]$ and a random position $h$, if $r_2 < mr$ then:\n",
    "\t\t$$(ch_a^\\text{new})_i = \\begin{cases}\n",
    "\t\t(ch_a)_i & \\text{if $i \\ne h$}, \\\\\n",
    "\t\t\\neg(ch_a)_h & \\text{if $i=h$}, \\\\\n",
    "\t\t\\end{cases}$$\n",
    "\t\tfor $a=1,2$, $\\neg 0=1$, and $\\neg 1=0$.</li>\n",
    "\t\t<li>Update new population according to fitness function $f$ as follows:\n",
    "\t\t<ul>\n",
    "\t\t\t<li>If $f(ch_1^\\text{new})> \\max\\{f(ch_1), f(ch_2)\\}$, then $ch_1^\\text{new}$ is added to new population.\n",
    "\t\t\t<li>If $f(ch_2^\\text{new})> \\max\\{f(ch_1), f(ch_2)\\}$, then $ch_2^\\text{new}$ is added to new population.\n",
    "        </ul></li>\n",
    "        </ol></li>\n",
    "</ol>\n",
    "\n",
    "Optimal thresholds are equal to the best global chromosome converted to decimal number among the $N$ ones obtained after the iteration process.\n",
    "\n",
    "\n",
    "**Reference:** Omar Banimelhem and Yahya Ahmed Yahya. *Multi-thresholding image segmentation using genetic algorithm*. In Proceedings of the International Conference on Image Processing, Computer Vision, and Pattern Recognition (IPCV), pages 1–1. The Steering Committee of The World Congress in Computer Science, Computer, 2011."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "a8e723dc",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[62, 133, 159]"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from image_multi_thresholding.threshold.gaa import threshold_gaa\n",
    "\n",
    "th_gaa = threshold_gaa(image, k=3)\n",
    "th_gaa"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "50fabfc1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<PIL.Image.Image image mode=RGB size=201x251 at 0x7F66A682F4C0>"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from image_multi_thresholding.utils import get_thresholded_image\n",
    "get_thresholded_image(image, th_gaa, COLORS)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dc6cc8a9",
   "metadata": {},
   "source": [
    "### Shuffled Frog Leaping Method\n",
    "\n",
    "Fix the following parameters:  number of memeplex $m$,  number of frogs in each memeplex $n$, total of replication in memeplex evolution $E$, and number of iterations $M$. In this case, $N=mn$ is the total number of population. Generate $N$ random possible frogs $t_i=t_{i,1}, \\dots ,t_{i,k-1}$ ($i=1, \\dots , N$), and register both the best frog $t^\\text{best}$ and the best fitness function value $f^{\\text{best}}$. Repeat the following cycle $M$ times:\n",
    "<ol>\n",
    "\t<li>For $h=1, \\dots , m$, distribute frogs in memeplex $Mem_h = \\{t_{(h-1)n+1}, \\dots ,  t_{hn}\\}$.</li>\n",
    "\t<li>Repeat the following internal evolution cycle $E$ times:\n",
    "\t<ol>\n",
    "\t\t<li>For each memeplex, find the best and the worst frogs $t_{Mem_h}^\\text{best}$ and $t_{Mem_h}^\\text{worst}$.\n",
    "\t\t<li>Consider random numbers $r_1,r_2 \\in [0,1]$, and generate a new frog $t_{Mem_h}^\\text{new} = t_{Mem_h}^\\text{worst} + r_1 (t_{Mem_h}^\\text{best}-t_{Mem_h}^\\text{worst})$.\n",
    "\t\t<li>Update the worst frog:\n",
    "\t\t$$\\begin{cases}\n",
    "\t\t& \\text{if $f(t_{Mem_h}^\\text{new})>f(t_{Mem_h}^\\text{worst})$: }  t_{Mem_h}^\\text{new worst}=t_{Mem_h}^\\text{worst}, \\\\\n",
    "\t\t& \\text{else if: }  t_{Mem_h}^\\text{new} = t_{Mem_h}^\\text{worst} + r_2 (t^\\text{best}-t_{Mem_h}^\\text{worst}), \\\\\n",
    "\t\t& \\hskip 1.1cm \\text{if $f(t_{Mem_h}^\\text{new})>f(t_{Mem_h}^\\text{worst})$:} \\\\\n",
    "\t\t& \\hskip 1.1cm t_{Mem_h}^\\text{new worst}=t_{Mem_h}^\\text{worst}, \\\\\n",
    "\t\t& \\hskip 1.1cm \\text{else if:}  \\\\\n",
    "\t\t& \\hskip 1.1cm t_{Mem_h}^\\text{new worst} \\text{ is a random generated frog.}\n",
    "\t\t\\end{cases}$$\n",
    "\t\t</ol></li>\n",
    "\t<li>Joint all frogs and update the best frog $t^\\text{best}$.</li>\n",
    "</ol>\n",
    "\n",
    "Optimal thresholds are equal to the best global frog among the $N$ ones obtained after the iteration process.\n",
    "\n",
    "\n",
    "**Reference:** M. H. Horng. *Multilevel image threshold selection based on the shuffled frog-leaping algorithm*. Journal of Chemical and Pharmaceutical Research, 5(9):599–605, 2013.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "d0fac3ed",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[101, 162, 218]"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from image_multi_thresholding.threshold.sfl import threshold_sfl\n",
    "\n",
    "th_sfl = threshold_sfl(image, k=3)\n",
    "th_sfl"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "33290a6d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAMkAAAD7CAIAAABPFif0AAAJJUlEQVR4nO3dS27cNgCHcbo10IMMkE2AHqA24IWBrnOBXqDoVXqOrAL4AlkYcPbZeGNg7tKFGpnhS6TEv0SR3w9FEY/H43l8Q1GPkW++f/lsAIFfjr4D6BZtQYW2oEJbUKEtqNAWVGgLKrQFFdqCCm1BhbagQltQoS2o0BZUaAsqtAUV2oIKbUGFtqBCW1ChLajQFlRoCyq0BRXaggptQYW2oEJbUKEtqNAWVGgLKrQFFdqCCm1BhbagQltQoS2o0BZUaAsqtAUV2oIKbUGFtqBCW1ChLajQFlRoCyq0BRXaggptQYW2oEJbUKEtqNAWVGgLKrQFlduj70AF16/fnEsuj3fThZfHuyPuEYwx5ub7l89H34fK/NRsc3b2JdV/O02bPsatIPvV9WOyL1lRQ6JOqpr1M26lh6uYOQX7xxUjWakOGj2mrevXb9Wfu8Tw43dT9Hov3ubilVfQtb6b5satYCLpFjPnT/4tr3v96s6o0o0GV1Oq/N4dNNeWLedVjF2nqJtEu7XGj+3jXP6zUXrLIk231bL5VfSHWP/CLbe/3VGRse20UZfHu4qL3Yql5tu6DSL29h1Zxacivawvolh/SrvdOA9YfXd7jbJ0O9kOD39eLai1ZpC53i3fdrr4Pst8I/aU4M5LqMSvy3+Hx24kcePRtkoffyOvfWvDoXN/1lW1pcXYPi7nQkXut/7vtu+B75BZYY4G75i/Z2ndz9a12xMVnW/l34MWRogGw2rEgc/MzZe//9l+K8G9chWtyFexTM+5zS3Lvs7UmcvP6zsV15kn1QfF7WtGmb+FvKqtJ9Zdnd5+U+r9fZl3YLfCGqy5zjLRkTh2KvOn9qc+Eqa1F34Hku1bTe0x3ajW8QiK/dyN6/a40xz574F1I3Etdt+Z24bUa1c5JMtE29nHrbNocGwbetzqybEja9Bwbe1/OEDd35s+bqwpw7V11DK61u890RyjWlsneszdaHCssh02bh21naLuMnH/wy4a78lWvJ6Yf3zEGUeyxVa2f/hs9V06neHmWwlbDolZvMHMzs5bkq9g3DrjOJRj55fzdAfGrZY7bvUX1lGvZX8NxUTb6i8m2zgv8IFG/HwiYe3j/3Gr71HKNkhYLeyrvqWqLh21a8vW/zaIvpNK7FU8/IH3fK6Rw5/cfRSdHmxPpx+3nMG/hed0Z80+5LO25Qz+h88t4AssE509Fcce/D53Ewuo2Xdty/b5UNB7W1s+LFr0qf917LYSe5SD51/g86i+HZ4T7fHyW06sbd/C4omcGvwkQuNiK5gVhzT5ZzGCnl7ePt1/CH7LXwrPY48/XCUuMRlvzZzz6g5Sp2IPurytp5e3dT84xWdH4wSU+cmqxBg24GcG0xJPyIrHq21rdVi+ObX0AJNeGjojWTDcTF22ZaoOYMK2prDmZV/FzmzBZav/u2KLYFNyVu1hrZiEXR7vVG2JStrOj4y2RMq2ncbm4NPlzfZks0fTnOmFv0KQs/aePhtjB73mfDqyzrjlNHeKyExGYab8PDzBLWodbxNJzM/Ous+niuktEVvTTK+BBjnrBPPoldi3cfbaEg9NMt86y7g1cxb06bMfprd9xMaqAbeZ0ZbL7iy93T8nkY6XhosK2rKLSazSO1ducI4/3fl5jmjP7oseY5Cz5SV4hfm7DZ5IsqLcthJ9LD6PrbVlkiUF762/ppIuL7FTK+fH+7DQViKL6+uzMeby8WH6Mv1UtszvzCy9YdJXyLxO96JtbWmizbEqLTaSpTfpzf82w5fk+6mt0wVRl79YdHJxyts+OevbzV+//3n0fWhLZiXB/hLTrNKb6sB7W9fX53nyNDh7AJvHJ9ELvy7HU3DHrWmGbqxJOoL2DOKkmyrcfT4k1aYz5lVtvjXmIrXXxVkV4X3VwSWjs0Er8VPpq/Wk12l4FeFxKzEILRY2uM4iK1oWOys9Qx9jo5C/fb+WxI7znDLS10l8a3qk9sJq8u+PS8rGLQatjToY1eakpgyc6ZOdWvEyEVUcO56tE6sqhu3yrWh5SAvuDFxsi/lWK3abqMU+g+4c6W/fH3su5M+L/I0J04WMW6e0vbzgFP7p5S04HfKHqFhn9oW0dWJbCrNnY4tH6RljLh8f/NErfMs/UqOtTmw5/iLI3xK+OMFyMN/qRPB4iloH5JVWNRnxbxf0ai7p6eVt+s+szSKmaMsUy0QExIoMbi+NXZ9xC67SoS52feZb+Ek6LP+7ievTFiQHG18+PtDW6GLHH8wbtIIWK7y+PjOXx7vg1tHgLh2TkRfjlkTws9om9BHIdhRN4dOHjk5XYD2xsk/3H+aAnI2Z9pctH/UQkxOf3RzLRLxzdlT7U7Gig0NZJq63uIA73Xk6F6NJHCLhf4u2KgieW+WMSz1HzviUuA5trWfvHo5N3k8xXIkwl6/JWQiOHJZh3Kpi8IZiGLcqOPvGBRHGrSzpw+5i/x4cbYWVnuENPtpasP9n8LvBdnmoMJeHCm1BhbagQltQoS2o0BZUaAsqtAUV2oIKbUGFtqBCW1ChLajQFlRoCyocG4j6pg/E0hbq8M8WQVtYI+e8I7SFAkXnUdo0l7c/sc6HFLp0fX3+dP/h+vo8/Vf0s9HPYjgnOEickiV4pg3+St7ZbT8x/c0fv/5mf50+Y/h8Hef0QMG8jtXgXWqcc77J+m3lY1jqQ90/nGFbP5cPnmPOrG2u1iP0/6oR7wHbns/M+nFrneDf2jvkVw9lPpfknk/43m0dbpDC9mwoZri2Zh1H1kJYZuR91eu22TTIfghNPZxx25o19Xosmu6t/X/Tal7s8zEm768v72nFlud2kpqNO98qsvgnRuxrOptjgl+m07HbajCaTLR1pJ03CuyMtqDCXB4qtAUV2oIKbUGFtqBCW1ChLajQFlRoCyq0BRXaggptQYW2oEJbUKEtqNAWVGgLKrQFFdqCCm1BhbagQltQoS2o0BZUaAsqtAUV2oIKbUGFtqBCW1ChLajQFlRoCyq0BRXaggptQYW2oEJbUKEtqNAWVGgLKrQFFdqCCm1BhbagQltQoS2o0BZUaAsqtAUV2oIKbUGFtqBCW1ChLajQFlRoCyq0BRXaggptQYW2oEJbUKEtqNAWVGgLKrQFFdqCCm1B5T8cDwviR6CwrgAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<PIL.Image.Image image mode=RGB size=201x251 at 0x7F66A682F340>"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from image_multi_thresholding.utils import get_thresholded_image\n",
    "get_thresholded_image(image, th_sfl, COLORS)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "af34db16",
   "metadata": {},
   "source": [
    "### Particle Swarm Optimization \n",
    "\n",
    "Fix the following parameters: number of population $N$, initial and final inertia $\\omega^I$ and $\\omega^F$, initial acceleration constants $c^I_1$ and $c^I_2$,  final acceleration constants $c^F_1$ and $c^F_2$, and number of iterations $M$.\n",
    "Generate $N$ random possible particle positions $t_i=t_{i,1}, \\dots ,t_{i,k-1}$ ($i=1, \\dots , N$), and register the best global particle position $t^\\text{best}$. Initialize particle velocities $v_i$ as null vector and the best particle positions $t_i^\\text{best}=t_i$. For $h=1, \\dots , M$ repeat the following cycle:\n",
    "<ol>\n",
    "\t<li>Update inertia $\\omega = (\\omega^I-\\omega^F)(M-h)/M+\\omega^F$, and accelerations $c_a = c_a^h+(c_a^F-c_a^I)h/M$, for $a=1,2$.</li>\n",
    "\t<li>Update velocities for random numbers $ r_1,r_2 \\in [0,1]$, $v_i^\\text{new} = \\omega v_i + c_1 r_1(t_i^\\text{best}-t_i) + c_2 r_2(t^\\text{best}-t_i)$.</li>\n",
    "\t<li>Update particle positions preserving range of solutions, $t_i^\\text{new} = t_i + v_i^\\text{new}$.</li>\n",
    "\t<li>Update the best particle positions $t_i^\\text{new best} = t_i^\\text{new}$, if $f(t_i^\\text{new})>f(t_i^\\text{best})$.</li>\n",
    "\t<li>If necessary, update the best global particle position $t^\\text{best}$.</li>\n",
    "</ol>\n",
    "\n",
    "Optimal thresholds are equal to the best global particle position among the $N$ ones obtained after the iteration process.\n",
    "\n",
    "\n",
    "**Reference:** Fayçal Hamdaoui, Anis Sakly, and Abdellatif Mtibaa. *An efficient multithresholding method for image segmentation based on PSO*. In International Conference on Control, Engineering & Information Technology (CEIT’14), pages 203–213, 2014.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "fd946a65",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 68, 168, 226])"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from image_multi_thresholding.threshold.pso import threshold_pso\n",
    "\n",
    "th_pso = threshold_pso(image, k=3)\n",
    "th_pso"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "fdbf923a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<PIL.Image.Image image mode=RGB size=201x251 at 0x7F6709FCD1F0>"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from image_multi_thresholding.utils import get_thresholded_image\n",
    "get_thresholded_image(image, th_pso, COLORS)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f23542d0",
   "metadata": {},
   "source": [
    "### State Transition Algorithm\n",
    "\n",
    "Fix the following parameters: search enforcement $N$,  maximum and minimum values for rotation factor $\\alpha_{\\max}>0$ and $\\alpha_{\\min}>0$ respectively, translation factor  $\\beta>0$,  expansion factor $\\gamma>0$,  axesion factor $\\delta>0$, lessening coefficient $c>0$, and  number of iterations $M$. Generate $N$ random possible states $t_i=t_{i,1}, \\dots ,t_{i,k-1}$ ($i=1, \\dots , N$). Repeat the following cycle $M$ times:\n",
    "<ol>\n",
    "\t<li>Generate a random number $\\alpha \\in [0,1]$ and, if $\\alpha < \\alpha_{\\min}$, then use $\\alpha=\\alpha_{\\max}$.</li>\n",
    "\t<li>Apply expansion transformation using a random diagonal matrix $E \\in \\mathbb{R}^{(k-1) \\times (k-1)}$ with elements obeying the Gaussian distribution, $t_i^\\text{expanded} = t_i + \\gamma E t_i'$, where $x'$ denotes the transpose of $x$.</li>\n",
    "\t<li>Using fitness function $f$, and if $f(t_i^\\text{expanded})>f(t_i)$, then do the following:\n",
    "\t<ol>\n",
    "\t\t<li>Update state $t_i^\\text{new} = t_i^\\text{expanded}$.</li>\n",
    "\t\t<li>Apply translation transformation for a random number $T \\in [0,1]$, $t_i^\\text{translated} = t_i^\\text{new} + \\beta T (t_i^\\text{new}-t_i)/\\lVert t_i^\\text{new}-t_i \\lVert_2$, where $\\lVert v \\lVert_2$ indicates the 2-norm of the vector $v$.</li>\n",
    "\t\t<li>If $f(t_i^\\text{translated})>f(t_i^\\text{new})$, update state $t_i^\\text{final new} = t_i^\\text{translated}$.</li>\n",
    "\t</ol></li>\n",
    "\t<li>Apply rotation transformation to the $t_i$ obtained after the modifications in the previous step, using a random matrix $R \\in \\mathbb{R}^{(k-1) \\times (k-1)}$ with elements in $[-1,1]$, $t_i^\\text{rotated} = t_i + \\alpha R t_i'/[(k-1) \\lVert t_i \\lVert_2]$.</li>\n",
    "\t<li>Using fitness function $f$, and if $f(t_i^\\text{rotated})>f(t_i)$, then update state $t_i^\\text{new} = t_i^\\text{rotated}$, and follow analogous steps to (b) and (c).</li>\n",
    "\t<li>Using a diagonal random matrix $A \\in \\mathbb{R}^{(k-1) \\times (k-1)}$ with elements obeying the Gaussian distribution and only one random position having non-zero value, apply axesion transformation to the $t_i$ modified in the step above, $t_i^\\text{axeded} = t_i + \\delta A t_i'$.</li>\n",
    "\t<li>Using fitness function $f$, and if $f(t_i^\\text{axeded})>f(t_i)$, update state $t_i^\\text{new} = t_i^\\text{axeded}$, and follow analogous steps to (b) and (c). </li>\n",
    "\t<li>Update rotation factor $\\alpha^\\text{new} = \\alpha/c$.</li>\n",
    "</ol>\n",
    "\n",
    "Optimal thresholds are equal to the best global state among the $N$ ones obtained after the iteration process.\n",
    "\n",
    "\n",
    "**Reference:** Jie Han, Chunhua Yang, Xiaojun Zhou, and Weihua Gui. *A new multi-threshold image segmentation approach using state transition algorithm*. Applied Mathematical Modelling, 44:588–601, 2017.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "99c5c205",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 84, 172, 230])"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from image_multi_thresholding.threshold.sta import threshold_sta\n",
    "\n",
    "th_sta = threshold_sta(image, k=3)\n",
    "th_sta"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "f35520a1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<PIL.Image.Image image mode=RGB size=201x251 at 0x7F66A2498190>"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from image_multi_thresholding.utils import get_thresholded_image\n",
    "get_thresholded_image(image, th_sta, COLORS)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fefac581",
   "metadata": {},
   "source": [
    "### Histogram Sampling Technique\n",
    "\n",
    "Let $A$ be the set of gray levels at which local minimum is reached using discrete gradient descent. If $r$ is a non-trivial divisor of $L$, histogram can be partitioned in $r$ regions of equal size. Let $B$ be the set of all minimum points in the histogram for each partition. Intersection $A\\cap B$ can be grouped in subsets $(A\\cap B)_j$ for $j=1, \\dots , k-1$, with the same number of elements with possible exception for the last one. Optimal thresholds are $t_j = \\textrm{mean} (A\\cap B)_j$.\n",
    "\n",
    "\n",
    "**Reference:** Amit Gurung and Sangyal Lama Tamang. *Image segmentation using multi-threshold technique by histogram sampling*. arXiv Preprint arXiv:1909.05084, 2019."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "77c72648",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[65, 181]"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from image_multi_thresholding.threshold.hst import threshold_hst\n",
    "\n",
    "th_hst = threshold_hst(image, k=2)\n",
    "th_hst"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "ee07fc72",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<PIL.Image.Image image mode=RGB size=201x251 at 0x7F66A19F07F0>"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from image_multi_thresholding.utils import get_thresholded_image\n",
    "get_thresholded_image(image, th_hst, COLORS)"
   ]
  }
 ],
 "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.8.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}