{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Kuzushiji Recognition Complete Guide\n\n## *Build a model to transcribe ancient Kuzushiji into contemporary Japanese characters*\n\n<img src=\"http://static.mxbi.net/umgy001-010-smallannomasked.jpg\" height=\"600\" width=\"600\">\n![]()\n\n---\n\nImagine the history contained in a thousand years of books. What stories are in those books? What knowledge can we learn from the world before our time? What was the weather like 500 years ago? What happened when Mt. Fuji erupted? How can one fold 100 cranes using only one piece of paper? The answers to these questions are in those books.\n\nJapan has millions of books and over a billion historical documents such as personal letters or diaries preserved nationwide. Most of them cannot be read by the majority of Japanese people living today because they were written in “Kuzushiji”.\n\nEven though Kuzushiji, a cursive writing style, had been used in Japan for over a thousand years, there are very few fluent readers of Kuzushiji today (only 0.01% of modern Japanese natives). Due to the lack of available human resources, there has been a great deal of interest in using Machine Learning to automatically recognize these historical texts and transcribe them into modern Japanese characters. \n\n\n**<span style=\"color:green\">kernel completed!</span>**\n\n---\n\n### Content\n\n1. **[EDA]()**\n     - New ```df_train```\n     - missing data\n     - char stats\n     - top-10 chars\n     - top-100 chars (plot)\n     \n     \n2. **[Simple Visualization]()**\n3. **[KMINST]()**\n    - Save the 683464 chars/digits images in ```kminst.zip``` and ```info.csv```\n    - Examples of obtained chars from a random image.\n    \n    \n4. **[KMINST Classification]()**\n    - Simple KNN\n    - Deep Learning\n    \n    \n5. **[Simple Predictions Visualization]()**\n\n### Other kernels\n\nI will create other kernels to perform **different tasks**: digitalize images, train models, do inferences etc . Here you can check them:\n\n### More information\n\n- [Must-read material](https://www.kaggle.com/c/kuzushiji-recognition/discussion/100579#latest-580915)\n- [Worldwide Competition to Develop AI for Historical Japanese Character (Kuzushiji) Recognition](https://www.nii.ac.jp/en/news/release/2019/0710.html)\n- [KMNIST Dataset](http://codh.rois.ac.jp/kmnist/index.html.en)\n- [Osaka University](http://www.digitalhumanities.org/dhq/vol/11/1/000281/000281.html)\n\n<br>"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"from PIL import Image, ImageDraw, ImageFont\nfrom os import listdir\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport re\nimport os\nimport gc\nimport sys\nimport seaborn as sns\nimport cv2\nimport shutil\nfrom sklearn.neighbors import KNeighborsClassifier\nfrom tqdm import tqdm_notebook as tqdm\n\n%matplotlib inline\n\nprint (os.listdir('../input/'))\nprint(\"Ready!\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Load packages**"},{"metadata":{},"cell_type":"markdown","source":"**Install ```NotoSans```**"},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true,"_kg_hide-input":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":{},"cell_type":"markdown","source":"### Utils\n> from: [Kuzushiji Visualisation](https://www.kaggle.com/anokas/kuzushiji-visualisation)\n\n1. ```visualize_training_data```\n2. ```visualize_predictions```"},{"metadata":{"_kg_hide-input":true,"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    # Convert annotation string to array\n    labels = np.array(labels.split(' ')).reshape(-1, 5)\n    \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    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)\n\n\n\ndef visualize_test_data(image_fn):\n    \n    # Read image\n    imsource = Image.open(image_fn).convert('RGBA')\n    imsource = imsource.convert(\"RGB\") # Remove alpha for saving in jpg format.\n    return np.asarray(imsource)","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"# This function takes in a filename of an image, and the labels in the string format given in a submission csv, and returns an image with the characters and predictions annotated.\ndef visualize_predictions(image_fn, labels):\n    # Convert annotation string to array\n    labels = np.array(labels.split(' ')).reshape(-1, 3)\n    \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    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 in labels:\n        x, y = int(x), int(y)\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-10, y-10, x+10, y+10), fill=(255, 0, 0, 255))\n        char_draw.text((x+25, y-fontsize*(3/4)), char, fill=(255, 0, 0, 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":{},"cell_type":"markdown","source":"# EDA\n\n----\n\n### Load data\n\n> <span style=\"color:red\"> DISCLAIMER </span> Remember to change the ```PATH``` (if necessary)"},{"metadata":{"trusted":true},"cell_type":"code","source":"!ls ../input/","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"PATH = '../input/kuzushiji-recognition/'\ndf_train = pd.read_csv(PATH+'train.csv')\ndf_test = os.listdir(PATH+'test_images/')\nunicode_map = {codepoint: char for codepoint, char in pd.read_csv(PATH+'unicode_translation.csv').values}\nprint (\"TRAIN: \", df_train.shape)\nprint (\"TEST: \", len(df_test))\ndf_train.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Check missing"},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"df_train.isnull().sum()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"276 images have no labels, I'll drop them using ```dropna```"},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"#df_train.dropna(inplace=True)\ndf_train.reset_index(inplace=True, drop=True)\nprint (\"TRAIN: \", df_train.shape)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Processing\n> lazy code, click ```code``` to see."},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"chars = {}\n\nfor i in range (df_train.shape[0]):\n    try:\n        a = [x for x in df_train.labels.values[i].split(' ') if x.startswith('U')]\n        n_a = int(len(a))        \n        for j in a:\n            if j not in chars: chars[j]=1\n            else:\n                chars[j]+=1\n                \n        a = \" \".join(a)\n        \n    except AttributeError:\n        a = None\n        n_a = 0\n        \n    df_train.loc[i,'chars'] = a\n    df_train.loc[i,'n_chars'] = n_a\n    \ndf_train.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**char stats**"},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"print (\"MAX chars in a picture= \", df_train.n_chars.max())\nprint (\"MIN chars in a picture= \", df_train.n_chars.min())\nprint (\"MEAN chars in a picture= \", df_train.n_chars.mean())","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Most common chars"},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"chars = pd.DataFrame(list(chars.items()), columns=['char', 'count'])\nchars['jp_char'] = chars['char'].map(unicode_map)\nprint (\" >> Chars dataframe <<\")\nprint (\"Number of chars: \",chars.shape[0])\nchars.to_csv(\"chars_freq.csv\",index=False)\nchars.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**TOP-10**"},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"chars.sort_values(by=['count'], ascending=False).head(10).reset_index()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**TOP-100**"},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"sns.set(style=\"whitegrid\")\nplt.figure(figsize=(22,20))\nax = sns.barplot(y=\"char\", x=\"count\", data=chars.sort_values(by=['count'], ascending=False).head(100))\nax.set_title(\"Character frequency in images (top 100)\")\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Rare chars"},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"print ('Total chars', chars.shape[0])\nprint ('< 10 freq', chars[chars['count'] <= 10].shape[0])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"rare = chars[chars['count'] <= 10]\nprint (rare.shape)\nrare.head()","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"rare.to_csv('rare_chars.csv', index=False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Images without chars or <10 chars"},{"metadata":{"trusted":true},"cell_type":"code","source":"lowchar = df_train[df_train.n_chars <= 10]\nprint ('lowchar images ',lowchar.shape[0], lowchar.shape[0]/ df_train.shape[0])\nlowchar.head()","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-output":true,"trusted":true},"cell_type":"code","source":"for image_fn in lowchar.image_id:\n    image_fn = '../input/train_images/'+image_fn+'.jpg'\n    imsource = Image.open(image_fn).convert('RGBA')\n    imsource = imsource.convert(\"RGB\") # Remove alpha for saving in jpg format.\n    imsource = np.asarray(imsource)\n    plt.figure(figsize=(10, 10))\n    plt.title(image_fn)\n    plt.axis(\"off\")\n    plt.imshow(imsource, interpolation='lanczos')\n    plt.show() ","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"print (lowchar.shape)\nlowchar.dropna(inplace=True)\nprint (lowchar.shape)\nlowchar.to_csv('train_lowchar.csv',index=False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<br>\n## Books"},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"df_train[\"title\"]= df_train[\"image_id\"].str.split(\"_\", n = 1, expand = True)[0]\n#df_train[\"chapter\"]= df_train[\"image_id\"].str.split(\"_\", n = 2, expand = True)[1]\n#df_train[\"page\"]= df_train[\"image_id\"].str.split(\"_\", n = 3, expand = True)[2]\ndf_train.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print (df_train['title'].nunique())\ndf_train['title'].unique()[0:10]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"book = df_train[df_train['title']== '200006663'].reset_index(drop=True)\nbook","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Visualize book\n**Click to see the function code**"},{"metadata":{"_kg_hide-output":false,"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"def visualize_book(title, df_train):\n    df_train[df_train['title']== title].reset_index(drop=True)\n    print ('Book ', title)\n    for i in book.index:\n        img,labels,_,_,_ = book.values[i]\n        viz = visualize_training_data(PATH+'train_images/{}.jpg'.format(img), labels)\n        plt.figure(figsize=(15, 15))\n        plt.title(img)\n        plt.axis(\"off\")\n        plt.imshow(viz, interpolation='lanczos')\n        plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"visualize_book('200006663', df_train)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### Another interesting books"},{"metadata":{"trusted":true},"cell_type":"code","source":"visualize_book('200014685-00002', df_train)","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-output":true,"trusted":true},"cell_type":"code","source":"visualize_book('200014685-00003', df_train)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print (\"TRAIN: \", df_train.shape)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Visualization"},{"metadata":{},"cell_type":"markdown","source":"#### Click ```output``` to see the images."},{"metadata":{"trusted":true,"_kg_hide-input":false,"_kg_hide-output":true},"cell_type":"code","source":"np.random.seed(1337)\n\nfor i in range(2):\n    img,labels,_,_,_ = df_train.values[np.random.randint(len(df_train))]\n    viz = visualize_training_data(PATH+'train_images/{}.jpg'.format(img), labels)\n    plt.figure(figsize=(15, 15))\n    plt.title(img)\n    plt.axis(\"off\")\n    plt.imshow(viz, interpolation='lanczos')\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Visualize Test"},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"for img in df_test[0:2]:\n    viz = visualize_test_data(PATH+'test_images/{}'.format(img))\n    plt.figure(figsize=(15, 15))\n    plt.title(img)\n    plt.axis(\"off\")\n    plt.imshow(viz, interpolation='lanczos')\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"\n# KMINST\n\n----\n\n**<span style=\"color:red\">DISCLAIMER</span>**\n> In this part I saved the 683464 chars/digits images in ```kminst.zip``` and ```info.csv```. You don't have to run this code if you can import those files. Check version **V4** ``` output ``` of this kernel and download them."},{"metadata":{},"cell_type":"markdown","source":"**get_char**\n> gets all the characters from the image ```img_id``` and save them in ```kminst```. The images names have the following format: ```img_id_idx.jpg'``` where ```idx``` is in range (0, number of chars in the image)."},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"def get_char(img_id, labels):\n    \n    image_fn = '../input/train_images/{}.jpg'.format(img_id)\n    # Convert annotation string to array\n    labels = np.array(labels.split(' ')).reshape(-1, 5)\n    # Read image\n    imsource = Image.open(image_fn).convert('RGBA')\n    img = np.asarray(imsource.convert(\"RGB\"))\n\n    info = []\n    \n    for idx, (codepoint, x, y, w, h) in enumerate(labels):\n        x, y, w, h = int(x), int(y), int(w), int(h)\n        try:\n            char = unicode_map[codepoint] # Convert codepoint to actual unicode character\n        except KeyError:\n            char = \"e\" # https://www.kaggle.com/c/kuzushiji-recognition/discussion/100712#latest-580747\n        \n        # crop char\n        #print (idx,x,y,w,h,char)\n        crop_img = img[y:y+h, x:x+w]\n        result = Image.fromarray(crop_img, mode='RGB')\n        name = img_id+'_{}.jpg'.format(idx)\n        result.save('kminst/'+name)\n        \n        info.append((name,codepoint))\n        \n    del imsource, img, result, name\n    gc.collect()\n    \n    return info","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Create the folder ```kminst```** where I'm going to save all the chars from all the pictures."},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"!mkdir kminst\n!ls","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### Save all the digits/chars in ```kminst```"},{"metadata":{"trusted":true},"cell_type":"code","source":"'''\ngenerated = 0\ninfo = []\n\nfor i in tqdm(df_train.index):\n    img, labels,_,_ = df_train.values[i]\n    info += get_char(img, labels)\n    generated+= int(df_train[df_train['image_id']==img].n_chars)\n    \n    if (i+1)%500 == 0 or i==df_train.index[-1]:\n        # save memory\n        shutil.make_archive('kminst_'+str(i//500), 'zip', 'kminst')\n        print (i+1,\"\\t>> generated ...\", generated)\n        shutil.rmtree('kminst', ignore_errors=True)\n        os.mkdir('kminst')\n'''","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"!rm -r kminst\n!ls","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**All as 1 zip ```kminst.zip```**"},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"#shutil.make_archive('kminst', 'zip', 'kminst')\n#!rm -r kminst\n#!ls","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### Generate and save ```info```"},{"metadata":{"trusted":true},"cell_type":"code","source":"info[0:5]","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"infok = pd.DataFrame(columns=['char_id','unicode'])\ninfok['char_id'] = [i[0] for i in info]\ninfok['unicode'] = [i[1] for i in info]\nprint (\"TOTAL KMNIST = \", infok.shape[0])\ninfok.to_csv('info.csv',index=False)\ninfok.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Examples"},{"metadata":{},"cell_type":"markdown","source":"**these are good pictures**"},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"example = \"200021660-00023_2\"\n\"100249537_00013_2\"\n\"hnsd007-039\"\n\"100249537_00003_2\"\n\"200014685-00003_1\"\n\"200014685-00016_2\"","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**get_char_example**\n> visualize what ```get_char``` does."},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"def get_char_example(image_fn, labels):\n    # Convert annotation string to array\n    labels = np.array(labels.split(' ')).reshape(-1, 5)\n    \n    # Read image\n    imsource = Image.open(image_fn).convert('RGBA')\n    img = np.asarray(imsource.convert(\"RGB\"))\n    bbox_canvas = Image.new('RGBA', imsource.size)\n    char_canvas = Image.new('RGBA', imsource.size)\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    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        # 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        # crop char\n        print (x,y,w,h,char)\n        crop_img = img[y:y+h, x:x+w]\n        plt.axis(\"off\")\n        plt.imshow(np.asarray(crop_img), interpolation='lanczos')\n        plt.show()\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":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"img, labels,_,_ = df_train[df_train['image_id']==\"umgy004-011\"].values[0]\nprint (\"IMAGE: \", img)\nprint (\">> chars:\", int(df_train[df_train['image_id']==img].n_chars),\"\\n\")\n\nviz = get_char_example(PATH+'train_images/{}.jpg'.format(img), labels)\nplt.figure(figsize=(15, 15))\nplt.title(img)\nplt.axis(\"off\")\nplt.imshow(viz, interpolation='lanczos')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# INFERENCE\n\n\n**<span style=\"color:red\">DISCLAIMER</span>**\n> The following code will perform the **inference** on the test set. For more information about the training (detector and classifier) please check the official github: https://github.com/mv-lab/kuzushiji-recognition\n\nWe take the predictions from the ```detector``` , we ```classify``` each detected symbol and generate the ```submisison``` file."},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<br>\n# Visualize Predictions\n\nsource: [Kuzushiji Visualisation](https://www.kaggle.com/anokas/kuzushiji-visualisation)\n> For the test set, you're only required to predict a single point within each bounding box instead of the entire bounding box (ideally, the centre of the bounding box). It may also be useful to visualise the box centres on the image:"},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"image_fn = '../input/test_images/test_030d9355.jpg'\npred_string = 'U+306F 1231 1465 U+304C 275 1652 U+3044 1495 1218 U+306F 436 1200 U+304C 800 2000 U+3044 1000 300' # Prediction string in submission file format\nviz = visualize_predictions(image_fn, pred_string)\n\nplt.figure(figsize=(15, 15))\nplt.imshow(viz, interpolation='lanczos')","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}