diff --git a/Gaussian Discriminant Analysis/GDA.ipynb b/Gaussian Discriminant Analysis/GDA.ipynb new file mode 100644 index 0000000..496ee7d --- /dev/null +++ b/Gaussian Discriminant Analysis/GDA.ipynb @@ -0,0 +1,776 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "name": "ML Exercise 3 Kavish and the Flow.ipynb", + "version": "0.3.2", + "provenance": [], + "collapsed_sections": [], + "toc_visible": true + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + } + }, + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "X-lotbAklSkS", + "colab_type": "text" + }, + "source": [ + "## **Gaussian Discriminant Analysis - ML Exercise 3 - Kavish and Florian**" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "b55YVPSYbodP", + "colab_type": "code", + "colab": {} + }, + "source": [ + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "from PIL import Image, ImageFilter\n", + "import imageio" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "RCjvSSC1fp1K", + "colab_type": "code", + "outputId": "b99ff229-6978-4843-9a59-02ca23429bc1", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 134 + } + }, + "source": [ + "!git clone https://github.com/KavishBhatia/MachineLearning.git" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Cloning into 'MachineLearning'...\n", + "remote: Enumerating objects: 55, done.\u001b[K\n", + "remote: Counting objects: 100% (55/55), done.\u001b[K\n", + "remote: Compressing objects: 100% (54/54), done.\u001b[K\n", + "remote: Total 142 (delta 22), reused 0 (delta 0), pack-reused 87\u001b[K\n", + "Receiving objects: 100% (142/142), 622.83 KiB | 11.12 MiB/s, done.\n", + "Resolving deltas: 100% (26/26), done.\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "5n-o74jBZS8Q", + "colab_type": "text" + }, + "source": [ + "Compute the feature probability distributions for the positive(p) and negative(n) group.\n", + "Features:\n", + " 1. Mean of all (R)GB values\n", + " 2. Mean of all R(G)B values\n", + " 3. Mean of all RG(B) values\n", + " 4. Lowest(darkest) cumulative RBG value of 2x2 Filter\n", + " 5. Mean of all RGB (all 3) values\n", + " \n", + "Plot distributions for p and n and check if they are differentiable.\n", + "\n", + "Sum up relative probability for an image to be in p or n according to all feature probabilities.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "-E3sNCl8P3JF", + "colab_type": "text" + }, + "source": [ + "Get paths of all the negative and positive images\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "d2JQbe4vemJA", + "colab_type": "code", + "colab": {} + }, + "source": [ + "category = [\"positives\", \"negatives\"]\n", + "ml = \"MachineLearning/\"\n", + "\n", + "def getPositiveImages():\n", + " image_path = []\n", + " for i in range(1,31):\n", + " if i < 10:\n", + " img_name = \"/p0\" + str(i)\n", + " else:\n", + " img_name = \"/p\" +str(i) \n", + " path = ml + category[0] + img_name + \".png\"\n", + " image_path.append(path)\n", + " return image_path \n", + "\n", + "def getNegativeImages():\n", + " image_path = []\n", + " for i in range(1,31):\n", + " if i < 10:\n", + " img_name = \"/n0\" + str(i)\n", + " else:\n", + " img_name = \"/n\" +str(i) \n", + " path = ml + category[1] + img_name + \".png\"\n", + " image_path.append(path)\n", + " return image_path\n", + " \n", + " " + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "8MzA3AXmQAP4", + "colab_type": "text" + }, + "source": [ + "Getting all positive and negative images" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "oAG-As6ssAKi", + "colab_type": "code", + "colab": {} + }, + "source": [ + " picturePathListPositive = getPositiveImages()\n", + " picturePathListNegative = getNegativeImages()" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "o7gOaD8OQQMS", + "colab_type": "text" + }, + "source": [ + "function to get pixels of an image" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "L7exlKujo2Re", + "colab_type": "code", + "colab": {} + }, + "source": [ + "def getPixelValues(imagepath):\n", + " im = imageio.imread(imagepath)\n", + " return im" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "1kppoUSUQVqR", + "colab_type": "text" + }, + "source": [ + "function to compute Means for a single color in the image and for all the pixel values" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "_w0kgQQihAfA", + "colab_type": "code", + "colab": {} + }, + "source": [ + "def computeMeanForAllColours(imagepath):\n", + " pixValues = getPixelValues(imagepath)\n", + " meanPixValues = np.mean(pixValues)\n", + " return meanPixValues\n", + "\n", + "def computeMeanSingleColour(colour, imagepath):\n", + " pixValues = getPixelValues(imagepath)\n", + " meanPixValues = np.mean(pixValues[:,:,colour])\n", + " return meanPixValues" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "faeMgfzQxtCy", + "colab_type": "code", + "colab": {} + }, + "source": [ + "red = 0\n", + "green = 1\n", + "blue = 2\n", + "m = 60 # total number of pos and neg images\n", + "n = 5 #no of features" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Va9jCjUAQgzn", + "colab_type": "text" + }, + "source": [ + "function to calculate mean of the image after converting to edges" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "KF_Si3QJmyj6", + "colab_type": "code", + "colab": {} + }, + "source": [ + "def calcMeanEdges(imagepath):\n", + " image = Image.open(imagepath)\n", + " return np.mean(image.filter(ImageFilter.FIND_EDGES))" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "P9gImej6QwcW", + "colab_type": "text" + }, + "source": [ + "function to plot histograms for all the features" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "sifVnAHDk-tU", + "colab_type": "code", + "colab": {} + }, + "source": [ + "def meanAllValues():\n", + " \n", + " listOfPosMeans = []\n", + " listOfNegMeans = []\n", + " listOfPosRedMeans = [] # pos red means\n", + " listOfPosGreenMeans = [] # pos green means\n", + " listOfPosBlueMeans = [] # pos blue means\n", + " listOfNegRedMeans = [] # neg red means\n", + " listOfNegGreenMeans = [] # neg green means\n", + " listOfNegBlueMeans = [] # neg blue means\n", + " listOfPosFilterMeans = [] # Filter means\n", + " listOfNegFilterMeans = [] # Filter means\n", + " \n", + " NegEdges = []\n", + " PosEdges = []\n", + " \n", + " for i in picturePathListPositive:\n", + " listOfPosMeans.append(computeMeanForAllColours(i))\n", + " listOfPosRedMeans.append(computeMeanSingleColour(red,i))\n", + " listOfPosGreenMeans.append(computeMeanSingleColour(green,i))\n", + " listOfPosBlueMeans.append(computeMeanSingleColour(blue,i))\n", + " listOfPosFilterMeans.append(filterMaxMean(i))\n", + " \n", + " PosEdges.append(calcMeanEdges(i))\n", + " \n", + " for i in picturePathListNegative:\n", + " listOfNegMeans.append(computeMeanForAllColours(i))\n", + " listOfNegRedMeans.append(computeMeanSingleColour(red,i))\n", + " listOfNegGreenMeans.append(computeMeanSingleColour(green,i))\n", + " listOfNegBlueMeans.append(computeMeanSingleColour(blue,i))\n", + " listOfNegFilterMeans.append(filterMaxMean(i))\n", + " \n", + " NegEdges.append(calcMeanEdges(i))\n", + " \n", + " bins = np.linspace(15, 60, 10)\n", + " plt.hist(PosEdges, bins, alpha=0.5, label='positive edges')\n", + " plt.hist(NegEdges, bins, alpha=0.5, label='negative edges')\n", + " plt.legend()\n", + " plt.show()\n", + " \n", + " \n", + "\n", + " bins = np.linspace(100, 200, 25)\n", + " plt.hist(listOfPosMeans, bins, alpha=0.5, label='positive mean all colours')\n", + " plt.hist(listOfNegMeans, bins, alpha=0.5, label='negative mean all colours')\n", + " plt.legend()\n", + " plt.show()\n", + "\n", + " bins = np.linspace(100, 200, 25)\n", + " plt.hist(listOfPosRedMeans, bins, alpha=0.5, label='positive red mean')\n", + " plt.hist(listOfNegRedMeans, bins, alpha=0.5, label='negative red mean')\n", + " plt.legend()\n", + " plt.show()\n", + " \n", + " bins = np.linspace(100, 200, 25)\n", + " plt.hist(listOfPosGreenMeans, bins, alpha=0.5, label='positive green mean')\n", + " plt.hist(listOfNegGreenMeans, bins, alpha=0.5, label='negative green mean')\n", + " plt.legend()\n", + " plt.show()\n", + "\n", + " bins = np.linspace(100, 200, 25)\n", + " plt.hist(listOfPosBlueMeans, bins, alpha=0.5, label='positive blue mean')\n", + " plt.hist(listOfNegBlueMeans, bins, alpha=0.5, label='negative blue mean')\n", + " plt.legend()\n", + " plt.show()\n", + " \n", + " bins = np.linspace(100, 200, 25)\n", + " plt.hist(listOfPosFilterMeans, bins, alpha=0.5, label='positive filter')\n", + " plt.hist(listOfNegFilterMeans, bins, alpha=0.5, label='negative filter')\n", + " plt.legend()\n", + " plt.show()" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "DeEo5CzImtHy", + "colab_type": "text" + }, + "source": [ + "function to get the Maximum or the darkest spot in the image from a 2x2 filter" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "7ctrYeScnu0G", + "colab_type": "code", + "colab": {} + }, + "source": [ + "def filterMaxMean(image):\n", + " img = Image.open(image)\n", + " members = [(0,0)] * 4\n", + " filteredMeanMax = 255\n", + " for i in range(1,23):\n", + " for j in range(1,23):\n", + " members[0] = img.getpixel((i-1,j-1))\n", + " members[1] = img.getpixel((i-1,j))\n", + " members[2] = img.getpixel((i-1,j+1))\n", + " members[3] = img.getpixel((i,j-1))\n", + " tempFilteredMeanMax = np.mean(members)\n", + " if tempFilteredMeanMax < filteredMeanMax:\n", + " filteredMeanMax = tempFilteredMeanMax\n", + " return (filteredMeanMax - 255)*(-1)\n" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "Kg2f12R7xN2B", + "colab_type": "code", + "outputId": "2c160d97-2c24-4540-ce65-e7570705c34a", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 1529 + } + }, + "source": [ + "meanAllValues()" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "display_data", + "data": { + "image/png": "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\n3twVEQmMgl9EJDBHHeoxsynAVcAWd+8Qlc0C2kRVMoAd7p5Tzb7FwC7gAFBe2zceRETk2KnNGP9U\n4Bng14cK3H3goWUz+wWw8wj7X+run9a1gyIiklxHDX53X2xmravbZrGP210PXJbcbolIvUn2bb8N\n4PbdHTt2MH36dO644w4APv74Y+666y7y8/Prpf1HHnmEpk2b1tuka19WomP8FwGfuPv6GrY7MN/M\nCs1sRIJtiYjUyo4dO5g4cWJ8/ayzzqq30D8eJBr8g4HDJ5/4Qi937wpcAYwys941VTSzEWZWYGYF\nW7duTbBbItJQFRcX065dO2699Vbat29PXl4e+/btA2Djxo3069ePCy64gIsuuoj3338/Xt6jRw86\nduzIgw8+SNOmTQHYvXs3l19+OV27dqVjx4689tprQGyq440bN5KTk8OYMWMoLi6mQ4cOQGz6hNWr\nV8f7c2gK5z179jB8+HC6d+9Oly5d4seq6vHHH6dbt2506tSJhx9+OF4+btw4zj//fHr16sW6devi\n5cuWLaNTp07xvhzqx4EDBxgzZkz8WM899xwApaWl9O7dm5ycHDp06MCbb76ZlPNeUZ2D38waA/8H\nmFVTHXffHP3cAswBuh+h7vPunuvuuZmZmXXtlogcB9avX8+oUaPic9+88sorAIwYMYLx48dTWFjI\nE088ER+qGT16NKNHj2blypW0bNkyfpz09HTmzJnD8uXLWbRoEffeey/uzmOPPcY3v/lNioqKePzx\nxyu1PXDgwPh8OqWlpZSWlpKbm8u4ceO47LLLWLp0KYsWLWLMmDHs2bOn0r7z589n/fr1LF26lKKi\nIgoLC1m8eDGFhYXMnDmToqIi5s2bx7Jly+L73HTTTTz33HPx6Z8PmTx5Ms2bN2fZsmUsW7aMX/3q\nV/zjH/9g+vTp9O3bl6KiIt577z1ycg67byZhiXyA69vA++5eUt1GMzsZOMHdd0XLecBPE2hPRL4i\nsrKy4oF2wQUXUFxczO7du/nb3/7GddddF693aF6bt99+m7lz5wLwve99Lz527u488MADLF68mBNO\nOIHNmzfzySefHLHt66+/nry8PH7yk58we/ZsBgwYAMRC/fXXX+eJJ54AYP/+/Xz00UeVpkaYP38+\n8+fPp0uXLkDsL47169eza9cu+vfvH59W+eqrrwZiQ067du3iwgsvjPf997//ffxYK1asiA9B7dy5\nk/Xr19OtWzeGDx9OWVkZ1157bWqC38xmAJcAp5lZCfCwu08GBlFlmMfMzgJecPcrgTOAOdF0q42B\n6e7+x+R2X0SOR1/72tfiy40aNWLfvn0cPHiQjIwMioqKan2cadOmsXXrVgoLC0lLS6N169bs37//\niPucffbZtGjRghUrVjBr1iwmTZoExH6JvPLKK7Rp06bGfd2d+++/n9tuu61S+dNPP13rPlc81vjx\n4+nbt+9h2xYvXswbb7zBsGHDuOeee7jxxhu/9PGP5KhDPe4+2N3PdPc0d28ZhT7uPszdJ1Wp+3EU\n+rj7h+7eOXq0d/dxSe25iHylnHLKKWRlZfHb3/4WiAXjoWmKe/ToER8OmjlzZnyfnTt3cvrpp5OW\nlsaiRYviUysfaZpmiA33/PznP2fnzp3xL0vp27cv48eP59DElX//+98P269v375MmTIl/rWJmzdv\nZsuWLfTu3Zu5c+eyb98+du3axe9+9zsAMjIyaNasGe++++5hfe/bty/PPvssZWVlAHzwwQfs2bOH\nTZs2ccYZZ3Drrbdyyy23sHz58i97Ko9Kc/WIhK4B3H55yLRp07j99tsZO3YsZWVlDBo0iM6dO/P0\n009zww03MG7cOPr160fz5s0BGDJkCN/5znfo2LEjubm5tG3bFoAWLVrQs2dPOnTowBVXXMGoUaMq\ntTNgwABGjx7NQw89FC976KGHuPvuu+nUqRMHDx4kKysrPixzSF5eHmvXro0P3TRt2pSXX36Zrl27\nMnDgQDp37szpp59Ot27d4vtMnjyZW2+9lRNOOIGLL7443vdbbrmF4uJiunbtiruTmZnJ3Llz+etf\n/8rjjz9OWloaTZs25de//jXJpmmZv8o0LXMlTy34INVdAFIz/31FqZ6WuS727t3LiSeeiJkxc+ZM\nZsyYUeNdNw3N7t2743chPfbYY5SWlvLLX/4yoWNqWmYR+corLCzkzjvvxN3JyMhgypQpqe5Srb3x\nxhs8+uijlJeXc+655zJ16tRUd0nBLyIN30UXXVRvX0uYbAMHDmTgwIFHr1iPNDunSIAa4hCv1E4y\n/u0U/CKBSU9PZ9u2bQr/45C7s23bNtLT0xM6joZ6RALTsmVLSkpK0NQox6f09PRKn16uCwW/SGDS\n0tLIyspKdTckhTTUIyISGAW/iEhgFPwiIoFR8IuIBEbBLyISGAW/iEhgFPwiIoFR8IuIBEbBLyIS\nGAW/iEhgFPwiIoE5avCb2RQz22JmqyqUPWJmm82sKHpcWcO+/cxsnZltMLP7ktlxERGpm9pc8U8F\n+lVT/pS750SPeVU3mlkjYAJwBZANDDaz7EQ6KyIiiTtq8Lv7YmB7HY7dHdjg7h+6+3+AmcA1dTiO\niIgkUSJj/Hea2YpoKOjUarafDfyzwnpJVFYtMxthZgVmVqB5wkVEjp26Bv+zwDeBHKAU+EWiHXH3\n5909191zMzMzEz2ciIjUoE7B7+6fuPsBdz8I/IrYsE5Vm4FzKqy3jMpERCSF6hT8ZnZmhdX+wKpq\nqi0DzjOzLDNrAgwCXq9LeyIikjxH/epFM5sBXAKcZmYlwMPAJWaWAzhQDNwW1T0LeMHdr3T3cjO7\nE/gT0AiY4u6rj8mzEBGRWjtq8Lv74GqKJ9dQ92Pgygrr84DDbvUUEZHU0Sd3RUQCo+AXEQmMgl9E\nJDAKfhGRwCj4RUQCo+AXEQmMgl9EJDAKfhGRwCj4RUQCo+AXEQmMgl9EJDAKfhGRwCj4RUQCo+AX\nEQmMgl9EJDAKfhGRwCj4RUQCo+AXEQnMUYPfzKaY2RYzW1Wh7HEze9/MVpjZHDPLqGHfYjNbaWZF\nZlaQzI6LiEjd1OaKfyrQr0rZAqCDu3cCPgDuP8L+l7p7jrvn1q2LIiKSTEcNfndfDGyvUjbf3cuj\n1XeAlsegbyIicgwkY4x/OPCHGrY5MN/MCs1sRBLaEhGRBDVOZGcz+xFQDkyroUovd99sZqcDC8zs\n/egviOqONQIYAdCqVatEuiUiIkdQ5yt+MxsGXAUMcXevro67b45+bgHmAN1rOp67P+/uue6em5mZ\nWdduiYjIUdQp+M2sH/A/wNXuvreGOiebWbNDy0AesKq6uiIiUn9qczvnDOBtoI2ZlZjZzcAzQDNi\nwzdFZjYpqnuWmc2Ldj0DWGJm7wFLgTfc/Y/H5FmIiEitHXWM390HV1M8uYa6HwNXRssfAp0T6p2I\niCRdQm/uisiX99SCD1LdBQD+u8/5qe6CpIimbBARCYyCX0QkMAp+EZHAKPhFRAKj4BcRCYyCX0Qk\nMAp+EZHAKPhFRAKj4BcRCYyCX0QkMAp+EZHAKPhFRAKj4BcRCYyCX0QkMAp+EZHAKPhFRAKj4BcR\nCUytgt/MppjZFjNbVaHs62a2wMzWRz9PrWHfoVGd9WY2NFkdFxGRuqntFf9UoF+VsvuAhe5+HrAw\nWq/EzL4OPAx8C+gOPFzTLwgREakftQp+d18MbK9SfA3wUrT8EnBtNbv2BRa4+3Z3/zewgMN/gYiI\nSD1KZIz/DHcvjZb/BZxRTZ2zgX9WWC+JykREJEUaJ+Mg7u5m5okcw8xGACMAWrVqlYxuSUOx6NFU\n9yDy3VR3QKRBSOSK/xMzOxMg+rmlmjqbgXMqrLeMyg7j7s+7e66752ZmZibQLREROZJEgv914NBd\nOkOB16qp8ycgz8xOjd7UzYvKREQkRWp7O+cM4G2gjZmVmNnNwGNAHzNbD3w7WsfMcs3sBQB33w78\nDFgWPX4alYmISIrUaozf3QfXsOnyauoWALdUWJ8CTKlT70REJOn0yV0RkcAo+EVEAqPgFxEJjIJf\nRCQwCn4RkcAo+EVEAqPgFxEJjIJfRCQwCn4RkcAo+EVEAqPgFxEJjIJfRCQwCn4RkcAo+EVEAqPg\nFxEJjIJfRCQwCn4RkcAo+EVEAlPn4DezNmZWVOHxmZndXaXOJWa2s0KdHyfeZRERSUStvnO3Ou6+\nDsgBMLNGwGZgTjVV33T3q+rajoiIJFeyhnouBza6+6YkHU9ERI6RZAX/IGBGDdsuNLP3zOwPZtY+\nSe2JiEgdJRz8ZtYEuBr4bTWblwPnuntnYDww9wjHGWFmBWZWsHXr1kS7JSIiNUjGFf8VwHJ3/6Tq\nBnf/zN13R8vzgDQzO626g7j78+6e6+65mZmZSeiWiIhUJxnBP5gahnnM7L/MzKLl7lF725LQpoiI\n1FGd7+oBMLOTgT7AbRXKRgK4+yRgAHC7mZUD+4BB7u6JtCkiIolJKPjdfQ/QokrZpArLzwDPJNKG\niIgklz65KyISGAW/iEhgFPwiIoFR8IuIBEbBLyISGAW/iEhgFPwiIoFR8IuIBEbBLyISGAW/iEhg\nFPwiIoFR8IuIBEbBLyISGAW/iEhgFPwiIoFR8IuIBEbBLyISGAW/iEhgFPwiIoFJOPjNrNjMVppZ\nkZkVVLPdzOz/mdkGM1thZl0TbVNEROouoS9br+BSd/+0hm1XAOdFj28Bz0Y/RUQkBepjqOca4Nce\n8w6QYWZn1kO7IiJSjWQEvwPzzazQzEZUs/1s4J8V1kuiskrMbISZFZhZwdatW5PQLRERqU4ygr+X\nu3clNqQzysx61+Ug7v68u+e6e25mZmYSuiUiItVJOPjdfXP0cwswB+hepcpm4JwK6y2jMhERSYGE\ngt/MTjazZoeWgTxgVZVqrwM3Rnf39AB2untpIu2KiEjdJXpXzxnAHDM7dKzp7v5HMxsJ4O6TgHnA\nlcAGYC9wU4JtiohIAhIKfnf/EOhcTfmkCssOjEqkHRERSR59cldEJDAKfhGRwCj4RUQCo+AXEQmM\ngl9EJDAKfhGRwCj4RUQCo+AXEQmMgl9EJDAKfhGRwCj4RUQCo+AXEQmMgl9EJDAKfhGRwCj4RUQC\no+AXEQmMgl9EJDAKfhGRwNQ5+M3sHDNbZGZrzGy1mY2ups4lZrbTzIqix48T666IiCQqke/cLQfu\ndfflZtYMKDSzBe6+pkq9N939qgTaERGRJKrzFb+7l7r78mh5F7AWODtZHRMRkWMjKWP8ZtYa6AK8\nW83mC83sPTP7g5m1T0Z7IiJSd4kM9QBgZk2BV4C73f2zKpuXA+e6+24zuxKYC5xXw3FGACMAWrVq\nlWi3RESkBgld8ZtZGrHQn+bur1bd7u6fufvuaHkekGZmp1V3LHd/3t1z3T03MzMzkW6JiMgRJHJX\njwGTgbXu/mQNdf4rqoeZdY/a21bXNkVEJHGJDPX0BL4PrDSzoqjsAaAVgLtPAgYAt5tZObAPGOTu\nnkCbIiKSoDoHv7svAewodZ4BnqlrGyIiknz65K6ISGAU/CIigVHwi4gERsEvIhIYBb+ISGAU/CIi\ngVHwi4gERsEvIhIYBb+ISGAU/CIigVHwi4gEJuH5+KUGix5NdQ8ajLc/bCATsuprHkQAXfGLiARH\nwS8iEhgFv4hIYBT8IiKBUfCLiARGwS8iEpiEgt/M+pnZOjPbYGb3VbP9a2Y2K9r+rpm1TqQ9ERFJ\nXJ2D38waAROAK4BsYLCZZVepdjPwb3f/X8BTwP+ta3siIpIciVzxdwc2uPuH7v4fYCZwTZU61wAv\nRcv5wOVmdsQvaBcRkWMrkeA/G/hnhfWSqKzaOu5eDuwEWiTQpoiIJKjBTNlgZiOAEdHqbjNbl8r+\nJMFpwKep7kQD0UDOxS9S3YFDGsT5uCfVHfhCgzgfDUQi5+Lc2lZMJPg3A+dUWG8ZlVVXp8TMGgPN\ngWonbnH354HnE+hPg2JmBe6em+p+NAQ6F5XpfFSm8/GF+joXiQz1LAPOM7MsM2sCDAJer1LndWBo\ntDwA+Iu7ewJtiohIgup8xe/u5WZ2J/AnoBEwxd1Xm9lPgQJ3fx2YDPzGzDYA24n9chARkRRKaIzf\n3ecB86qU/bjC8n7gukTaOI59ZYatkkDnojKdj8p0Pr5QL+fCNPIiIhIWTdkgIhIYBX+CzOwcM1tk\nZmvMbLWZjY7Kv25mC8xsffTz1FT3tT6YWbqZLTWz96Lz8ZOoPCuatmNDNI1Hk1T3tb6YWSMz+7uZ\n/T5aD/lcFJvZSjMrMrOCqCzI1wqAmWWYWb6ZvW9ma83swvo4Hwr+xJUD97p7NtADGBVNXXEfsNDd\nzwMWRush+By4zN07AzlAPzPrQWy6jqei6Tv+TWw6j1CMBtZWWA/5XABc6u45FW5bDPW1AvBL4I/u\n3hboTOz/yTE/Hwr+BLl7qbsvj5Z3EfuHO5vK01W8BFybmh7WL4/ZHa2mRQ8HLiM2bQcEdD7MrCXw\nv4EXonUj0HNxBEG+VsysOdCb2N2PuPt/3H0H9XA+FPxJFM0+2gV4FzjD3UujTf8CzkhRt+pdNLRR\nBGwBFgAbgR3RtB1Q/fQeX1VPA/8DHIzWWxDuuYDYRcB8MyuMPq0P4b5WsoCtwIvRUOALZnYy9XA+\nFPxJYmZNgVeAu939s4rbog+tBXP7lLsfcPccYp/m7g60TXGXUsLMrgK2uHthqvvSgPRy967EZvUd\nZWa9K24M7LXSGOgKPOvuXYA9VBnWOVbnQ8GfBGaWRiz0p7n7q1HxJ2Z2ZrT9TGJXv0GJ/mxdBFwI\nZETTdkD103t8FfUErjazYmKz115GbEw3xHMBgLtvjn5uAeYQuzAI9bVSApS4+7vRej6xXwTH/Hwo\n+BMUjdlOBta6+5MVNlWcrmIo8Fp99y0VzCzTzDKi5ROBPsTe91hEbNoOCOR8uPv97t7S3VsT+9T6\nX9x9CAGeCwAzO9nMmh1aBvKAVQT6WnH3fwH/NLM2UdHlwBrq4XzoA1wJMrNewJvASr4Yx32A2Dj/\nbKAVsAm43t23p6ST9cjMOhF7Q6oRsQuL2e7+UzP7BrGr3q8DfwducPfPU9fT+mVmlwA/dPerQj0X\n0fOeE602Bqa7+zgza0GArxUAM8sh9sZ/E+BD4Cai1w3H8Hwo+EVEAqOhHhGRwCj4RUQCo+AXEQmM\ngl9EJDAKfhGRwCj4RUQCo+AXEQmMgl9EJDD/H/HvQFU9vmq2AAAAAElFTkSuQmCC\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "tags": [] + } + }, + { + "output_type": "display_data", + "data": { + "image/png": "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\nv66oqMA5x4QJE7j11luPWG/RokUsWLCApUuX0qRJE/r06RO+Xjk+Pj7c5kaNGlFRUXHMfu+//376\n9u3LvHnzKCsro0+fPhG3ua7FxcVx6NCh8Oujr7s+88wzw9P5+fksX76cv/71r/To0YOioiJat24d\ns1pFYumUGqvk008/ZenSpQC88sor/OQnP6FDhw6UlZXx0UcfAfDSSy9xySWXsHfvXnbv3s0VV1zB\nE088QUlJyTHba9asGXv27KlyX9dccw1vvvkmM2fOZMiQIQD079+fOXPmsGPHDgB27drFJ59EPJLj\nES677DKmTZvG3r17Adi2bRs7duxg9+7dtGrViiZNmrB+/XqWLVtWq+3u3r2btm3bAsG++dq49NJL\nmTJlSvj1//7v/5KVlcXf//53du7cybfffsvMmTO55JJLjlivV69evPHGG+zfv599+/Yxb948evXq\nxVlnncWOHTsoLy/nq6++4u23365235s3b+bCCy9k4sSJJCYmsmXLllrVLuKTmN3yfrT6+OS9Q4cO\nTJkyheHDh9O5c2dGjhxJQkICL7zwAtdffz0VFRVkZmZy2223sWvXLgYNGsTBgwdxzvH4448fs73c\n3Fxuu+02GjduHP6DcFirVq3o1KkTH374IVlZWQB07tyZSZMmkZOTw6FDh4iPj2fKlCmce+65tW5L\nTk4OpaWlXHRR8CbWpk2b8vLLLzNgwADy8/Pp1KkTHTp0IDs7u1bbveuuuxg2bBiTJk3iyiuvrNW6\n9913H6NHjyYQCNCoUSMeeOABrr32Wh555BH69u2Lc44rr7ySQYMGHbFe9+7dyc3NDf+cRowYQXp6\nOgC//e1vycrKom3btnTs2LHafY8fP55NmzbhnKN///507dq1VrWL+MScc3W+0YyMDHf0gxRKS0vp\n1KlTne8rUmVlZQwcOJC1a9fWWw1ycon0d1KXA0osmFmRcy6iLulTqqtERKQhOGWCOzk5WWfbItIg\nnDLBLSLSUCi4RUQ8o+AWEfGMgltExDP1dh03BTXfPVgrfSfU7fa+hy+++IJXXnmFUaNGAfDZZ5/x\ny1/+kjlz5tRzZdGRm5vLwIEDGTx4MH369GHy5MlkZHz/G2wrDx0rItXTGXcd+uKLL3juuefCr885\n55wGG9onM+fcEbfKizQ0p0xwl5WV0alTJ2655Ra6dOlCTk4OBw4cAIK3Sw8YMIAePXrQq1cv1q9f\nH56fnZ1Namoq9913H02bNgWCw5f279+f7t27k5qayptvvgkEh4HdvHkz3bp1Y/z48UcMS5qdnX3E\ngE2Hh4Ddt28fw4cPJysri/T09PC2Klu0aBGXXHIJgwYN4rzzzuOee+5hxowZZGVlkZqayubNmwH4\n/PPPue6668jMzCQzM5P3338fqH6o1unTp3PttdcyYMAAfvzjH3PXXXdV+bObOHEimZmZBAIB8vLy\nqM1NWytXruTiiy+ma9euZGVlsWfPHg4ePBge/jU9PZ2CgoJj1tu1axdXX301aWlpZGdns3r1auC7\nYXUPCwQClJWVUVZWRocOHbjpppsIBAJs2bKF3NxcAoEAqampPPHEExHXLHKyO2WCG2DTpk2MHj2a\ndevW0bJly/B40Xl5eTzzzDMUFRUxefLkcFfHuHHjGDduHGvWrKFdu3bh7SQkJDBv3jxWrVpFQUEB\nd955J845HnnkEc4//3yKi4t57LHHjtj3DTfcwOzZswHYvn0727dvJyMjg4ceeoh+/fqxYsUKCgoK\nGD9+PPv2HftwoZKSEvLz8yktLeWll15i48aNrFixghEjRvDMM8+E673jjjtYuXIlc+fOZcSIEcDx\nh2otLi4OD2k7a9asKsf4GDNmDCtXrmTt2rUcOHAg4q6Mr7/+mhtuuIGnnnqKkpISFixYQOPGjZky\nZQpmxpo1a5g5cybDhg07ZgCpBx54gPT0dFavXs0f/vAHbrrpphr3t2nTJkaNGsW6devYuXMn27Zt\nY+3ataxZs4abb745oppFfFB/fdz1ICUlhW7dugHfDWu6d+9e/vGPf3D99deHlzv8IIWlS5eGx47+\n+c9/Hn6YgnOOe++9l8WLF3Paaaexbdu2Kh9KUNnPfvYzcnJy+N3vfsfs2bMZPHgwEBxX+6233gqf\nRR48eJBPP/30mFuxMzMzOfvsswE4//zzycnJAYLDvh4+Y12wYAEffvjdUOlffvlleLCsYcOGsWnT\nJsyMb775JrxM//79adGiBRAcS+WTTz6hffv2R+y7oKCARx99lP3797Nr1y66dOnCVVdddfwfNsHx\nz88++2wyMzMBaN68ORAcxnXs2LFA8I/Kueeey8aNR95WvmTJkvAf1n79+lFeXs6XX3553P2de+65\n4bFZzjvvPD7++GPGjh3LlVdeGf55iTQEp1RwVx4etVGjRhw4cIBDhw7RsmVLiouLI97OjBkz+Pzz\n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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "tags": [] + } + }, + { + "output_type": "display_data", + "data": { + "image/png": "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\nxGrIkCE888wz0XHqDz/8EICDBw/Spk0bkpKSePnllysdk08k3fIu0oASdfleRe3bt+e5555j/Pjx\ndOrUiYkTJ5KSksJLL73EyJEjOXbsGL169WLChAl8/vnnDBs2jKNHj+LuPPHEE1/b37hx45gwYQIt\nWrSI/odQ7pvf/CYdO3Zk27Zt5OTkANCpUycefPBBBg8ezIkTJ0hOTua5557jsssuq7buuXPnMnHi\nRB588EFKS0vJy8ujW7duPP3009x00008+uijDBs27LT+bh544AGmTp1K165dOXHiBBkZGbz11ltM\nmjSJ4cOH84c//IHc3NzoO4GGYvH4BDQ7O9v1RQrSaNTj5YDbt2+nY8eOp1lQ3RUVFXHdddexZcuW\nBqtBKv89MLNCd49pSFpDJSIigVFwizQh6enpOttuBBTcIiKBUXCLiARGwS0iEhgFt4hIYHQdt0hD\nqu2lhjU5A2YmPHDgAPPmzYvOJfLpp58yefJkCgoKGqSeOXPmsG7dOp599tkGOX486IxbROrVgQMH\neP7556OPL7744noP7UTcVn4mU3CLNCFFRUV07NiRW2+9lc6dOzN48GCOHDkCUOW0qXv27KFPnz7R\naVPPPfdcoGzip0GDBtGjRw8yMzOjU6BOnz6dPXv2kJWVxbRp0ygqKqJLly4A9OnTh61bt0brKZ8C\ntqrpVCtasWIF/fv35/rrr49+SUNV08O+9NJLtGvXjpycnCpn65sxYwZjx46lf//+XHbZZSxatIh7\n7rmHzMxMcnNzKS0tBaCwsJCrrrqKnj17MmTIkOjkVr/97W/p1asX3bp1Y/jw4dHpcceNG8fkyZP5\nzne+w+WXXx6XdxoKbpEm5qOPPuK2225j69attGzZktdffx2g2mlTp0yZwubNm2nbtm10PykpKSxe\nvJj169ezfPly7rrrLtydRx55hG9/+9ts2LCBxx9//KRjjxo1ioULFwJQXFxMcXEx2dnZVU6neqr1\n69fz9NNPs2vXriqnhy0uLuYXv/gFq1atYuXKlSfN5HeqPXv28O6777JkyRLGjBnDwIED2bx5My1a\ntOCPf/wjpaWl3HHHHRQUFFBYWMj48eO57777APjBD37An//8ZzZu3EjHjh154YUXovstLi5m5cqV\nvPXWW0yfPr2OPVU1jXGLNDEZGRlkZWUB0LNnT4qKik6aNrVc+RcprF69mjfeeAOAm266KfplCu7O\n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\nAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "tags": [] + } + }, + { + "output_type": "display_data", + "data": { + "image/png": "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\nRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "tags": [] + } + }, + { + "output_type": "display_data", + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAW4AAAD8CAYAAABXe05zAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4zLCBo\ndHRwOi8vbWF0cGxvdGxpYi5vcmcvnQurowAAGJJJREFUeJzt3X10VdWZx/HvE4gGK0KLkUExJnTk\nPRAgBFqkgiwhqB1LRYuFKSzUFBEBq7iwahdd1epoRp2hKsViqcpLaAR10XlREcaFokCQ9xcFjBal\nBWOhgGIDeeaPXK4hJOQm5Cbsy++zVlbOPfdkn2fnhB/n7nvOvubuiIhIOJIauwAREakdBbeISGAU\n3CIigVFwi4gERsEtIhIYBbeISGAU3CIigVFwi4gERsEtIhKYpvFo9Pzzz/f09PR4NC0ikpCKioo+\nc/fUWLaNS3Cnp6ezevXqeDQtIpKQzOyjWLfVUImISGAU3CIigVFwi4gEJi5j3CICpaWl7Nq1i8OH\nDzd2KXIaSUlJoW3btiQnJ9e5DQW3SJzs2rWL5s2bk56ejpk1djlyGnB3SkpK2LVrFxkZGXVuJ6ah\nEjNraWaFZrbVzLaY2XfqvEeRM8Thw4dp1aqVQluizIxWrVqd8quwWM+4/wP4H3cfbmZnAeec0l5F\nzhAKbamsPv4magxuM2sBfA8YA+Du/wD+ccp7FhGROonljDsD2Av83sy6A0XAJHc/FNfKRBLM46+9\nX6/t3XFl+3ptryozZszgnHPO4Sc/+QmzZ89m8ODBXHjhhQDcfPPN/OxnP6Nz586ntI9jN+ydf/75\nx62fNm0a5557LnfdddcptZ+IYgnupkBP4HZ3f9fM/gOYCtxfcSMzywPyANLS0uq7TglMfYdUVRoi\nuM5048aNiy7Pnj2brl27RoP7d7/7XWOVdcaL5c3JXcAud3838riQ8iA/jrvPdPdsd89OTY3pdnsR\niZPi4mI6duzIyJEj6dSpE8OHD+eLL74AYMmSJfTo0YPMzEzGjh3LV199BcDUqVPp3Lkz3bp1i57l\nTps2jfz8fAoLC1m9ejUjR44kKyuLL7/8kgEDBrB69WpmzJjBlClTovuePXs2EyZMAOCFF14gJyeH\nrKwsfvrTn3L06NEq633kkUfIzMwkJyeH7du3n/D8sX0BfPbZZxybC+no0aNMmTKF3r17061bN377\n299W+7sYM2YM7du3Z+TIkbz++uv069ePSy+9lJUrVwJw6NAhxo4dS05ODj169ODll1+O/nz//v3p\n2bMnPXv25O233wZg2bJlDBgwgOHDh0d/1+5euwNVRzUGt7v/BfizmXWIrBoEbI5rVSJyyrZt28b4\n8ePZsmUL5513Hk899RSHDx9mzJgxFBQUsGHDBo4cOcLTTz9NSUkJixYtYtOmTaxfv5777rvvuLaG\nDx9OdnY2c+bMYe3atTRr1iz63HXXXceiRYuijwsKChgxYgRbtmyhoKCAt956i7Vr19KkSRPmzJlT\nZa0tWrRgw4YNTJgwgcmTJ8fcx1mzZtGiRQtWrVrFqlWreOaZZ/jwww9P2G779u3ceeedbN26la1b\ntzJ37lyWL19Ofn4+v/71rwF48MEHueKKK1i5ciVLly5lypQpHDp0iAsuuIDXXnuNNWvWUFBQwMSJ\nE6PtvvfeezzxxBNs3ryZnTt38tZbb8Vc+6mI9c7J24E5ZrYeyAJ+Hb+SRKQ+XHzxxfTr1w+AUaNG\nsXz5crZt20ZGRgbt25cPM40ePZo333yTFi1akJKSwk033cTChQs555zYLxxLTU2lXbt2vPPOO5SU\nlLB161b69evHkiVLKCoqonfv3mRlZbFkyRJ27txZZRs33nhj9PuKFSti3verr77Kc889R1ZWFn36\n9KGkpIQPPvjghO0yMjLIzMwkKSmJLl26MGjQIMyMzMxMiouLo209/PDDZGVlMWDAAA4fPszHH39M\naWkpt9xyC5mZmVx//fVs3vz1eWtOTg5t27YlKSmJrKysaFvxFtPlgO6+FsiOcy0iUo8qX3Z2ssvQ\nmjZtysqVK1myZAmFhYX85je/4Y033oh5XyNGjGDBggV07NiRYcOGYWa4O6NHj+ahhx6qVa1V1dm0\naVPKysoAjrsG2t2ZPn06Q4YMOWn7Z599dnQ5KSkp+jgpKYkjR45E23rxxRfp0KHDcT87bdo0Wrdu\nzbp16ygrKyMlJaXKdps0aRJtK940V4lIgvr444+jZ69z587lsssuo0OHDhQXF0fHkZ9//nkuv/xy\nDh48yP79+7nqqqt4/PHHWbdu3QntNW/enAMHDlS5r2HDhvHyyy8zb948RowYAcCgQYMoLCxkz549\nAHz++ed89FHVM5cWFBREv3/nOyfe35eenk5RUREAhYWF0fVDhgzh6aefprS0FID333+fQ4fqdsHb\nkCFDmD59enSc+r333gNg//79tGnThqSkJJ5//vlqx+kbkm55F2kgDX0VTIcOHXjyyScZO3YsnTt3\n5tZbbyUlJYXf//73XH/99Rw5coTevXszbtw4Pv/8c6699loOHz6Mu/PYY4+d0N6YMWMYN24czZo1\nO2E445vf/CadOnVi8+bN5OTkANC5c2ceeOABBg8eTFlZGcnJyTz55JNccsklJ7T9t7/9jW7dunH2\n2Wczb968E56/6667uOGGG5g5cyZXX311dP3NN99McXExPXv2xN1JTU3lpZdeqtPv6/7772fy5Ml0\n69aNsrIyMjIyWLx4MePHj+e6667jueeeIzc3l2984xt1ar8+WTzeBc3OznZ9kMKZTZcDwpYtW+jU\nqVOj7Lu4uJhrrrmGjRs3Nsr+5eSq+tswsyJ3j2lIWkMlIiKBUXCLJKD09HSdbScwBbeISGAU3CIi\ngVFwi4gERsEtIhIYXcct0lCW1nwHYa0MvKd+26ulffv2MXfuXMaPHw/Ap59+ysSJE4+7QaYuli1b\nRn5+PosXLz7hueqmgD3T6IxbROpk3759PPXUU9HHF1544SmHtsRGwS2SgIqLi+nUqRO33HILXbp0\nYfDgwXz55ZcA7Nixg9zcXHr16kX//v3ZunVrdH3fvn3JzMzkvvvu49xzzwXg4MGDDBo0iJ49e5KZ\nmRmd7nTq1Kns2LGDrKwspkyZQnFxMV27dgWgb9++bNq0KVrPsWlZq5s6tbK///3vXH311XTo0IFx\n48ZF5ymp2L9j+wLIz89n2rRpJ+1fRdOmTWP06NH079+fSy65hIULF3L33XeTmZlJbm5u9Bb6oqIi\nLr/8cnr16sWQIUPYvXs3AM888wy9e/eme/fuXHfdddEpc8eMGcPEiRP57ne/S7t27eL2H5mCWyRB\nffDBB9x2221s2rSJli1b8uKLLwKQl5fH9OnTKSoqIj8/PzrUMWnSJCZNmsSGDRto27ZttJ2UlBQW\nLVrEmjVrWLp0KXfeeSfuzsMPP8y3v/1t1q5dy6OPPnrcvn/0ox+xYMECAHbv3s3u3bvJzs6udurU\nylauXMn06dPZvHkzO3bsYOHChTH3u7r+VbZjxw7eeOMNXnnlFUaNGsXAgQPZsGEDzZo1409/+hOl\npaXcfvvtFBYWUlRUxNixY7n33nsB+OEPf8iqVatYt24dnTp1YtasWdF2d+/ezfLly1m8eDFTp06N\nue7a0Bi3SILKyMggKysLgF69elFcXMzBgwd5++23uf7666PbHfsghRUrVkTn+fjxj38c/TAFd+fn\nP/85b775JklJSXzyySf89a9/Pem+b7jhBgYPHswvf/lLFixYwPDhw4HyqVNfeeUV8vPzAaJTp1a+\n/TsnJ4d27doB5VO9Ll++PNrGyZysf5UNHTqU5ORkMjMzOXr0KLm5uQDRqV63bdvGxo0bufLKK4Hy\nD21o06YNABs3buS+++5j3759HDx48LjZCX/wgx+QlJRE586da/w91ZWCWyRBVZ5y9Msvv6SsrIyW\nLVuydu3amNuZM2cOe/fupaioiOTkZNLT04+bWrUqF110Ea1atWL9+vUUFBQwY8YMoPqpUyuraUra\nitO8wtdTvdamfxWndk1OTo7u49hUr+5Oly5dqpwffMyYMbz00kt0796d2bNns2zZshPaPdbfeNBQ\nicgZ5LzzziMjI4M//vGPQHmwHJvCtW/fvtHhlPnz50d/Zv/+/VxwwQUkJyezdOnS6NSsJ5vmFcqH\nSx555BH2799Pt27dgOqnTq1s5cqVfPjhh5SVlVFQUMBll1123POtW7dmz549lJSU8NVXX0WvQDlZ\n/2qrQ4cO7N27NxrcpaWl0XH7AwcO0KZNG0pLS6v9VJ940hm3SENp5Mv3jpkzZw633norDzzwAKWl\npYwYMYLu3bvzxBNPMGrUKB588EFyc3Np0aIFACNHjuT73/8+mZmZZGdn07FjRwBatWpFv3796Nq1\nK0OHDuW22247bj/Dhw9n0qRJ3H//158rXt3UqZX17t2bCRMmsH37dgYOHMiwYcOOez45OZlf/OIX\n5OTkcNFFF0VrOln/auuss86isLCQiRMnsn//fo4cOcLkyZPp0qULv/rVr+jTpw+pqan06dPnpP+B\nxYOmdZW40LSujTuta1188cUXNGvWDDNj/vz5zJs3r9qrPuTUnOq0rjrjFhGg/NK3CRMm4O60bNmS\nZ599trFLkmoouEUEgP79+9d5PFgalt6cFImjeF1VIOGqj78JBbdInKSkpFBSUqLwlih3p6Sk5LhP\niq8LDZWIxEnbtm3ZtWsXe/fubexS5DSSkpJy3J2pdaHgFomT5ORkMjIyGrsMSUAaKhERCYyCW0Qk\nMDENlZhZMXAAOAocifUicRERqX+1GeMe6O6fxa0SERGJiYZKREQCE+sZtwOvmpkDv3X3mZU3MLM8\nIA8gLS2t/io8k9TlMwlPk4mLQlGXOVRO9zlR5MwT6xn3Ze7eExgK3GZm36u8gbvPdPdsd89OTU2t\n1yJFRORrMQW3u38S+b4HWATkxLMoERGpXo3BbWbfMLPmx5aBwcDGeBcmIiJVi2WMuzWwKPKxPk2B\nue7+P3GtSkREqlVjcLv7TqD2Hx8hIiJxocsBRUQCo+AWEQmMgltEJDAKbhGRwCi4RUQCo+AWEQmM\ngltEJDAKbhGRwCi4RUQCo+AWEQmMgltEJDAKbhGRwCi4RUQCo+AWEQmMgltEJDAKbhGRwCi4RUQC\no+AWEQmMgltEJDAKbhGRwCi4RUQCo+AWEQmMgltEJDAKbhGRwCi4RUQCE3Nwm1kTM3vPzBbHsyAR\nETm52pxxTwK2xKsQERGJTUzBbWZtgauB38W3HBERqUmsZ9xPAHcDZXGsRUREYtC0pg3M7Bpgj7sX\nmdmAk2yXB+QBpKWl1VuBp42lDzV2BfWntn0ZeE986hCROonljLsf8C9mVgzMB64wsxcqb+TuM909\n292zU1NT67lMERE5psbgdvd73L2tu6cDI4A33H1U3CsTEZEq6TpuEZHA1DjGXZG7LwOWxaUSERGJ\nic64RUQCo+AWEQmMgltEJDAKbhGRwCi4RUQCo+AWEQmMgltEJDAKbhGRwCi4RUQCo+AWEQmMgltE\nJDAKbhGRwCi4RUQCo+AWEQmMgltEJDAKbhGRwCi4RUQCo+AWEQmMgltEJDAKbhGRwCi4RUQCo+AW\nEQmMgltEJDAKbhGRwCi4RUQCo+AWEQlMjcFtZilmttLM1pnZJjP7ZUMUJiIiVWsawzZfAVe4+0Ez\nSwaWm9l/u/s7ca5NRESqUGNwu7sDByMPkyNfHs+iRESkerGccWNmTYAi4J+BJ9393Sq2yQPyANLS\n0uqzRmlkj7/2fmOXUKXTtS6ReIvpzUl3P+ruWUBbIMfMulaxzUx3z3b37NTU1PquU0REImp1VYm7\n7wOWArnxKUdERGoSy1UlqWbWMrLcDLgS2BrvwkREpGqxjHG3Af4QGedOAha4++L4liUiItWJ5aqS\n9UCPBqhFRERioDsnRUQCo+AWEQmMgltEJDAKbhGRwCi4RUQCo+AWEQmMgltEJDAKbhGRwCi4RUQC\no+AWEQmMgltEJDAKbhGRwCi4RUQCo+AWEQmMgltEJDAKbhGRwCi4RUQCo+AWEQmMgltEJDAKbhGR\nwCi4RUQCo+AWEQmMgltEJDAKbhGRwCi4RUQCU2Nwm9nFZrbUzDab2SYzm9QQhYmISNWaxrDNEeBO\nd19jZs2BIjN7zd03x7k2ERGpQo1n3O6+293XRJYPAFuAi+JdmIiIVK1WY9xmlg70AN6NRzEiIlIz\nc/fYNjQ7F/g/4EF3X1jF83lAHkBaWlqvjz76qD7rrF9LH2rsChrVip0lcd/HO2l5tf6Zvh/PjEMl\nx6tLXbV1x5Xt474PSTxmVuTu2bFsG9MZt5klAy8Cc6oKbQB3n+nu2e6enZqaGnu1IiJSK7FcVWLA\nLGCLuz8W/5JERORkYjnj7gf8K3CFma2NfF0V57pERKQaNV4O6O7LAWuAWkREJAa6c1JEJDAKbhGR\nwCi4RUQCo+AWEQmMgltEJDAKbhGRwCi4RUQCo+AWEQmMgltEJDAKbhGRwCi4RUQCo+AWEQmMgltE\nJDAKbhGRwCi4RUQCo+AWEQmMgltEJDAKbhGRwCi4RUQCo+AWEQmMgltEJDAKbhGRwCi4RUQCo+AW\nEQmMgltEJDAKbhGRwNQY3Gb2rJntMbONDVGQiIicXCxn3LOB3DjXISIiMaoxuN39TeDzBqhFRERi\n0LS+GjKzPCAPIC0trb6ardnShxpuX3G2YmdJY5eQ8Pp+PDPu+3j8tbxa/8wdV7aPQyWSqOrtzUl3\nn+nu2e6enZqaWl/NiohIJbqqREQkMApuEZHAxHI54DxgBdDBzHaZ2U3xL0tERKpT45uT7n5jQxQi\nIiKx0VCJiEhgFNwiIoFRcIuIBEbBLSISGAW3iEhgFNwiIoFRcIuIBEbBLSISGAW3iEhgFNwiIoFR\ncIuIBEbBLSISGAW3iEhgFNwiIoFRcIuIBEbBLSISGAW3iEhgFNwiIoFRcIuIBEbBLSISGAW3iEhg\nFNwiIoFRcIuIBEbBLSISGAW3iEhgYgpuM8s1s21mtt3Mpsa7KBERqV6NwW1mTYAngaFAZ+BGM+sc\n78JERKRqsZxx5wDb3X2nu/8DmA9cG9+yRESkOrEE90XAnys83hVZJyIijaBpfTVkZnlAXuThQTPb\nVsemzgc+q5+qgpGAff73mjZIwD4fU2XfT9rfn8WtlkaVwMe4WqfS50ti3TCW4P4EuLjC47aRdcdx\n95nAzFh3XB0zW+3u2afaTkjU58R3pvUX1Od4imWoZBVwqZllmNlZwAjglfiWJSIi1anxjNvdj5jZ\nBOB/gSbAs+6+Ke6ViYhIlWIa43b3/wL+K861HHPKwy0BUp8T35nWX1Cf48bcvSH2IyIi9US3vIuI\nBKZBg9vMnjWzPWa2scK6b5nZa2b2QeT7NyPrzcz+M3Kb/Xoz69mQtdaXavr8qJltjfRrkZm1rPDc\nPZE+bzOzIY1T9ampqs8VnrvTzNzMzo88TtjjHFl/e+RYbzKzRyqsT8jjbGZZZvaOma01s9VmlhNZ\nH/xxNrOLzWypmW2OHM9JkfUNn2Hu3mBfwPeAnsDGCuseAaZGlqcC/xZZvgr4b8CAvsC7DVlrnPs8\nGGgaWf63Cn3uDKwDzgYygB1Ak8buQ330ObL+Ysrf5P4IOP8MOM4DgdeBsyOPL0j04wy8CgytcGyX\nJcpxBtoAPSPLzYH3I8eywTOsQc+43f1N4PNKq68F/hBZ/gPwgwrrn/Ny7wAtzaxNw1Raf6rqs7u/\n6u5HIg/fofzaeCjv83x3/8rdPwS2Uz7lQFCqOc4AjwN3AxXfWEnY4wzcCjzs7l9FttkTWZ/Ix9mB\n8yLLLYBPI8vBH2d33+3uayLLB4AtlN9F3uAZdjqMcbd2992R5b8ArSPLZ8qt9mMp/18ZErjPZnYt\n8Im7r6v0VML2GWgP9Dezd83s/8ysd2R9Ivd5MvComf0ZyAfuiaxPqD6bWTrQA3iXRsiw0yG4o7z8\n9cUZc5mLmd0LHAHmNHYt8WRm5wA/B37R2LU0sKbAtyh/mTwFWGBm1rglxd2twB3ufjFwBzCrkeup\nd2Z2LvAiMNnd/17xuYbKsNMhuP967OVD5Puxl5Mx3WofKjMbA1wDjIwcbEjcPn+b8rHcdWZWTHm/\n1pjZP5G4fYbyM6yFkZfKK4EyyueySOQ+jwYWRpb/yNdDQAnRZzNLpjy057j7sX42eIadDsH9CuUH\nm8j3lyus/0nkndm+wP4KL0eCZma5lI/1/ou7f1HhqVeAEWZ2tpllAJcCKxujxvrk7hvc/QJ3T3f3\ndMoDrae7/4UEPs7AS5S/QYmZtQfOonwCooQ8zhGfApdHlq8APogsB3+cI6+WZgFb3P2xCk81fIY1\n8Luy84DdQCnl/3hvAloBSyg/wK8D34psa5R/gMMOYAOQ3ZC1xrnP2ykf+1ob+ZpRYft7I33eRuTd\n+dC+qupzpeeL+fqqkkQ+zmcBLwAbgTXAFYl+nIHLgCLKr5p5F+iVKMc50jcH1lf4t3tVY2SY7pwU\nEQnM6TBUIiIitaDgFhEJjIJbRCQwCm4RkcAouEVEAqPgFhEJjIJbRCQwCm4RkcD8P2YYwoyj4vxZ\nAAAAAElFTkSuQmCC\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "tags": [] + } + }, + { + "output_type": "display_data", + "data": { + "image/png": "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\nSGD+H2uWuv1q9EkiAAAAAElFTkSuQmCC\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "tags": [] + } + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "lN2meWTLRB07", + "colab_type": "text" + }, + "source": [ + "function to get all features for a single image" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "EgaU3Y7AnxW1", + "colab_type": "text" + }, + "source": [ + "All Features except for mean green pixel values seem to allow for decent destinction between the classes. G" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "lTyV3w06xZ2z", + "colab_type": "code", + "colab": {} + }, + "source": [ + "def getFeaturesOneImage(imagepath):\n", + " X = []\n", + " X.append(filterMaxMean(imagepath))\n", + " X.append(computeMeanForAllColours(imagepath))\n", + " X.append(computeMeanSingleColour(red, imagepath))\n", + " X.append(computeMeanSingleColour(blue, imagepath))\n", + " X.append(calcMeanEdges(imagepath))\n", + " X = np.asarray(X).reshape(1,n)\n", + " return X" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "nKPME6gkRFnC", + "colab_type": "text" + }, + "source": [ + "function to calculate mu0, mu1 and sigma" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "tdEABEUjwCt4", + "colab_type": "code", + "colab": {} + }, + "source": [ + "def computeParameters():\n", + " flag = 0\n", + " meanMaxPos = []\n", + " meanMaxNeg = []\n", + " meanAllColorNeg = []\n", + " meanAllColorPos = []\n", + " meanRedNeg = []\n", + " meanRedPos = []\n", + " meanBlueNeg = []\n", + " meanBluePos = []\n", + " \n", + " meanEdgeNeg = []\n", + " meanEdgePos = []\n", + " \n", + " mu0 = []\n", + " mu1 = []\n", + " sig = []\n", + " \n", + " for i in range(60):\n", + " if i >= 30:\n", + " flag = 1\n", + " if flag == 0:\n", + " meanMaxNeg.append(filterMaxMean(picturePathListNegative[i]))\n", + " meanAllColorNeg.append(computeMeanForAllColours(picturePathListNegative[i]))\n", + " meanRedNeg.append(computeMeanSingleColour(red, picturePathListNegative[i]))\n", + " meanBlueNeg.append(computeMeanSingleColour(blue, picturePathListNegative[i]))\n", + " \n", + " meanEdgeNeg.append(calcMeanEdges(picturePathListNegative[i]))\n", + " elif flag == 1:\n", + " i = i - 30\n", + " meanMaxPos.append(filterMaxMean(picturePathListPositive[i]))\n", + " meanAllColorPos.append(computeMeanForAllColours(picturePathListPositive[i]))\n", + " meanRedPos.append(computeMeanSingleColour(red, picturePathListPositive[i]))\n", + " meanBluePos.append(computeMeanSingleColour(blue, picturePathListPositive[i]))\n", + " meanEdgePos.append(calcMeanEdges(picturePathListPositive[i]))\n", + " \n", + " mu0.append(np.mean(meanMaxNeg))\n", + " mu0.append(np.mean(meanAllColorNeg))\n", + " mu0.append(np.mean(meanRedNeg))\n", + " mu0.append(np.mean(meanBlueNeg))\n", + " mu0.append(np.mean(meanEdgeNeg))\n", + " \n", + " mu1.append(np.mean(meanMaxPos))\n", + " mu1.append(np.mean(meanAllColorPos))\n", + " mu1.append(np.mean(meanRedPos))\n", + " mu1.append(np.mean(meanBluePos))\n", + " mu1.append(np.mean(meanEdgePos))\n", + " \n", + " mu0 = np.asarray(mu0).reshape(1,n)\n", + " mu1 = np.asarray(mu1).reshape(1,n)\n", + " \n", + " SIG = np.zeros((n,n)) #dimensions\n", + " for i in picturePathListNegative:\n", + " X = getFeaturesOneImage(i)\n", + " X = np.asarray(X).reshape(1,n)\n", + " sub = np.subtract(X,mu0)\n", + " SIG += np.dot(sub.T,sub)\n", + " \n", + " for i in picturePathListPositive:\n", + " X = getFeaturesOneImage(i)\n", + " X = np.asarray(X).reshape(1,n)\n", + " sub = np.subtract(X,mu1)\n", + " SIG += np.dot(sub.T,sub)\n", + " \n", + " #print(SIG*(1/m))\n", + " return mu0,mu1,SIG*(1/m)\n", + " " + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "VdzRvBg0RJpw", + "colab_type": "text" + }, + "source": [ + "function to apply GDA on the images" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "j1a3B3_KxPRB", + "colab_type": "code", + "colab": {} + }, + "source": [ + "def gda():\n", + " negVecMean, posVecMean, determinant = computeParameters()\n", + " print(negVecMean, posVecMean)\n", + "\n", + " phi=0.5\n", + " dimensions = n #number of features\n", + " \n", + " picturePathList = []\n", + " picturePathList = picturePathListNegative + picturePathListPositive\n", + " \n", + " classifiedList = []\n", + " \n", + " denominator = (2 * np.pi)**(dimensions/2) * np.sqrt(np.linalg.det(determinant))\n", + " \n", + " for i in picturePathList:\n", + " vecImg = []\n", + " vecImg = getFeaturesOneImage(i)\n", + " vector = vecImg - negVecMean\n", + " \n", + " probClass0 = np.exp(-0.5 * (vecImg - negVecMean) @ (np.linalg.inv(determinant) @ (vecImg - negVecMean).T)) / denominator\n", + " probClass1 = np.exp(-0.5 * (vecImg - posVecMean) @ (np.linalg.inv(determinant) @ (vecImg - posVecMean).T)) / denominator\n", + " \n", + " if probClass0 > probClass1:\n", + " classifiedList.append('0')\n", + " else:\n", + " classifiedList.append('1')\n", + " \n", + " \n", + " return classifiedList" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "Ji1rP1X1B1iM", + "colab_type": "code", + "outputId": "64694a25-9ea1-4d00-de5d-746084c63621", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 1042 + } + }, + "source": [ + "classifierList = gda()\n", + "classifierList" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "[[133.61944444 139.29417438 163.71302083 127.34149306 29.01847994]] [[152.38888889 152.87141204 176.17256944 142.91741898 39.15675154]]\n" + ], + "name": "stdout" + }, + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "['0',\n", + " '0',\n", + " '0',\n", + " '0',\n", + " '0',\n", + " '0',\n", + " '0',\n", + " '0',\n", + " '0',\n", + " '0',\n", + " '0',\n", + " '0',\n", + " '0',\n", + " '0',\n", + " '0',\n", + " '0',\n", + " '0',\n", + " '0',\n", + " '0',\n", + " '0',\n", + " '0',\n", + " '0',\n", + " '0',\n", + " '0',\n", + " '0',\n", + " '0',\n", + " '0',\n", + " '0',\n", + " '0',\n", + " '0',\n", + " '1',\n", + " '1',\n", + " '1',\n", + " '1',\n", + " '1',\n", + " '1',\n", + " '1',\n", + " '1',\n", + " '1',\n", + " '1',\n", + " '1',\n", + " '1',\n", + " '1',\n", + " '1',\n", + " '1',\n", + " '1',\n", + " '1',\n", + " '1',\n", + " '1',\n", + " '1',\n", + " '1',\n", + " '1',\n", + " '1',\n", + " '1',\n", + " '1',\n", + " '1',\n", + " '1',\n", + " '1',\n", + " '1',\n", + " '1']" + ] + }, + "metadata": { + "tags": [] + }, + "execution_count": 39 + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "pyeOWvsuQv9d", + "colab_type": "code", + "colab": {} + }, + "source": [ + "" + ], + "execution_count": 0, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Gaussian Discriminant Analysis/GDA.py b/Gaussian Discriminant Analysis/GDA.py new file mode 100644 index 0000000..033fb46 --- /dev/null +++ b/Gaussian Discriminant Analysis/GDA.py @@ -0,0 +1,305 @@ +# -*- coding: utf-8 -*- +"""ML Exercise 3 Kavish and the Flow.ipynb + +Automatically generated by Colaboratory. + +Original file is located at + https://colab.research.google.com/drive/1WJtYqrxa_8Mjrl2D_dpeMVNJLooyL9aE + +## **Gaussian Discriminant Analysis - ML Exercise 3 - Kavish and Florian** +""" + +import numpy as np +import matplotlib.pyplot as plt +from PIL import Image, ImageFilter +import imageio + +!git clone https://github.com/KavishBhatia/MachineLearning.git + +"""Compute the feature probability distributions for the positive(p) and negative(n) group. +Features: + 1. Mean of all (R)GB values + 2. Mean of all R(G)B values + 3. Mean of all RG(B) values + 4. Lowest(darkest) cumulative RBG value of 2x2 Filter + 5. Mean of all RGB (all 3) values + +Plot distributions for p and n and check if they are differentiable. + +Sum up relative probability for an image to be in p or n according to all feature probabilities. + +Get paths of all the negative and positive images +""" + +category = ["positives", "negatives"] +ml = "MachineLearning/" + +def getPositiveImages(): + image_path = [] + for i in range(1,31): + if i < 10: + img_name = "/p0" + str(i) + else: + img_name = "/p" +str(i) + path = ml + category[0] + img_name + ".png" + image_path.append(path) + return image_path + +def getNegativeImages(): + image_path = [] + for i in range(1,31): + if i < 10: + img_name = "/n0" + str(i) + else: + img_name = "/n" +str(i) + path = ml + category[1] + img_name + ".png" + image_path.append(path) + return image_path + +"""Getting all positive and negative images""" + +picturePathListPositive = getPositiveImages() + picturePathListNegative = getNegativeImages() + +"""function to get pixels of an image""" + +def getPixelValues(imagepath): + im = imageio.imread(imagepath) + return im + +"""function to compute Means for a single color in the image and for all the pixel values""" + +def computeMeanForAllColours(imagepath): + pixValues = getPixelValues(imagepath) + meanPixValues = np.mean(pixValues) + return meanPixValues + +def computeMeanSingleColour(colour, imagepath): + pixValues = getPixelValues(imagepath) + meanPixValues = np.mean(pixValues[:,:,colour]) + return meanPixValues + +red = 0 +green = 1 +blue = 2 +m = 60 # total number of pos and neg images +n = 5 #no of features + +"""function to calculate mean of the image after converting to edges""" + +def calcMeanEdges(imagepath): + image = Image.open(imagepath) + return np.mean(image.filter(ImageFilter.FIND_EDGES)) + +"""function to plot histograms for all the features""" + +def meanAllValues(): + + listOfPosMeans = [] + listOfNegMeans = [] + listOfPosRedMeans = [] # pos red means + listOfPosGreenMeans = [] # pos green means + listOfPosBlueMeans = [] # pos blue means + listOfNegRedMeans = [] # neg red means + listOfNegGreenMeans = [] # neg green means + listOfNegBlueMeans = [] # neg blue means + listOfPosFilterMeans = [] # Filter means + listOfNegFilterMeans = [] # Filter means + + NegEdges = [] + PosEdges = [] + + for i in picturePathListPositive: + listOfPosMeans.append(computeMeanForAllColours(i)) + listOfPosRedMeans.append(computeMeanSingleColour(red,i)) + listOfPosGreenMeans.append(computeMeanSingleColour(green,i)) + listOfPosBlueMeans.append(computeMeanSingleColour(blue,i)) + listOfPosFilterMeans.append(filterMaxMean(i)) + + PosEdges.append(calcMeanEdges(i)) + + for i in picturePathListNegative: + listOfNegMeans.append(computeMeanForAllColours(i)) + listOfNegRedMeans.append(computeMeanSingleColour(red,i)) + listOfNegGreenMeans.append(computeMeanSingleColour(green,i)) + listOfNegBlueMeans.append(computeMeanSingleColour(blue,i)) + listOfNegFilterMeans.append(filterMaxMean(i)) + + NegEdges.append(calcMeanEdges(i)) + + bins = np.linspace(15, 60, 10) + plt.hist(PosEdges, bins, alpha=0.5, label='positive edges') + plt.hist(NegEdges, bins, alpha=0.5, label='negative edges') + plt.legend() + plt.show() + + + + bins = np.linspace(100, 200, 25) + plt.hist(listOfPosMeans, bins, alpha=0.5, label='positive mean all colours') + plt.hist(listOfNegMeans, bins, alpha=0.5, label='negative mean all colours') + plt.legend() + plt.show() + + bins = np.linspace(100, 200, 25) + plt.hist(listOfPosRedMeans, bins, alpha=0.5, label='positive red mean') + plt.hist(listOfNegRedMeans, bins, alpha=0.5, label='negative red mean') + plt.legend() + plt.show() + + bins = np.linspace(100, 200, 25) + plt.hist(listOfPosGreenMeans, bins, alpha=0.5, label='positive green mean') + plt.hist(listOfNegGreenMeans, bins, alpha=0.5, label='negative green mean') + plt.legend() + plt.show() + + bins = np.linspace(100, 200, 25) + plt.hist(listOfPosBlueMeans, bins, alpha=0.5, label='positive blue mean') + plt.hist(listOfNegBlueMeans, bins, alpha=0.5, label='negative blue mean') + plt.legend() + plt.show() + + bins = np.linspace(100, 200, 25) + plt.hist(listOfPosFilterMeans, bins, alpha=0.5, label='positive filter') + plt.hist(listOfNegFilterMeans, bins, alpha=0.5, label='negative filter') + plt.legend() + plt.show() + +"""function to get the Maximum or the darkest spot in the image from a 2x2 filter""" + +def filterMaxMean(image): + img = Image.open(image) + members = [(0,0)] * 4 + filteredMeanMax = 255 + for i in range(1,23): + for j in range(1,23): + members[0] = img.getpixel((i-1,j-1)) + members[1] = img.getpixel((i-1,j)) + members[2] = img.getpixel((i-1,j+1)) + members[3] = img.getpixel((i,j-1)) + tempFilteredMeanMax = np.mean(members) + if tempFilteredMeanMax < filteredMeanMax: + filteredMeanMax = tempFilteredMeanMax + return (filteredMeanMax - 255)*(-1) + +meanAllValues() + +"""function to get all features for a single image + +All Features except for mean green pixel values seem to allow for decent destinction between the classes. G +""" + +def getFeaturesOneImage(imagepath): + X = [] + X.append(filterMaxMean(imagepath)) + X.append(computeMeanForAllColours(imagepath)) + X.append(computeMeanSingleColour(red, imagepath)) + X.append(computeMeanSingleColour(blue, imagepath)) + X.append(calcMeanEdges(imagepath)) + X = np.asarray(X).reshape(1,n) + return X + +"""function to calculate mu0, mu1 and sigma""" + +def computeParameters(): + flag = 0 + meanMaxPos = [] + meanMaxNeg = [] + meanAllColorNeg = [] + meanAllColorPos = [] + meanRedNeg = [] + meanRedPos = [] + meanBlueNeg = [] + meanBluePos = [] + + meanEdgeNeg = [] + meanEdgePos = [] + + mu0 = [] + mu1 = [] + sig = [] + + for i in range(60): + if i >= 30: + flag = 1 + if flag == 0: + meanMaxNeg.append(filterMaxMean(picturePathListNegative[i])) + meanAllColorNeg.append(computeMeanForAllColours(picturePathListNegative[i])) + meanRedNeg.append(computeMeanSingleColour(red, picturePathListNegative[i])) + meanBlueNeg.append(computeMeanSingleColour(blue, picturePathListNegative[i])) + + meanEdgeNeg.append(calcMeanEdges(picturePathListNegative[i])) + elif flag == 1: + i = i - 30 + meanMaxPos.append(filterMaxMean(picturePathListPositive[i])) + meanAllColorPos.append(computeMeanForAllColours(picturePathListPositive[i])) + meanRedPos.append(computeMeanSingleColour(red, picturePathListPositive[i])) + meanBluePos.append(computeMeanSingleColour(blue, picturePathListPositive[i])) + meanEdgePos.append(calcMeanEdges(picturePathListPositive[i])) + + mu0.append(np.mean(meanMaxNeg)) + mu0.append(np.mean(meanAllColorNeg)) + mu0.append(np.mean(meanRedNeg)) + mu0.append(np.mean(meanBlueNeg)) + mu0.append(np.mean(meanEdgeNeg)) + + mu1.append(np.mean(meanMaxPos)) + mu1.append(np.mean(meanAllColorPos)) + mu1.append(np.mean(meanRedPos)) + mu1.append(np.mean(meanBluePos)) + mu1.append(np.mean(meanEdgePos)) + + mu0 = np.asarray(mu0).reshape(1,n) + mu1 = np.asarray(mu1).reshape(1,n) + + SIG = np.zeros((n,n)) #dimensions + for i in picturePathListNegative: + X = getFeaturesOneImage(i) + X = np.asarray(X).reshape(1,n) + sub = np.subtract(X,mu0) + SIG += np.dot(sub.T,sub) + + for i in picturePathListPositive: + X = getFeaturesOneImage(i) + X = np.asarray(X).reshape(1,n) + sub = np.subtract(X,mu1) + SIG += np.dot(sub.T,sub) + + #print(SIG*(1/m)) + return mu0,mu1,SIG*(1/m) + +"""function to apply GDA on the images""" + +def gda(): + negVecMean, posVecMean, determinant = computeParameters() + print(negVecMean, posVecMean) + + phi=0.5 + dimensions = n #number of features + + picturePathList = [] + picturePathList = picturePathListNegative + picturePathListPositive + + classifiedList = [] + + denominator = (2 * np.pi)**(dimensions/2) * np.sqrt(np.linalg.det(determinant)) + + for i in picturePathList: + vecImg = [] + vecImg = getFeaturesOneImage(i) + vector = vecImg - negVecMean + + probClass0 = np.exp(-0.5 * (vecImg - negVecMean) @ (np.linalg.inv(determinant) @ (vecImg - negVecMean).T)) / denominator + probClass1 = np.exp(-0.5 * (vecImg - posVecMean) @ (np.linalg.inv(determinant) @ (vecImg - posVecMean).T)) / denominator + + if probClass0 > probClass1: + classifiedList.append('0') + else: + classifiedList.append('1') + + + return classifiedList + +classifierList = gda() +classifierList +