{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "_cell_guid": "9cfd0e90-cfef-21f9-9914-4304373f81f5"
      },
      "source": [
        "# Data exploration\n",
        "\n",
        "- Visualization of all training data, all testing data\n",
        "- Visualize some additional training data\n",
        "- Clustering of training and test data\n",
        "- Basic skin detection\n",
        "- Some stats using jpg exif"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "948f623a-4a94-5f35-ceaf-fe424582d564"
      },
      "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 # linear algebra\n",
        "import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n",
        "import cv2\n",
        "\n",
        "# Input data files are available in the \"../input/\" directory.\n",
        "# For example, running this (by clicking run or pressing Shift+Enter) will list the files in the input directory\n",
        "\n",
        "from subprocess import check_output\n",
        "print(check_output([\"ls\", \"../input\"]).decode(\"utf8\"))\n",
        "\n",
        "# Any results you write to the current directory are saved as output."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "51a49ad2-8ced-248b-191f-f54a4adfa419"
      },
      "outputs": [],
      "source": [
        "import os\n",
        "from glob import glob\n",
        "TRAIN_DATA = \"../input/train\"\n",
        "type_1_files = glob(os.path.join(TRAIN_DATA, \"Type_1\", \"*.jpg\"))\n",
        "type_1_ids = np.array([s[len(os.path.join(TRAIN_DATA, \"Type_1\"))+1:-4] for s in type_1_files])\n",
        "type_2_files = glob(os.path.join(TRAIN_DATA, \"Type_2\", \"*.jpg\"))\n",
        "type_2_ids = np.array([s[len(os.path.join(TRAIN_DATA, \"Type_2\"))+1:-4] for s in type_2_files])\n",
        "type_3_files = glob(os.path.join(TRAIN_DATA, \"Type_3\", \"*.jpg\"))\n",
        "type_3_ids = np.array([s[len(os.path.join(TRAIN_DATA, \"Type_3\"))+1:-4] for s in type_3_files])\n",
        "\n",
        "print(len(type_1_files), len(type_2_files), len(type_3_files))\n",
        "print(\"Type 1\", type_1_ids[:10])\n",
        "print(\"Type 2\", type_2_ids[:10])\n",
        "print(\"Type 3\", type_3_ids[:10])"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "4301126b-d4f5-3b05-f443-14b9fd20d319"
      },
      "outputs": [],
      "source": [
        "TEST_DATA = \"../input/test\"\n",
        "test_files = glob(os.path.join(TEST_DATA, \"*.jpg\"))\n",
        "test_ids = np.array([s[len(TEST_DATA)+1:-4] for s in test_files])\n",
        "print(len(test_ids))\n",
        "print(test_ids[:10])"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "07f0897f-17e2-f4c0-0b05-ab3f879a7424"
      },
      "outputs": [],
      "source": [
        "ADDITIONAL_DATA = \"../input/additional\"\n",
        "additional_type_1_files = glob(os.path.join(ADDITIONAL_DATA, \"Type_1\", \"*.jpg\"))\n",
        "additional_type_1_ids = np.array([s[len(os.path.join(ADDITIONAL_DATA, \"Type_1\"))+1:-4] for s in additional_type_1_files])\n",
        "additional_type_2_files = glob(os.path.join(ADDITIONAL_DATA, \"Type_2\", \"*.jpg\"))\n",
        "additional_type_2_ids = np.array([s[len(os.path.join(ADDITIONAL_DATA, \"Type_2\"))+1:-4] for s in additional_type_2_files])\n",
        "additional_type_3_files = glob(os.path.join(ADDITIONAL_DATA, \"Type_3\", \"*.jpg\"))\n",
        "additional_type_3_ids = np.array([s[len(os.path.join(ADDITIONAL_DATA, \"Type_3\"))+1:-4] for s in additional_type_3_files])\n",
        "\n",
        "print(len(additional_type_1_files), len(additional_type_2_files), len(additional_type_3_files))\n",
        "print(\"Type 1\", additional_type_1_ids[:10])\n",
        "print(\"Type 2\", additional_type_2_ids[:10])\n",
        "print(\"Type 3\", additional_type_3_ids[:10])"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "edc35b44-c48c-0c56-453a-b8e9cebdad91"
      },
      "outputs": [],
      "source": [
        "def get_filename(image_id, image_type):\n",
        "    \"\"\"\n",
        "    Method to get image file path from its id and type   \n",
        "    \"\"\"\n",
        "    if image_type == \"Type_1\" or \\\n",
        "        image_type == \"Type_2\" or \\\n",
        "        image_type == \"Type_3\":\n",
        "        data_path = os.path.join(TRAIN_DATA, image_type)\n",
        "    elif image_type == \"Test\":\n",
        "        data_path = TEST_DATA\n",
        "    elif image_type == \"AType_1\" or \\\n",
        "          image_type == \"AType_2\" or \\\n",
        "          image_type == \"AType_3\":\n",
        "        data_path = os.path.join(ADDITIONAL_DATA, image_type[1:])\n",
        "    else:\n",
        "        raise Exception(\"Image type '%s' is not recognized\" % image_type)\n",
        "\n",
        "    ext = 'jpg'\n",
        "    return os.path.join(data_path, \"{}.{}\".format(image_id, ext))\n",
        "\n",
        "\n",
        "def get_image_data(image_id, image_type):\n",
        "    \"\"\"\n",
        "    Method to get image data as np.array specifying image id and type\n",
        "    \"\"\"\n",
        "    fname = get_filename(image_id, image_type)\n",
        "    img = cv2.imread(fname)\n",
        "    assert img is not None, \"Failed to read image : %s, %s\" % (image_id, image_type)\n",
        "    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n",
        "    return img"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "73597458-63f1-42c9-fccb-104953aeb4bf"
      },
      "outputs": [],
      "source": [
        "import matplotlib.pylab as plt\n",
        "\n",
        "def plt_st(l1,l2):\n",
        "    plt.figure(figsize=(l1,l2))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "_cell_guid": "0519c890-f4b0-00d2-03de-c466eb3e47a6"
      },
      "source": [
        "## Display all train images of Type_1, Type_2, Type_3"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "ebb9981e-51e6-0bce-7560-505152199dc0"
      },
      "outputs": [],
      "source": [
        "tile_size = (256, 256)\n",
        "n = 15\n",
        "\n",
        "complete_images = []\n",
        "for k, type_ids in enumerate([type_1_ids, type_2_ids, type_3_ids]):\n",
        "    m = int(np.ceil(len(type_ids) * 1.0 / n))\n",
        "    complete_image = np.zeros((m*(tile_size[0]+2), n*(tile_size[1]+2), 3), dtype=np.uint8)\n",
        "    train_ids = sorted(type_ids)\n",
        "    counter = 0\n",
        "    for i in range(m):\n",
        "        ys = i*(tile_size[1] + 2)\n",
        "        ye = ys + tile_size[1]\n",
        "        for j in range(n):\n",
        "            xs = j*(tile_size[0] + 2)\n",
        "            xe = xs + tile_size[0]\n",
        "            if counter == len(train_ids):\n",
        "                break\n",
        "            image_id = train_ids[counter]; counter+=1\n",
        "            img = get_image_data(image_id, 'Type_%i' % (k+1))\n",
        "            img = cv2.resize(img, dsize=tile_size)\n",
        "            img = cv2.putText(img, image_id, (5,img.shape[0] - 5), cv2.FONT_HERSHEY_SIMPLEX, 2.0, (255, 255, 255), thickness=3)\n",
        "            complete_image[ys:ye, xs:xe, :] = img[:,:,:]\n",
        "        if counter == len(train_ids):\n",
        "            break\n",
        "    complete_images.append(complete_image)           "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "19d6c251-a771-ad13-a8b3-cabedd0ee402"
      },
      "outputs": [],
      "source": [
        "plt_st(20, 20)\n",
        "plt.imshow(complete_images[0])\n",
        "plt.title(\"Training dataset of type %i\" % (1))"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "a1ba4b31-428a-6d50-5677-dbde8b85d243"
      },
      "outputs": [],
      "source": [
        "index = 1\n",
        "m = complete_images[index].shape[0] / (tile_size[0] + 2)\n",
        "n = int(np.ceil(m / 20.0))\n",
        "for i in range(n):\n",
        "    plt_st(20, 20)\n",
        "    ys = i*(tile_size[0] + 2)*20\n",
        "    ye = min((i+1)*(tile_size[0] + 2)*20, complete_images[index].shape[0])\n",
        "    plt.imshow(complete_images[index][ys:ye,:,:])\n",
        "    plt.title(\"Training dataset of type %i, part %i\" % (index + 1, i))"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "c087ff0a-bcdb-e823-9319-b0a9bec49d61"
      },
      "outputs": [],
      "source": [
        "index = 2\n",
        "m = complete_images[index].shape[0] / (tile_size[0] + 2)\n",
        "n = int(np.ceil(m / 20.0))\n",
        "for i in range(n):\n",
        "    plt_st(20, 20)\n",
        "    ys = i*(tile_size[0] + 2)*20\n",
        "    ye = min((i+1)*(tile_size[0] + 2)*20, complete_images[index].shape[0])\n",
        "    plt.imshow(complete_images[index][ys:ye,:,:])\n",
        "    plt.title(\"Training dataset of type %i, part %i\" % (index + 1, i))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "_cell_guid": "902b1037-0846-ca12-b628-e15ce07fba18"
      },
      "source": [
        "### Display all test images"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "470cb510-1bfa-04db-82fb-cc5c94cca1d4"
      },
      "outputs": [],
      "source": [
        "tile_size = (256, 256)\n",
        "n = 15\n",
        "m = int(np.ceil(len(test_ids) * 1.0 / n))\n",
        "complete_test_image = np.zeros((m*(tile_size[0]+2), n*(tile_size[1]+2), 3), dtype=np.uint8)\n",
        "counter = 0\n",
        "for i in range(m):\n",
        "    ys = i*(tile_size[1] + 2)\n",
        "    ye = ys + tile_size[1]\n",
        "    for j in range(n):\n",
        "        xs = j*(tile_size[0] + 2)\n",
        "        xe = xs + tile_size[0]\n",
        "        if counter == len(test_ids):\n",
        "            break\n",
        "        image_id = test_ids[counter]; counter+=1\n",
        "        img = get_image_data(image_id, 'Test')\n",
        "        img = cv2.resize(img, dsize=tile_size)\n",
        "        img = cv2.putText(img, image_id, (5,img.shape[0] - 5), cv2.FONT_HERSHEY_SIMPLEX, 2.0, (255, 255, 255), thickness=3)\n",
        "        complete_test_image[ys:ye, xs:xe, :] = img[:,:,:]\n",
        "    if counter == len(test_ids):\n",
        "        break"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "5c941d6f-2e27-81fd-5db1-2417e7f7ea5d"
      },
      "outputs": [],
      "source": [
        "m = complete_test_image.shape[0] / (tile_size[0] + 2)\n",
        "n = int(np.ceil(m / 20.0))\n",
        "for i in range(n):\n",
        "    plt_st(20, 20)\n",
        "    ys = i*(tile_size[0] + 2)*20\n",
        "    ye = min((i+1)*(tile_size[0] + 2)*20, complete_test_image.shape[0])\n",
        "    plt.imshow(complete_test_image[ys:ye,:,:])\n",
        "    plt.title(\"Test dataset, part %i\" % (i))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "_cell_guid": "ae360dea-8473-72e5-bf15-34f98168802f"
      },
      "source": [
        "## Display 500 addtional train images of Type_1, Type_2, Type_3"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "a9a627cd-f77d-992e-ceef-6fbfa06150cb"
      },
      "outputs": [],
      "source": [
        "tile_size = (256, 256)\n",
        "n = 15\n",
        "ll = 500\n",
        "complete_images = []\n",
        "for k, type_ids in enumerate([additional_type_1_ids[:ll], additional_type_2_ids[:ll], additional_type_3_ids[:ll]]):\n",
        "    m = int(np.ceil(len(type_ids) * 1.0 / n))\n",
        "    complete_image = np.zeros((m*(tile_size[0]+2), n*(tile_size[1]+2), 3), dtype=np.uint8)\n",
        "    train_ids = sorted(type_ids)\n",
        "    counter = 0\n",
        "    for i in range(m):\n",
        "        ys = i*(tile_size[1] + 2)\n",
        "        ye = ys + tile_size[1]\n",
        "        for j in range(n):\n",
        "            xs = j*(tile_size[0] + 2)\n",
        "            xe = xs + tile_size[0]\n",
        "            if counter == len(train_ids):\n",
        "                break\n",
        "            image_id = train_ids[counter]; counter+=1\n",
        "            img = get_image_data(image_id, 'AType_%i' % (k+1))\n",
        "            img = cv2.resize(img, dsize=tile_size)\n",
        "            img = cv2.putText(img, image_id, (5,img.shape[0] - 5), cv2.FONT_HERSHEY_SIMPLEX, 2.0, (255, 255, 255), thickness=3)\n",
        "            complete_image[ys:ye, xs:xe, :] = img[:,:,:]\n",
        "        if counter == len(train_ids):\n",
        "            break\n",
        "    complete_images.append(complete_image)       "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "be57bd27-2106-7193-8254-dfb6cff4f0bf"
      },
      "outputs": [],
      "source": [
        "index = 0\n",
        "m = complete_images[index].shape[0] / (tile_size[0] + 2)\n",
        "n = int(np.ceil(m / 15.0))\n",
        "for i in range(n):\n",
        "    plt_st(20, 20)\n",
        "    ys = i*(tile_size[0] + 2)*15\n",
        "    ye = min((i+1)*(tile_size[0] + 2)*15, complete_images[index].shape[0])\n",
        "    plt.imshow(complete_images[index][ys:ye,:,:])\n",
        "    plt.title(\"Additional Training dataset (500 images) of type %i, part %i\" % (index + 1, i))"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "5155c64b-eabf-725e-3dcb-79877f39ea55"
      },
      "outputs": [],
      "source": [
        "index = 1\n",
        "m = complete_images[index].shape[0] / (tile_size[0] + 2)\n",
        "n = int(np.ceil(m / 15.0))\n",
        "for i in range(n):\n",
        "    plt_st(20, 20)\n",
        "    ys = i*(tile_size[0] + 2)*15\n",
        "    ye = min((i+1)*(tile_size[0] + 2)*15, complete_images[index].shape[0])\n",
        "    plt.imshow(complete_images[index][ys:ye,:,:])\n",
        "    plt.title(\"Additional Training dataset (500 images) of type %i, part %i\" % (index + 1, i))"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "f8059659-22e0-f7af-0ab7-d1286773e0e9"
      },
      "outputs": [],
      "source": [
        "index = 2\n",
        "m = complete_images[index].shape[0] / (tile_size[0] + 2)\n",
        "n = int(np.ceil(m / 15.0))\n",
        "for i in range(n):\n",
        "    plt_st(20, 20)\n",
        "    ys = i*(tile_size[0] + 2)*15\n",
        "    ye = min((i+1)*(tile_size[0] + 2)*15, complete_images[index].shape[0])\n",
        "    plt.imshow(complete_images[index][ys:ye,:,:])\n",
        "    plt.title(\"Additional Training dataset (500 images) of type %i, part %i\" % (index + 1, i))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "_cell_guid": "98f68fed-10fd-c499-cb08-52e8b68abb0b"
      },
      "source": [
        "## Basic skin detection"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "d954848f-6fd8-e644-6cd9-645b77130495"
      },
      "outputs": [],
      "source": [
        "img_1 = get_image_data('1023', 'Type_1')\n",
        "img_2 = get_image_data('531', 'Type_1')\n",
        "img_3 = get_image_data('596', 'Type_1')\n",
        "img_4 = get_image_data('1061', 'Type_1')\n",
        "img_5 = get_image_data('1365', 'Type_2')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "5e786612-1d1d-9903-ba5e-b2403c285444"
      },
      "outputs": [],
      "source": [
        "def sieve(image, size):\n",
        "    \"\"\"\n",
        "    Filter removes small objects of 'size' from binary image\n",
        "    Input image should be a single band image of type np.uint8\n",
        "    Idea : use Opencv findContours\n",
        "    \"\"\"\n",
        "    sqLimit = size**2\n",
        "    linLimit = size*4\n",
        "    outImage = image.copy()\n",
        "    image, contours, hierarchy = cv2.findContours(image.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)\n",
        "    if len(hierarchy) > 0:\n",
        "        hierarchy = hierarchy[0]\n",
        "        index = 0\n",
        "        while index >= 0:\n",
        "            contour = contours[index]\n",
        "            p = cv2.arcLength(contour, True)\n",
        "            s = cv2.contourArea(contour)\n",
        "            r = cv2.boundingRect(contour)\n",
        "            if s <= sqLimit and p <= linLimit:\n",
        "                outImage[r[1]:r[1]+r[3], r[0]:r[0]+r[2]] = 0\n",
        "            index = hierarchy[index][0]\n",
        "    else:\n",
        "        pass\n",
        "        # print(\"No contours found\")\n",
        "    return outImage\n",
        "\n",
        "\n",
        "# in HSV :\n",
        "skin_range_1_min = np.array([120, 0, 0], dtype=np.uint8)\n",
        "skin_range_1_max = np.array([255, 255, 255], dtype=np.uint8)\n",
        "\n",
        "skin_range_2_min = np.array([0, 0, 0], dtype=np.uint8)\n",
        "skin_range_2_max = np.array([45, 255, 255], dtype=np.uint8)\n",
        "\n",
        "skin_kernel_size = 7\n",
        "skin_sieve_min_size = 5\n",
        "\n",
        "def detect_skin(image):\n",
        "    proc = cv2.medianBlur(image, 7)\n",
        "    ### Detect skin\n",
        "    image_hsv = cv2.cvtColor(proc, cv2.COLOR_RGB2HSV)\n",
        "    skin_like_mask = cv2.inRange(image_hsv, skin_range_1_min, skin_range_1_max)\n",
        "    skin_like_mask_2 = cv2.inRange(image_hsv, skin_range_2_min, skin_range_2_max)\n",
        "    skin_like_mask = cv2.bitwise_or(skin_like_mask, skin_like_mask_2)    \n",
        "    # Filter the skin mask :\n",
        "    skin_mask = sieve(skin_like_mask, skin_sieve_min_size)\n",
        "    kernel = np.ones((skin_kernel_size, skin_kernel_size), dtype=np.int8)\n",
        "    skin_mask = cv2.morphologyEx(skin_mask, cv2.MORPH_CLOSE, kernel)    \n",
        "    # Apply skin mask\n",
        "    skin_segm_rgb = cv2.bitwise_and(image, image, mask=skin_mask)\n",
        "    return skin_segm_rgb\n",
        "\n",
        "for image in [img_1, img_2, img_3, img_4, img_5]:       \n",
        "    image = cv2.resize(image, dsize=(512, 512))\n",
        "    skin_segm_rgb = detect_skin(image)\n",
        "    plt_st(12, 4)\n",
        "    plt.subplot(121)\n",
        "    plt.title(\"Original image\")    \n",
        "    plt.imshow(image)\n",
        "    plt.subplot(122)\n",
        "    plt.title(\"Skin segmentation\")\n",
        "    plt.imshow(skin_segm_rgb)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "cda3aa57-8c54-8497-45ba-693874a1251d"
      },
      "outputs": [],
      "source": [
        "tile_size = (256, 256)\n",
        "n = 15\n",
        "\n",
        "complete_images = []\n",
        "for k, type_ids in enumerate([type_1_ids, ]):\n",
        "    m = int(np.floor(len(type_ids) / n))\n",
        "    complete_image = np.zeros((m*(tile_size[0]+2), n*(tile_size[1]+2), 3), dtype=np.uint8)\n",
        "    train_ids = sorted(type_ids)\n",
        "    counter = 0\n",
        "    for i in range(m):\n",
        "        ys = i*(tile_size[1] + 2)\n",
        "        ye = ys + tile_size[1]\n",
        "        for j in range(n):\n",
        "            xs = j*(tile_size[0] + 2)\n",
        "            xe = xs + tile_size[0]\n",
        "            image_id = train_ids[counter]; counter+=1\n",
        "            img = get_image_data(image_id, 'Type_%i' % (k+1))\n",
        "            img = cv2.resize(img, dsize=tile_size)\n",
        "            img = detect_skin(img)\n",
        "            img = cv2.putText(img, image_id, (5,img.shape[0] - 5), cv2.FONT_HERSHEY_SIMPLEX, 2.0, (255, 255, 255), thickness=3)\n",
        "            complete_image[ys:ye, xs:xe, :] = img[:,:,:]\n",
        "    complete_images.append(complete_image)    "
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "_cell_guid": "b429d2b1-99b2-1fbf-b2a8-5448ae524c5a"
      },
      "source": [
        "### Apply skin segmentation on all training data and visualize the result"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "d0d6ed51-b54f-9599-3d1f-9b9cb3d6fa5d"
      },
      "outputs": [],
      "source": [
        "plt_st(20, 20)\n",
        "plt.imshow(complete_images[0])\n",
        "plt.title(\"Training dataset of type %i\" % (0))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "_cell_guid": "71ebc9c0-0f9b-d9f7-8ea3-4cbab409f253"
      },
      "source": [
        "## Clustering\n",
        "\n",
        "- Take a number of images from all classified images and test images\n",
        "- Compute histogram on hue channel\n",
        "- Perform 5 classes clustering on the data "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "36027043-6945-bf2b-2bdc-ac24d79d9143"
      },
      "outputs": [],
      "source": [
        "def compute_histogram(img, hist_size=100):\n",
        "    hist = cv2.calcHist([img], [0], mask=None, histSize=[hist_size], ranges=(0, 255))\n",
        "    hist = cv2.normalize(hist, dst=hist)\n",
        "    return hist\n",
        "\n",
        "#for image in [img_1, img_2, img_3, img_4, img_5]:       \n",
        "#    image = cv2.resize(image, dsize=(512, 512))    \n",
        "#    hue = cv2.cvtColor(image, cv2.COLOR_RGB2HSV)[:,:,0]\n",
        "#    hist = compute_histogram(hue)\n",
        "#    plt_st(12, 4)\n",
        "#    plt.subplot(131)\n",
        "#    plt.title(\"Original image\")    \n",
        "#    plt.imshow(image)\n",
        "#    plt.subplot(132)\n",
        "#    plt.title(\"Hue\")    \n",
        "#    plt.imshow(hue, cmap='gray')\n",
        "#    plt.subplot(133)\n",
        "#    plt.title(\"Histogram\")\n",
        "#    plt.plot(hist)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "7fed17f0-6c5a-f607-3cb0-1c419d90c673"
      },
      "outputs": [],
      "source": [
        "train_nb_samples = 100\n",
        "type_ids=(type_1_ids, type_2_ids, type_3_ids, test_ids)\n",
        "image_types = [\"Type_1\", \"Type_2\", \"Type_3\", \"Test\"]\n",
        "ll = [int(len(ids)) for ids in type_ids]\n",
        "\n",
        "count = 0\n",
        "train_id_type_list = []\n",
        "while count < train_nb_samples:\n",
        "    for l, ids, image_type in zip(ll, type_ids, image_types):\n",
        "        image_id = ids[count % l]\n",
        "        train_id_type_list.append((image_id, image_type))\n",
        "    count += 1"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "b1a19394-f2c0-1490-6d87-6d6e6093ef02"
      },
      "outputs": [],
      "source": [
        "image_size = (256, 256)\n",
        "hist_size = 100\n",
        "X = np.zeros((len(train_id_type_list), hist_size), dtype=np.float32)\n",
        "Y = np.zeros((len(train_id_type_list), 2), dtype=np.float32)\n",
        "for i, (image_id, image_type) in enumerate(train_id_type_list):\n",
        "    img = get_image_data(image_id, image_type)\n",
        "    img = cv2.resize(img, dsize=image_size[::-1])\n",
        "    hue = cv2.cvtColor(img, cv2.COLOR_RGB2HSV)[:,:,0]\n",
        "    hist = compute_histogram(hue, hist_size)    \n",
        "    X[i, :] = hist[:, 0]\n",
        "    Y[i, :] = (hist.mean(), hist.std())"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "648bc088-0473-d86d-62ff-b888da52b828"
      },
      "outputs": [],
      "source": [
        "plt.title(\"Image Hue Histogram std vs mean\")\n",
        "plt.scatter(Y[:, 0], Y[:, 1], s=50, cmap='viridis');"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "4a8d6762-0d93-fa88-1f6e-8a2f56a257a7"
      },
      "outputs": [],
      "source": [
        "np_classes = 5"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "93a8db25-4de8-cf3a-fb72-9090428d1424"
      },
      "outputs": [],
      "source": [
        "#from sklearn.cluster import KMeans\n",
        "#kmeans = KMeans(n_clusters=np_classes)\n",
        "#kmeans.fit(X)\n",
        "#y_kmeans = kmeans.predict(X)\n",
        "#_ = plt.hist(y_kmeans)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "45d399a3-37af-e5d1-6a5c-4c4aa53b0f26"
      },
      "outputs": [],
      "source": [
        "from sklearn.cluster import SpectralClustering\n",
        "model = SpectralClustering(n_clusters=np_classes, affinity='nearest_neighbors', assign_labels='kmeans')\n",
        "y_spectral = model.fit_predict(X)\n",
        "_ = plt.hist(y_spectral)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "4542dc9e-c7b1-a8a2-894d-456e617721fd"
      },
      "outputs": [],
      "source": [
        "image_size = (256, 256)\n",
        "all_classes_images = []\n",
        "for class_index in range(np_classes):\n",
        "    \n",
        "    class_indices = np.where(y_spectral == class_index)[0]\n",
        "    n = 10    \n",
        "    m = int(np.ceil(len(class_indices) / n)) \n",
        "    one_class_image = np.zeros((m*(image_size[0]+2), n*(image_size[1]+2), 3), dtype=np.uint8)    \n",
        "    \n",
        "    counter = 0\n",
        "    for i in range(m):\n",
        "        ys = i*(image_size[1] + 2)\n",
        "        ye = ys + image_size[1]\n",
        "        for j in range(n):\n",
        "            xs = j*(image_size[0] + 2)\n",
        "            xe = xs + image_size[0]\n",
        "            if counter == len(class_indices):\n",
        "                break\n",
        "            image_id, image_type = train_id_type_list[class_indices[counter]]; counter+=1\n",
        "            img = get_image_data(image_id, image_type)\n",
        "            img = cv2.resize(img, dsize=image_size)\n",
        "            img = cv2.putText(img, image_id + ' | ' + str(image_type) + ' | ' + str(class_index), (5,img.shape[0] - 5), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (255, 255, 255), thickness=2)\n",
        "            one_class_image[ys:ye, xs:xe, :] = img[:,:,:]\n",
        "\n",
        "        if counter == len(class_indices):\n",
        "            break\n",
        "    \n",
        "    all_classes_images.append(one_class_image)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "45ec1f8f-8be6-65a7-adc4-991f33930e16"
      },
      "outputs": [],
      "source": [
        "for class_index in range(np_classes):\n",
        "    plt_st(20, 20)\n",
        "    plt.imshow(all_classes_images[class_index])\n",
        "    plt.title(\"Class %i\" % (class_index)) "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "834ef6ca-a2fd-6273-e004-945124e3835b"
      },
      "outputs": [],
      "source": [
        ""
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "_cell_guid": "6a9df9de-92f0-c38c-a3f9-e0c56a4e9ec8"
      },
      "source": [
        "## Some stats using jpg exif\n",
        "\n",
        "We can explore metadata of all these images. If exif metadata is present in images, we can found out camera name, camera type, acquisition date and time etc."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "234a1824-f994-b74d-ea27-49d0b617c7e2"
      },
      "outputs": [],
      "source": [
        "from PIL import Image\n",
        "import seaborn as sns\n",
        "\n",
        "def _get_image_data_pil(image_id, image_type, return_exif_md=False):\n",
        "    \"\"\"\n",
        "    Method to get image data as np.array specifying image id and type\n",
        "    \"\"\"\n",
        "    fname = get_filename(image_id, image_type)\n",
        "    try:\n",
        "        img_pil = Image.open(fname)\n",
        "    except Exception as e:\n",
        "        assert False, \"Failed to read image : %s, %s. Error message: %s\" % (image_id, image_type, e)\n",
        "\n",
        "    img = np.asarray(img_pil)\n",
        "    assert isinstance(img, np.ndarray), \"Open image is not an ndarray. Image id/type : %s, %s\" % (image_id, image_type)\n",
        "    if not return_exif_md:\n",
        "        return img\n",
        "    else:\n",
        "        return img, img_pil._getexif()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "ca93bb0b-fde1-d4a7-b3ca-2826196df0da"
      },
      "outputs": [],
      "source": [
        "exif_stats = pd.DataFrame(columns=['Image_id', 'Image_type', 'Camera_name', 'Camera_type', 'Datetime', 'ISO'])\n",
        "\n",
        "type_ids=(type_1_ids, type_2_ids, type_3_ids, test_ids)\n",
        "image_types = [\"Type_1\", \"Type_2\", \"Type_3\", \"Test\"]\n",
        "\n",
        "counter = 0\n",
        "for ids, image_type in zip(type_ids, image_types):\n",
        "    print('--', image_type)\n",
        "    for image_id in ids:\n",
        "        img, exif_data = _get_image_data_pil(image_id, image_type, return_exif_md=True)\n",
        "        if isinstance(exif_data, dict):\n",
        "            exif_stats.loc[counter, :] = [image_id, image_type, \n",
        "                                          exif_data[271], \n",
        "                                          exif_data[272], \n",
        "                                          exif_data[306],\n",
        "                                          exif_data[34855]] \n",
        "        else:            \n",
        "            exif_stats.loc[counter, :] = [image_id, image_type, \n",
        "                                          'NA', \n",
        "                                          'NA', \n",
        "                                          'NA', \n",
        "                                          'NA'] \n",
        "        counter+=1"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "624db981-469c-d770-8b4b-bf5e9a48d52b"
      },
      "outputs": [],
      "source": [
        "exif_stats['Camera_name'] = exif_stats['Camera_name'].str.lower()\n",
        "exif_stats['YMD'] = exif_stats['Datetime'].apply(lambda x: x[:10])\n",
        "data_mask = exif_stats['Camera_name'] != 'na'"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "b2fd2952-a7f4-3616-51b0-687a8f85eff2"
      },
      "outputs": [],
      "source": [
        "exif_stats.head(10)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "179f7a1a-2531-c33e-0fc1-becf3c9f96de"
      },
      "outputs": [],
      "source": [
        "sns.countplot(data=exif_stats, x='Camera_name', hue='Image_type')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "fb56802a-5d1b-57fc-18c0-a2c93ecb5969"
      },
      "outputs": [],
      "source": [
        "plt_st(12, 12)\n",
        "sns.countplot(data=exif_stats[data_mask].sort_values(['YMD']), y='YMD')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "af181e08-61e8-47a5-5476-dba26b55d237"
      },
      "outputs": [],
      "source": [
        ""
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "2f0faf70-6b1e-0ce9-0a83-2a5ac14038aa"
      },
      "outputs": [],
      "source": [
        ""
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "a1079751-d6ef-95a5-7fe1-697fedc2a957"
      },
      "outputs": [],
      "source": [
        ""
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "059fa343-d05e-ab50-05a5-34d15c8e3024"
      },
      "outputs": [],
      "source": [
        ""
      ]
    }
  ],
  "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
}