{"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\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport 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\nfrom subprocess import check_output\nprint(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\nfrom glob import glob\nTRAIN_DATA = \"../input/train\"\ntype_1_files = glob(os.path.join(TRAIN_DATA, \"Type_1\", \"*.jpg\"))\ntype_1_ids = np.array([s[len(os.path.join(TRAIN_DATA, \"Type_1\"))+1:-4] for s in type_1_files])\ntype_2_files = glob(os.path.join(TRAIN_DATA, \"Type_2\", \"*.jpg\"))\ntype_2_ids = np.array([s[len(os.path.join(TRAIN_DATA, \"Type_2\"))+1:-4] for s in type_2_files])\ntype_3_files = glob(os.path.join(TRAIN_DATA, \"Type_3\", \"*.jpg\"))\ntype_3_ids = np.array([s[len(os.path.join(TRAIN_DATA, \"Type_3\"))+1:-4] for s in type_3_files])\n\nprint(len(type_1_files), len(type_2_files), len(type_3_files))\nprint(\"Type 1\", type_1_ids[:10])\nprint(\"Type 2\", type_2_ids[:10])\nprint(\"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\"\ntest_files = glob(os.path.join(TEST_DATA, \"*.jpg\"))\ntest_ids = np.array([s[len(TEST_DATA)+1:-4] for s in test_files])\nprint(len(test_ids))\nprint(test_ids[:10])"},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"07f0897f-17e2-f4c0-0b05-ab3f879a7424"},"outputs":[],"source":"ADDITIONAL_DATA = \"../input/additional\"\nadditional_type_1_files = glob(os.path.join(ADDITIONAL_DATA, \"Type_1\", \"*.jpg\"))\nadditional_type_1_ids = np.array([s[len(os.path.join(ADDITIONAL_DATA, \"Type_1\"))+1:-4] for s in additional_type_1_files])\nadditional_type_2_files = glob(os.path.join(ADDITIONAL_DATA, \"Type_2\", \"*.jpg\"))\nadditional_type_2_ids = np.array([s[len(os.path.join(ADDITIONAL_DATA, \"Type_2\"))+1:-4] for s in additional_type_2_files])\nadditional_type_3_files = glob(os.path.join(ADDITIONAL_DATA, \"Type_3\", \"*.jpg\"))\nadditional_type_3_ids = np.array([s[len(os.path.join(ADDITIONAL_DATA, \"Type_3\"))+1:-4] for s in additional_type_3_files])\n\nprint(len(additional_type_1_files), len(additional_type_2_files), len(additional_type_2_files))\nprint(\"Type 1\", additional_type_1_ids[:10])\nprint(\"Type 2\", additional_type_2_ids[:10])\nprint(\"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\ndef 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\ndef 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)\nn = 15\n\ncomplete_images = []\nfor 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)\nplt.imshow(complete_images[0])\nplt.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\nm = complete_images[index].shape[0] / (tile_size[0] + 2)\nn = int(np.ceil(m / 20.0))\nfor 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\nm = complete_images[index].shape[0] / (tile_size[0] + 2)\nn = int(np.ceil(m / 20.0))\nfor 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)\nn = 15\nm = int(np.ceil(len(test_ids) * 1.0 / n))\ncomplete_test_image = np.zeros((m*(tile_size[0]+2), n*(tile_size[1]+2), 3), dtype=np.uint8)\ncounter = 0\nfor 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)\nn = int(np.ceil(m / 20.0))\nfor 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)\nn = 15\nll = 500\ncomplete_images = []\nfor 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\nm = complete_images[index].shape[0] / (tile_size[0] + 2)\nn = int(np.ceil(m / 15.0))\nfor 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\nm = complete_images[index].shape[0] / (tile_size[0] + 2)\nn = int(np.ceil(m / 15.0))\nfor 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\nm = complete_images[index].shape[0] / (tile_size[0] + 2)\nn = int(np.ceil(m / 15.0))\nfor 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')\nimg_2 = get_image_data('531', 'Type_1')\nimg_3 = get_image_data('596', 'Type_1')\nimg_4 = get_image_data('1061', 'Type_1')\nimg_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 :\nskin_range_1_min = np.array([120, 0, 0], dtype=np.uint8)\nskin_range_1_max = np.array([255, 255, 255], dtype=np.uint8)\n\nskin_range_2_min = np.array([0, 0, 0], dtype=np.uint8)\nskin_range_2_max = np.array([45, 255, 255], dtype=np.uint8)\n\nskin_kernel_size = 7\nskin_sieve_min_size = 5\n\ndef 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\nfor 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)\nn = 15\n\ncomplete_images = []\nfor 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)\nplt.imshow(complete_images[0])\nplt.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\ntype_ids=(type_1_ids, type_2_ids, type_3_ids, test_ids)\nimage_types = [\"Type_1\", \"Type_2\", \"Type_3\", \"Test\"]\nll = [int(len(ids)) for ids in type_ids]\n\ncount = 0\ntrain_id_type_list = []\nwhile 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)\nhist_size = 100\nX = np.zeros((len(train_id_type_list), hist_size), dtype=np.float32)\nY = np.zeros((len(train_id_type_list), 2), dtype=np.float32)\nfor 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\")\nplt.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\nmodel = SpectralClustering(n_clusters=np_classes, affinity='nearest_neighbors', assign_labels='kmeans')\ny_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)\nall_classes_images = []\nfor 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\nWe 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\nimport seaborn as sns\n\ndef _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\ntype_ids=(type_1_ids, type_2_ids, type_3_ids, test_ids)\nimage_types = [\"Type_1\", \"Type_2\", \"Type_3\", \"Test\"]\n\ncounter = 0\nfor 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()\nexif_stats['YMD'] = exif_stats['Datetime'].apply(lambda x: x[:10])\ndata_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)\nsns.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}