{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "1f8c46f2-acdb-093b-1285-e68d4cadffb9"
      },
      "outputs": [],
      "source": [
        "# This Python 3 environment comes with many helpful analytics libraries installed\n",
        "# It is defined by the kaggle/python docker image: https://github.com/kaggle/docker-python\n",
        "# For example, here's several helpful packages to load in \n",
        "\n",
        "import numpy as np\n",
        "import pandas as pd\n",
        "import os\n",
        "import cv2\n",
        "import matplotlib.pyplot as plt\n",
        "import skimage.feature\n",
        "from sklearn.model_selection import train_test_split\n",
        "from sklearn.preprocessing import LabelBinarizer\n",
        "import keras\n",
        "from keras.models import Sequential, load_model\n",
        "from keras.layers import Dense, Dropout, Activation, Flatten, Conv2D, MaxPooling2D, Lambda, Cropping2D\n",
        "from keras.utils import np_utils\n",
        "\n",
        "from collections import Counter\n",
        "\n",
        "%matplotlib inline\n",
        "# Any results you write to the current directory are saved as output."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "75f1f1d0-284d-190a-bb90-2fd3d1b75a91"
      },
      "outputs": [],
      "source": [
        "class_names = ['adult_females', 'adult_males', 'juveniles', 'pups', 'subadult_males']\n",
        "\n",
        "file_names = os.listdir(\"../input/Train/\")\n",
        "file_names = sorted(file_names, key=lambda \n",
        "                    item: (int(item.partition('.')[0]) if item[0].isdigit() else float('inf'), item)) \n",
        "\n",
        "# select a subset of files to run on\n",
        "file_names = file_names[0:1]\n",
        "\n",
        "# dataframe to store results in\n",
        "coordinates_df = pd.DataFrame(index=file_names, columns=class_names)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "94cf0b05-7cfd-e16b-0b4f-2667bc60db69"
      },
      "outputs": [],
      "source": [
        "for filename in file_names:\n",
        "    \n",
        "    # read the Train and Train Dotted images\n",
        "    image_1 = cv2.imread(\"../input/TrainDotted/\" + filename)\n",
        "    image_2 = cv2.imread(\"../input/Train/\" + filename)\n",
        "    \n",
        "    cut = np.copy(image_2)\n",
        "    \n",
        "    # absolute difference between Train and Train Dotted\n",
        "    image_3 = cv2.absdiff(image_1,image_2)\n",
        "    \n",
        "    # mask out blackened regions from Train Dotted\n",
        "    mask_1 = cv2.cvtColor(image_1, cv2.COLOR_BGR2GRAY)\n",
        "    mask_1[mask_1 < 20] = 0\n",
        "    mask_1[mask_1 > 0] = 255\n",
        "    \n",
        "    mask_2 = cv2.cvtColor(image_2, cv2.COLOR_BGR2GRAY)\n",
        "    mask_2[mask_2 < 20] = 0\n",
        "    mask_2[mask_2 > 0] = 255\n",
        "    \n",
        "    image_3 = cv2.bitwise_or(image_3, image_3, mask=mask_1)\n",
        "    image_3 = cv2.bitwise_or(image_3, image_3, mask=mask_2) \n",
        "    \n",
        "    # convert to grayscale to be accepted by skimage.feature.blob_log\n",
        "    image_3 = cv2.cvtColor(image_3, cv2.COLOR_BGR2GRAY)\n",
        "    \n",
        "    # detect blobs\n",
        "    blobs = skimage.feature.blob_log(image_3, min_sigma=3, max_sigma=4, num_sigma=1, threshold=0.02)\n",
        "    \n",
        "    adult_males = []\n",
        "    subadult_males = []\n",
        "    pups = []\n",
        "    juveniles = []\n",
        "    adult_females = [] \n",
        "    \n",
        "    image_circles = image_1\n",
        "    \n",
        "    for blob in blobs:\n",
        "        # get the coordinates for each blob\n",
        "        y, x, s = blob\n",
        "        # get the color of the pixel from Train Dotted in the center of the blob\n",
        "        g,b,r = image_1[int(y)][int(x)][:]\n",
        "        \n",
        "        # decision tree to pick the class of the blob by looking at the color in Train Dotted\n",
        "        if r > 200 and g < 50 and b < 50: # RED\n",
        "            adult_males.append((int(x),int(y)))\n",
        "            cv2.circle(image_circles, (int(x),int(y)), 20, (0,0,255), 10) \n",
        "        elif r > 200 and g > 200 and b < 50: # MAGENTA\n",
        "            subadult_males.append((int(x),int(y))) \n",
        "            cv2.circle(image_circles, (int(x),int(y)), 20, (250,10,250), 10)\n",
        "        elif r < 100 and g < 100 and 150 < b < 200: # GREEN\n",
        "            pups.append((int(x),int(y)))\n",
        "            cv2.circle(image_circles, (int(x),int(y)), 20, (20,180,35), 10)\n",
        "        elif r < 100 and  100 < g and b < 100: # BLUE\n",
        "            juveniles.append((int(x),int(y))) \n",
        "            cv2.circle(image_circles, (int(x),int(y)), 20, (180,60,30), 10)\n",
        "        elif r < 150 and g < 50 and b < 100:  # BROWN\n",
        "            adult_females.append((int(x),int(y)))\n",
        "            cv2.circle(image_circles, (int(x),int(y)), 20, (0,42,84), 10)  \n",
        "            \n",
        "        cv2.rectangle(cut, (int(x)-112,int(y)-112),(int(x)+112,int(y)+112), 0,-1)\n",
        "            \n",
        "    coordinates_df[\"adult_males\"][filename] = adult_males\n",
        "    coordinates_df[\"subadult_males\"][filename] = subadult_males\n",
        "    coordinates_df[\"adult_females\"][filename] = adult_females\n",
        "    coordinates_df[\"juveniles\"][filename] = juveniles\n",
        "    coordinates_df[\"pups\"][filename] = pups\n",
        "    "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "2bd3e95c-2fcf-9f9c-2942-aada88650aa0"
      },
      "outputs": [],
      "source": [
        "f, ax = plt.subplots(1,1,figsize=(10,16))\n",
        "ax.imshow(cv2.cvtColor(image_circles, cv2.COLOR_BGR2RGB))\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "f8983af6-4d35-56bd-dfad-9b77570bdf83"
      },
      "outputs": [],
      "source": [
        "f, ax = plt.subplots(1,1,figsize=(10,16))\n",
        "ax.imshow(cv2.cvtColor(cut, cv2.COLOR_BGR2RGB))\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "1d4c0b08-e5f8-6bdd-83c1-54adc547b7bc"
      },
      "outputs": [],
      "source": [
        "x = []\n",
        "y = []\n",
        "\n",
        "for filename in file_names:    \n",
        "    image = cv2.imread(\"../input/Train/\" + filename)\n",
        "    for lion_class in class_names:\n",
        "        for coordinates in coordinates_df[lion_class][filename]:\n",
        "            thumb = image[coordinates[1]-32:coordinates[1]+32,coordinates[0]-32:coordinates[0]+32,:]\n",
        "            if np.shape(thumb) == (64, 64, 3):\n",
        "                x.append(thumb)\n",
        "                y.append(lion_class)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "54fa6e39-9200-d83c-071a-3c04f1a5c130"
      },
      "outputs": [],
      "source": [
        "for i in range(0,np.shape(cut)[0],224):\n",
        "    for j in range(0,np.shape(cut)[1],224):                \n",
        "        thumb = cut[i:i+64,j:j+64,:]\n",
        "        if np.amin(cv2.cvtColor(thumb, cv2.COLOR_BGR2GRAY)) != 0:\n",
        "            if np.shape(thumb) == (64,64,3):\n",
        "                x.append(thumb)\n",
        "                y.append(\"negative\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "5d3a4cee-4b10-789f-e396-fc2d39c2b3c3"
      },
      "outputs": [],
      "source": [
        "class_names.append(\"negative\")\n",
        "x = np.array(x)\n",
        "y = np.array(y)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "9b2cc6b1-f898-0056-76df-dd54b485b46a"
      },
      "outputs": [],
      "source": [
        "# http://machinelearningmastery.com/display-deep-learning-model-training-history-in-keras/\n",
        "# summarize history for accuracy\n",
        "for lion_class in class_names:\n",
        "    f, ax = plt.subplots(1,10,figsize=(12,1.5))\n",
        "    f.suptitle(lion_class)\n",
        "    axes = ax.flatten()\n",
        "    j = 0\n",
        "    for a in axes:\n",
        "        a.set_xticks([])\n",
        "        a.set_yticks([])\n",
        "        for i in range(j,len(x)):\n",
        "            if y[i] == lion_class:\n",
        "                j = i+1\n",
        "                a.imshow(cv2.cvtColor(x[i], cv2.COLOR_BGR2RGB))\n",
        "                break"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "2dfa9b6e-2b9f-6c3f-7252-5b1418956e64"
      },
      "outputs": [],
      "source": [
        "encoder = LabelBinarizer()\n",
        "encoder.fit(y)\n",
        "y = encoder.transform(y).astype(float)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "b7805b62-57ff-1896-e063-26c4af8cf7c6"
      },
      "outputs": [],
      "source": [
        "model = Sequential()\n",
        "\n",
        "model.add(Lambda(lambda x: (x / 255.0) - 0.5, input_shape=(64,64,3)))\n",
        "\n",
        "\n",
        "model.add(Conv2D(32, (5, 5), activation='relu', padding='same'))\n",
        "model.add(MaxPooling2D(pool_size=(2,2)))\n",
        "model.add(Conv2D(64, (5, 5), activation='relu', padding='same'))\n",
        "model.add(MaxPooling2D(pool_size=(2,2)))\n",
        "model.add(Conv2D(128, (5, 5), activation='relu', padding='same'))\n",
        "\n",
        "model.add(Flatten())\n",
        "\n",
        "model.add(Dense(512, activation='relu'))\n",
        "model.add(Dropout(0.5))\n",
        "model.add(Dense(6, activation='softmax'))\n",
        "\n",
        "model.compile(loss='categorical_crossentropy',optimizer='adam',metrics=['accuracy'])"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "6651c8c1-a3d0-a191-0393-baf3ae334055"
      },
      "outputs": [],
      "source": [
        "history = model.fit(x, y, epochs=10, verbose=0)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "0c9f23dc-70e7-083a-ac3b-65dbe34bfbf5"
      },
      "outputs": [],
      "source": [
        "plt.plot(history.history['acc'])\n",
        "plt.title('model accuracy')\n",
        "plt.ylabel('accuracy')\n",
        "plt.xlabel('epoch')\n",
        "plt.legend(['train', 'test'], loc='upper left')\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "_cell_guid": "ddcff384-1f72-11de-bd41-937ef4719539"
      },
      "source": [
        "**Build the test**"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "cc7666cd-215e-55a9-8db7-f2fd18c292f4"
      },
      "outputs": [],
      "source": [
        "img = cv2.imread(\"../input/Train/\" + filename)\n",
        "\n",
        "x_test = []\n",
        "\n",
        "for i in range(0,np.shape(img)[0],64):\n",
        "    for j in range(0,np.shape(img)[1],64):                \n",
        "        thumb = img[i:i+64,j:j+64,:]        \n",
        "        if np.shape(thumb) == (64,64,3):\n",
        "            x_test.append(thumb)\n",
        "\n",
        "x_test = np.array(x_test)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "e5790ae6-35d6-e310-348e-fee972305e0c"
      },
      "outputs": [],
      "source": [
        "y_predicted = model.predict(x_test, verbose=0)\n",
        "y_predicted = encoder.inverse_transform(y_predicted)\n",
        "print(Counter(y_predicted).items())"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "47e97b90-e945-d954-ae11-f4a55049b878"
      },
      "outputs": [],
      "source": [
        "reference = pd.read_csv('../input/Train/train.csv')\n",
        "reference.ix[0:2]"
      ]
    }
  ],
  "metadata": {
    "_change_revision": 0,
    "_is_fork": false,
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.6.0"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}