{"metadata": {"kernelspec": {"name": "python3", "language": "python", "display_name": "Python 3"}, "language_info": {"name": "python", "mimetype": "text/x-python", "pygments_lexer": "ipython3", "file_extension": ".py", "version": "3.6.4", "nbconvert_exporter": "python", "codemirror_mode": {"name": "ipython", "version": 3}}}, "cells": [{"source": ["# Overview\n", "The competition involves a number of different image modalities and so this kernel tries to make them all look similar so we can perform nucleus detection using a single model (which can later be trained)"], "cell_type": "markdown", "metadata": {"_cell_guid": "a98e3d69-8cd9-4390-b26a-6f59669598b1", "_uuid": "5db17699cd869f1ddbf48ba3a6c2201fd2614b0c"}}, {"source": ["import numpy as np # linear algebra\n", "import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n", "from glob import glob\n", "import os\n", "from skimage.io import imread\n", "import matplotlib.pyplot as plt\n", "import seaborn as sns\n", "%matplotlib inline\n", "dsb_data_dir = os.path.join('..', 'input')\n", "stage_label = 'stage1'"], "cell_type": "code", "execution_count": null, "outputs": [], "metadata": {"_cell_guid": "1aa2cf84-25e3-46de-990c-30dd52398467", "collapsed": true, "_uuid": "be235a65746e3e4f5f3509644b0cea8a16cbbfaa"}}, {"source": ["all_images = glob(os.path.join(dsb_data_dir, 'stage1_*', '*', '*', '*.png'))\n", "img_df = pd.DataFrame({'path': all_images})\n", "img_id = lambda in_path: in_path.split('/')[-3]\n", "img_type = lambda in_path: in_path.split('/')[-2]\n", "img_group = lambda in_path: in_path.split('/')[-4].split('_')[1]\n", "img_stage = lambda in_path: in_path.split('/')[-4].split('_')[0]\n", "img_df['ImageId'] = img_df['path'].map(img_id)\n", "img_df['ImageType'] = img_df['path'].map(img_type)\n", "img_df['TrainingSplit'] = img_df['path'].map(img_group)\n", "img_df['Stage'] = img_df['path'].map(img_stage)\n", "# we don't want any masks\n", "img_df = img_df.query('ImageType==\"images\"').drop(['ImageType'],1)\n", "img_df.sample(2)"], "cell_type": "code", "execution_count": null, "outputs": [], "metadata": {"_cell_guid": "f4e6c5cc-288d-46fa-b210-97f84580b5a6", "collapsed": true, "_uuid": "4e666e3f34f6705721a0e285c761b3adb1b0e059"}}, {"source": ["# Load in all the data"], "cell_type": "markdown", "metadata": {"_cell_guid": "274a2949-8448-4b65-8c28-670f78989121", "_uuid": "3f5af01cab030068412e92fb48f8322351740e17"}}, {"source": ["%%time\n", "img_df['images'] = img_df['path'].map(imread)\n", "img_df.drop(['path'],1, inplace = True)\n", "img_df.sample(1)"], "cell_type": "code", "execution_count": null, "outputs": [], "metadata": {"_cell_guid": "cf5bf735-fd88-4868-8523-943851a36033", "collapsed": true, "_uuid": "859a1b5eee975ad535a12681bae53238a52a83c8"}}, {"source": ["# Create Color Features\n", "Here we create color features and see if there are any differences betweeen our training and testing sets"], "cell_type": "markdown", "metadata": {"_cell_guid": "55e7f216-c4ff-445d-af88-5638c171eb11", "_uuid": "fbb7ae5e4537381b24d337a23f1fdc8784fc401e"}}, {"source": ["color_features_names = ['Gray', 'Red', 'Green', 'Blue', 'Red-Green',  'Red-Green-Sd']\n", "def create_color_features(in_df):\n", "    in_df['Red'] = in_df['images'].map(lambda x: np.mean(x[:,:,0]))\n", "    in_df['Green'] = in_df['images'].map(lambda x: np.mean(x[:,:,1]))\n", "    in_df['Blue'] = in_df['images'].map(lambda x: np.mean(x[:,:,2]))\n", "    in_df['Gray'] = in_df['images'].map(lambda x: np.mean(x))\n", "    in_df['Red-Green'] = in_df['images'].map(lambda x: np.mean(x[:,:,0]-x[:,:,1]))\n", "    in_df['Red-Green-Sd'] = in_df['images'].map(lambda x: np.std(x[:,:,0]-x[:,:,1]))\n", "    return in_df\n", "\n", "img_df = create_color_features(img_df)\n", "sns.pairplot(img_df[color_features_names+['TrainingSplit']], \n", "             hue = 'TrainingSplit')"], "cell_type": "code", "execution_count": null, "outputs": [], "metadata": {"_cell_guid": "5d939ca6-0365-4d8b-ac38-4144f7784143", "collapsed": true, "_uuid": "08e95c5d0c64dbd433302cb4471c520bc7105bcb"}}, {"source": ["we see that there are definitely some types of images in our data which are different between the training and testing. We also see there are a number of different types of groups"], "cell_type": "markdown", "metadata": {"_cell_guid": "a3c0ecdc-9038-4600-aa0f-d88d2fd39cee", "_uuid": "2a14193ad0ad44951078033d3392f2d84254d258"}}, {"source": ["from sklearn.cluster import KMeans\n", "from string import ascii_lowercase\n", "\n", "def create_color_cluster(in_df, cluster_maker = None, cluster_count = 3):\n", "    if cluster_maker is None:\n", "        cluster_maker = KMeans(cluster_count)\n", "        cluster_maker.fit(in_df[['Green', 'Red-Green', 'Red-Green-Sd']])\n", "        \n", "    in_df['cluster-id'] = np.argmin(\n", "        cluster_maker.transform(in_df[['Green', 'Red-Green', 'Red-Green-Sd']]),\n", "        -1)\n", "    in_df['cluster-id'] = in_df['cluster-id'].map(lambda x: ascii_lowercase[x])\n", "    return in_df, cluster_maker\n", "\n", "img_df, train_cluster_maker = create_color_cluster(img_df, cluster_count=4)\n", "sns.pairplot(img_df,\n", "             vars = ['Green', 'Red-Green', 'Red-Green-Sd'], \n", "             hue = 'cluster-id')"], "cell_type": "code", "execution_count": null, "outputs": [], "metadata": {"_cell_guid": "3f9752d2-d324-4591-ac1d-50c02deddc14", "collapsed": true, "_uuid": "7308ab504b5584f4a1b70933120867e8fba732e2"}}, {"source": ["# Show Sample Images\n", "Here we show some sample images from each group"], "cell_type": "markdown", "metadata": {"_cell_guid": "d2a4b267-37d4-4605-bf03-02e850ad15f4", "_uuid": "f79d2b1aa791514b32fb2e52d3bc49e56c3b3468"}}, {"source": ["n_img = 3\n", "grouper = img_df.groupby(['cluster-id', 'TrainingSplit'])\n", "fig, m_axs = plt.subplots(n_img, len(grouper), \n", "                          figsize = (20, 4))\n", "for (c_group, clus_group), c_ims in zip(grouper, \n", "                                     m_axs.T):\n", "    c_ims[0].set_title('Group: {}\\nSplit: {}'.format(*c_group))\n", "    for (_, clus_row), c_im in zip(clus_group.sample(n_img, replace = True).iterrows(), c_ims):\n", "        c_im.imshow(clus_row['images'])\n", "        c_im.axis('off')\n", "fig.savefig('messy_overview.png')"], "cell_type": "code", "execution_count": null, "outputs": [], "metadata": {"_cell_guid": "a6a61890-36f4-471b-b362-53c64c867c37", "collapsed": true, "_uuid": "78660dce4b66af0de14799ecc36c748586da3bef"}}, {"source": ["So we evidently have more than 4 groups and the testing and training data look very, very different"], "cell_type": "markdown", "metadata": {"_cell_guid": "b5a4a10a-5f26-458d-9eb4-6f2a902c5bb2", "_uuid": "9a3eb253d0ac83d9a28ec863d19b7d8cf0d09cd8"}}, {"source": ["# Experimental Subset\n", "Here we make a small subset of the data to experiment with"], "cell_type": "markdown", "metadata": {"_cell_guid": "5a3cce4f-1691-4746-900b-05dea4a4a948", "_uuid": "a1b8e5e3f9346e3add4ad070c81990e6562d9e1e"}}, {"source": ["tiny_img_df = grouper.apply(lambda x: x.sample(n_img if n_img<x.shape[0] else x.shape[0])\n", "                           ).reset_index(drop=True).drop(color_features_names, 1).sort_values(['cluster-id', 'TrainingSplit'])\n", "print(tiny_img_df.shape[0], 'images to experiment with')\n", "tiny_img_df.sample(2)"], "cell_type": "code", "execution_count": null, "outputs": [], "metadata": {"_cell_guid": "17df4bd9-01a2-4f1e-8a86-c8c6214b3901", "collapsed": true, "_uuid": "5e6ca8ececa3948df1d5f884c134594cd3d99622"}}, {"source": ["def show_test_img(in_df, in_col):\n", "    plt_cols = tiny_img_df.shape[0]//4\n", "    fig, m_axs = plt.subplots(4, plt_cols, figsize = (12, 12))\n", "    for c_ax, (_, c_row) in zip(m_axs.flatten(), in_df.iterrows()):\n", "        c_ax.imshow(c_row[in_col])\n", "        c_ax.axis('off')\n", "        c_ax.set_title('K:{cluster-id} T:{TrainingSplit}'.format(**c_row))\n", "show_test_img(tiny_img_df, 'images')"], "cell_type": "code", "execution_count": null, "outputs": [], "metadata": {"_cell_guid": "7fe08e48-12d8-41cc-95e3-e9ae4e52f70a", "collapsed": true, "_uuid": "8c98d5ac9b195f7e1c8ad84a3b59b60779f84c01"}}, {"source": ["# Histogram Equalization\n", "Does histogram equalization help us? For this we use CLAHE on the RGB data, thanks [StackOverflow](https://stackoverflow.com/questions/25008458/how-to-apply-clahe-on-rgb-color-images)"], "cell_type": "markdown", "metadata": {"_cell_guid": "e0330068-879d-4ec4-9f4b-64fa8ea5939b", "_uuid": "1743f31368da8c67fa6197f621a868f2c48141b4"}}, {"source": ["import cv2\n", "grid_size = 8\n", "def rgb_clahe(in_rgb_img): \n", "    bgr = in_rgb_img[:,:,[2,1,0]] # flip r and b\n", "    lab = cv2.cvtColor(bgr, cv2.COLOR_BGR2LAB)\n", "    clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(grid_size,grid_size))\n", "    lab[:,:,0] = clahe.apply(lab[:,:,0])\n", "    bgr = cv2.cvtColor(lab, cv2.COLOR_LAB2BGR)\n", "    return bgr[:,:,[2,1,0]]"], "cell_type": "code", "execution_count": null, "outputs": [], "metadata": {"_cell_guid": "043613bb-9e0c-4da0-b335-c85aed7a6013", "collapsed": true, "_uuid": "7c32a4362add46f22ab7a34cc46ebcf287896183"}}, {"source": ["tiny_img_df['clahe_lab'] = tiny_img_df['images'].map(rgb_clahe)"], "cell_type": "code", "execution_count": null, "outputs": [], "metadata": {"_cell_guid": "9f1ad631-6e5a-40c9-ac76-fae0b23a4f28", "collapsed": true, "_uuid": "efd71b08960e065bf044aeb24685a0fae26c4185"}}, {"source": ["show_test_img(tiny_img_df, 'clahe_lab')"], "cell_type": "code", "execution_count": null, "outputs": [], "metadata": {"_cell_guid": "2363700d-1515-43e8-8ccd-b68025653583", "collapsed": true, "_uuid": "89ba2c327711a04a323f8d2459373c21728ce41c"}}, {"source": ["# Just extract L?\n", "Instead of recreating the color image maybe just keep the L channel"], "cell_type": "markdown", "metadata": {"_cell_guid": "d054377f-de03-4a96-95df-b8a2009868f1", "_uuid": "81b63f6b3fb790c7904fa36ece01e9e2257f4345"}}, {"source": ["def rgb_clahe_justl(in_rgb_img): \n", "    bgr = in_rgb_img[:,:,[2,1,0]] # flip r and b\n", "    lab = cv2.cvtColor(bgr, cv2.COLOR_BGR2LAB)\n", "    clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(grid_size,grid_size))\n", "    return clahe.apply(lab[:,:,0])\n", "tiny_img_df['clahe_justl'] = tiny_img_df['images'].map(rgb_clahe_justl)"], "cell_type": "code", "execution_count": null, "outputs": [], "metadata": {"_cell_guid": "98185c88-3384-4dbc-808d-f58d48486956", "collapsed": true, "_uuid": "f883c5947964302a936fbfc02c2a887e2b32f9bc"}}, {"source": ["show_test_img(tiny_img_df, 'clahe_justl')"], "cell_type": "code", "execution_count": null, "outputs": [], "metadata": {"_cell_guid": "79678bea-1bf1-4dea-8670-ca73531de838", "collapsed": true, "_uuid": "1db5f2f2dcb999870d0e24815d1b0b7dd5dab613"}}, {"source": ["# Invert if the intensity/background is too high?\n"], "cell_type": "markdown", "metadata": {"_cell_guid": "9d19e8ad-2a91-47ee-826e-d182ed6da2e8", "_uuid": "1e4dc6f33dae4b9873e118bfc24643ba2be1d465"}}, {"source": ["tiny_img_df['clahe_justl_flip'] = tiny_img_df['clahe_justl'].map(lambda x: 255-x if x.mean()>127 else x)"], "cell_type": "code", "execution_count": null, "outputs": [], "metadata": {"_cell_guid": "aa7e33c9-2afc-4484-8fe4-91242e593c2d", "collapsed": true, "_uuid": "18643a11768763402f8c57d952fce317ddf8c9c2"}}, {"source": ["show_test_img(tiny_img_df, 'clahe_justl_flip')"], "cell_type": "code", "execution_count": null, "outputs": [], "metadata": {"_cell_guid": "da3b802d-ad57-466d-8aec-95e11d3da789", "collapsed": true, "_uuid": "f7046bd4b04e9927ecdc363e475d5943a04cda22"}}, {"source": ["# Notes\n", "Not perfect but the data seems to be much more homogenous and hopefully easier to build models around"], "cell_type": "markdown", "metadata": {"_cell_guid": "3b3d7465-32fb-4c1f-bf45-9c3dc1f3a13b", "_uuid": "cb6465723298a3ade02bce776c08c9b926c5aa56"}}], "nbformat_minor": 1, "nbformat": 4}