{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","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)\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\nimport os\nimport seaborn as sns\nprint(os.listdir(\"../input\"))\n\nimport matplotlib.pyplot as plt\n\nfrom PIL import Image, ImageDraw, ImageFont\nimport tensorflow as tf","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"tf.enable_eager_execution()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 1. Load data:"},{"metadata":{},"cell_type":"markdown","source":"## 1.1. Load training data:"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df = pd.read_csv('../input/train.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print('Total records of datatframe: ', len(train_df))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print('Distinct image id:', len(train_df['image_id'].unique()))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"- So the number of unique image in dataframe is also the number of records, which means each image has 1 label row"},{"metadata":{},"cell_type":"markdown","source":"## 1.2. Load unicode translation:\n- Firstly, you have to download the Japanese font\n- This code is used from https://www.kaggle.com/anokas/kuzushiji-visualisation"},{"metadata":{"trusted":true},"cell_type":"code","source":"fontsize = 50\n\n# From https://www.google.com/get/noto/\n!wget -q --show-progress https://noto-website-2.storage.googleapis.com/pkgs/NotoSansCJKjp-hinted.zip\n!unzip -p NotoSansCJKjp-hinted.zip NotoSansCJKjp-Regular.otf > NotoSansCJKjp-Regular.otf\n!rm NotoSansCJKjp-hinted.zip\n\nfont = ImageFont.truetype('./NotoSansCJKjp-Regular.otf', fontsize, encoding='utf-8')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"unicode_map = {codepoint: char for codepoint, char in pd.read_csv('../input/unicode_translation.csv').values}","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print('Total unicode character provided:', len(unicode_map))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":""},{"metadata":{},"cell_type":"markdown","source":"# 2. Quick EDA"},{"metadata":{},"cell_type":"markdown","source":"- Read the data into tensorflow Dataset"},{"metadata":{"trusted":true},"cell_type":"code","source":"def map_name_to_image(image_name):\n    img_raw = tf.io.read_file(tf.strings.join(['../input/train_images/', image_name, '.jpg']))\n    image = tf.image.decode_jpeg(img_raw)\n    return image","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def map_image_to_width_height(image):\n    return tf.shape(image)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"name_ds = tf.data.Dataset.from_tensor_slices(train_df['image_id'])\nimage_ds = name_ds.map(map_name_to_image)\nimage_width_height = image_ds.map(map_image_to_width_height)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for img in image_ds:\n    print(img.shape)\n    break","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"widths = []\nheights = []\nfor width, height, channel in image_width_height:\n    widths.append(width.numpy())\n    heights.append(height.numpy())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Assign width and height to each image in dataframe\ntrain_df['width'] = pd.Series(widths)\ntrain_df['height'] = pd.Series(heights)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sum(train_df['width']==train_df['height'])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"- This visualizing code is used from https://www.kaggle.com/anokas/kuzushiji-visualisation"},{"metadata":{"trusted":true},"cell_type":"code","source":"# This function takes in a filename of an image, and the labels in the string format given in train.csv, and returns an image containing the bounding boxes and characters annotated\ndef visualize_training_data(image_fn, labels):\n    # Read image\n    imsource = Image.open(image_fn).convert('RGBA')\n    bbox_canvas = Image.new('RGBA', imsource.size)\n    char_canvas = Image.new('RGBA', imsource.size)\n    \n    # Convert annotation string to array\n    if(labels is not np.nan):\n        labels = np.array(labels.split(' ')).reshape(-1, 5)\n        bbox_draw = ImageDraw.Draw(bbox_canvas) # Separate canvases for boxes and chars so a box doesn't cut off a character\n        char_draw = ImageDraw.Draw(char_canvas)\n\n        for codepoint, x, y, w, h in labels:\n            x, y, w, h = int(x), int(y), int(w), int(h)\n            char = unicode_map[codepoint] # Convert codepoint to actual unicode character\n\n            # Draw bounding box around character, and unicode character next to it\n            bbox_draw.rectangle((x, y, x+w, y+h), fill=(255, 255, 255, 0), outline=(255, 0, 0, 255))\n            char_draw.text((x + w + fontsize/4, y + h/2 - fontsize), char, fill=(0, 0, 255, 255), font=font)\n\n        imsource = Image.alpha_composite(Image.alpha_composite(imsource, bbox_canvas), char_canvas)\n    imsource = imsource.convert(\"RGB\") # Remove alpha for saving in jpg format.\n    return np.asarray(imsource)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"collapsed":true},"cell_type":"code","source":"# plot some image\nnp.random.seed(1337)\n\nfor i in range(10):\n    img, labels, w, h = train_df.values[np.random.randint(len(train_df))]\n    viz = visualize_training_data('../input/train_images/{}.jpg'.format(img), labels)\n    \n    plt.figure(figsize=(15, 15))\n    plt.title(img)\n    plt.imshow(viz, interpolation='lanczos')\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## 2.1. Image height and width:"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df['aspect_ratio'] = train_df['width'] / train_df['height']","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df.describe()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"- Width and height are not too unequal"},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.hist(train_df['width'])\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.hist(train_df['height'])\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## 2.2. Image labels:\n- First, we are gonna look at some NaN labeled image\n- Then, we will see the distribution of labels (characters) over all training set"},{"metadata":{},"cell_type":"markdown","source":"### 2.2.1. NaN Label:"},{"metadata":{"trusted":true},"cell_type":"code","source":"print('Number of image having NaN label:', sum(train_df['labels'].isna()))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"np.random.seed(2444)\n\nNaN_train_df = train_df[train_df['labels'].isna()]\n\nfor i in range(10):\n    img, labels, w, h, ar = NaN_train_df.values[np.random.randint(len(NaN_train_df))]\n    viz = visualize_training_data('../input/train_images/{}.jpg'.format(img), labels)\n    \n    plt.figure(figsize=(15, 15))\n    plt.title(img)\n    plt.imshow(viz, interpolation='lanczos')\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"NaN_train_df.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### 2.2.2. Distribution of labels"},{"metadata":{"trusted":true},"cell_type":"code","source":"def count_codepoint_freq(labels):\n    labels = np.array(labels.split(' ')).reshape(-1, 5)\n    code_point = pd.Series(labels[:, 0])\n    return code_point.value_counts(sort=False)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"labels_series = train_df['labels']\nall_labels = labels_series.str.cat(sep=' ')\nlabel_counts = count_codepoint_freq(all_labels)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print('Number of valid characters in all images: ', len(all_labels))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print('Number codepoint appearing in training set: %d, compared to total codepoints in dict: %d'%(len(label_counts), len(unicode_map)))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"- Distribution of 10 different code point in training set"},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize=(30, 5))\nsns.barplot(label_counts.index[:20], label_counts.values[:20])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print('Codepoint that has the most appearance:', np.argmax(label_counts), ' with freq = ', np.max(label_counts))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print('Codepoint that has the least appearance:', np.argmin(label_counts), ' with freq = ', np.min(label_counts))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"- We can see that the counts of each code points varies so much compared to each other\n- Below we will see the distribution and histogram of the **value count** of codepoints"},{"metadata":{"trusted":true},"cell_type":"code","source":"label_counts.describe()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.hist(label_counts.values, bins=100)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"- We can see that the mean of characters appearing in training set is 162"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df.to_csv('train_df_plus.csv', index=False)","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}