{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from PIL import Image\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "\n",
    "class ImageFractalDimension:\n",
    "    def __init__(self, image_name, SIZE):\n",
    "        self.SIZE = SIZE\n",
    "        image = Image.open(image_name)\n",
    "\n",
    "        assert image.size[0] == image.size[1] and image.size[\n",
    "            0] == self.SIZE, \"Height and Width of the image must be equal.\"\n",
    "\n",
    "        image = np.asarray(image)\n",
    "        self.img_px_array = np.copy(image)\n",
    "\n",
    "        self.convertImg()\n",
    "        self.fractal_dim = self.calculate_fractal_dim()\n",
    "\n",
    "    # Turn image data from colour into either 1 or zero for each colour\n",
    "    def convertImg(self):\n",
    "        for i in range(len(self.img_px_array)):\n",
    "            for j in range(len(self.img_px_array[i])):\n",
    "                for k in range(len(self.img_px_array[i][j])):\n",
    "                    if (self.img_px_array[i][j][k] == 255):\n",
    "                        self.img_px_array[i][j][k] = 0\n",
    "                    else:\n",
    "                        self.img_px_array[i][j][k] = 1\n",
    "\n",
    "    def calculate_fractal_dim(self):\n",
    "        self.dimensions = []\n",
    "        self.filled_boxes = []\n",
    "\n",
    "        self.img_px_array = self.img_px_array[:, :, 0]\n",
    "\n",
    "        size = 1\n",
    "        while size != self.SIZE:\n",
    "            size *= 2\n",
    "            filled_box = self.boxcount(size)\n",
    "            self.filled_boxes.append(filled_box)\n",
    "            self.dimensions.append(size / self.SIZE)\n",
    "\n",
    "        return -np.polyfit(np.log(self.dimensions), np.log(self.filled_boxes), 1)[0]\n",
    "\n",
    "    def blockshaped(self, square_size):\n",
    "        h, w = self.img_px_array.shape\n",
    "        assert h % square_size == 0, \"Array is not evenly divisible\".format(h, square_size)\n",
    "        return (self.img_px_array.reshape(h // square_size, square_size, -1, square_size).swapaxes(1, 2).reshape(-1,\n",
    "                                                                                                                 square_size,\n",
    "                                                                                                                 square_size))\n",
    "\n",
    "    def boxcount(self, size):\n",
    "        blocked_arrays = self.blockshaped(size)\n",
    "        counter = 0\n",
    "\n",
    "        for i in range(len(blocked_arrays)):\n",
    "            for j in range(len(blocked_arrays[i])):\n",
    "                if (blocked_arrays[i][j].any()):\n",
    "                    counter += 1\n",
    "                    break\n",
    "        return counter\n",
    "\n",
    "    def graph(self):\n",
    "        plt.plot(-np.log(self.dimensions), np.log(self.filled_boxes))\n",
    "        plt.title(\"Fractal Dimension : \" + str(self.fractal_dim))\n",
    "        plt.show()\n",
    "        plt.clf()"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [],
   "metadata": {
    "collapsed": false
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
