{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(24840, 6211)"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import json\n",
    "\n",
    "with open('train-test-rumi-to-jawi.json') as fopen:\n",
    "    dataset = json.load(fopen)\n",
    "len(dataset['train']), len(dataset['test'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "with open('train-test-wiki.json') as fopen:\n",
    "    dataset_wiki = json.load(fopen)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(64840, 16211)"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dataset['train'] = dataset['train'] + dataset_wiki['train']\n",
    "dataset['test'] = dataset['test'] + dataset_wiki['test']\n",
    "len(dataset['train']), len(dataset['test'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/husein/.local/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:516: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_qint8 = np.dtype([(\"qint8\", np.int8, 1)])\n",
      "/home/husein/.local/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:517: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_quint8 = np.dtype([(\"quint8\", np.uint8, 1)])\n",
      "/home/husein/.local/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:518: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_qint16 = np.dtype([(\"qint16\", np.int16, 1)])\n",
      "/home/husein/.local/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:519: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_quint16 = np.dtype([(\"quint16\", np.uint16, 1)])\n",
      "/home/husein/.local/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:520: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_qint32 = np.dtype([(\"qint32\", np.int32, 1)])\n",
      "/home/husein/.local/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:525: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  np_resource = np.dtype([(\"resource\", np.ubyte, 1)])\n",
      "/home/husein/.local/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:541: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_qint8 = np.dtype([(\"qint8\", np.int8, 1)])\n",
      "/home/husein/.local/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:542: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_quint8 = np.dtype([(\"quint8\", np.uint8, 1)])\n",
      "/home/husein/.local/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:543: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_qint16 = np.dtype([(\"qint16\", np.int16, 1)])\n",
      "/home/husein/.local/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:544: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_quint16 = np.dtype([(\"quint16\", np.uint16, 1)])\n",
      "/home/husein/.local/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:545: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_qint32 = np.dtype([(\"qint32\", np.int32, 1)])\n",
      "/home/husein/.local/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:550: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  np_resource = np.dtype([(\"resource\", np.ubyte, 1)])\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import tensorflow as tf\n",
    "import matplotlib.pyplot as plt\n",
    "from skimage.transform import resize as imresize\n",
    "import cv2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_labels = [f.split('/')[1].split('.')[0].lower() for f in dataset['train']]\n",
    "test_labels = [f.split('/')[1].split('.')[0].lower() for f in dataset['test']]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 12676 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.imshow(cv2.imread(dataset['train'][-1], 0).astype(np.float32)/255.)\n",
    "plt.title(train_labels[-1])\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "image_height = 60\n",
    "image_width = 240\n",
    "image_channel = 1\n",
    "max_stepsize = 128\n",
    "num_hidden = 256\n",
    "epoch = 20\n",
    "batch_size = 128\n",
    "initial_learning_rate = 1e-3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "from scipy.ndimage.interpolation import map_coordinates\n",
    "from scipy.ndimage.filters import gaussian_filter\n",
    "\n",
    "def elastic_transform(image, alpha, sigma, alpha_affine, random_state=None):\n",
    "    if random_state is None:\n",
    "        random_state = np.random.RandomState(None)\n",
    "\n",
    "    shape = image.shape\n",
    "    shape_size = shape[:2]\n",
    "    \n",
    "    blur_size = int(4*sigma) | 1\n",
    "    dx = alpha * cv2.GaussianBlur((random_state.rand(*shape) * 2 - 1),\n",
    "                                  ksize=(blur_size, blur_size),\n",
    "                                  sigmaX=sigma)\n",
    "    dy = alpha * cv2.GaussianBlur((random_state.rand(*shape) * 2 - 1),\n",
    "                                  ksize=(blur_size, blur_size),\n",
    "                                  sigmaX=sigma)\n",
    "\n",
    "    x, y = np.meshgrid(np.arange(shape[1]), np.arange(shape[0]))\n",
    "    indices = np.reshape(y+dy, (-1, 1)), np.reshape(x+dx, (-1, 1))\n",
    "\n",
    "    image =  map_coordinates(image, indices, order=1, mode='constant').reshape(shape)\n",
    "    \n",
    "    # Random affine\n",
    "    center_square = np.float32(shape_size) // 2\n",
    "    square_size = min(shape_size) // 4\n",
    "    pts1 = np.float32([center_square + square_size,\n",
    "                       [center_square[0]+square_size, \n",
    "                        center_square[1]-square_size],\n",
    "                       center_square - square_size])\n",
    "    pts2 = pts1 + random_state.uniform(-alpha_affine, alpha_affine, size=pts1.shape).astype(np.float32)\n",
    "    M = cv2.getAffineTransform(pts1, pts2)\n",
    "    image = cv2.warpAffine(image, M, shape_size[::-1], borderMode=cv2.BORDER_CONSTANT)\n",
    "\n",
    "    return image"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 18532 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 363 ms, sys: 115 ms, total: 478 ms\n",
      "Wall time: 232 ms\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "\n",
    "img = cv2.imread(dataset['train'][3], 0)\n",
    "img = cv2.bitwise_not(img)\n",
    "img = img[:, np.min(np.where(img > 0)[1]) - 50:]\n",
    "im = imresize(cv2.flip((img.astype(np.float32)/255.), 1), (image_height,\n",
    "                                                           image_width,\n",
    "                                                           image_channel))[:,:,0]\n",
    "im = elastic_transform(im, im.shape[1] * 5, im.shape[1] * 0.3, im.shape[1] * 0.0001)\n",
    "plt.imshow(im, cmap = 'gray')\n",
    "plt.title(train_labels[3])\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 64840/64840 [15:17<00:00, 70.64it/s]\n"
     ]
    }
   ],
   "source": [
    "import tqdm\n",
    "train_X = []\n",
    "for img in tqdm.tqdm(dataset['train']):\n",
    "    img = cv2.imread(img, 0)\n",
    "    img = cv2.bitwise_not(img)\n",
    "    img = img[:, np.min(np.where(img > 0)[1]) - 50:]\n",
    "    im = imresize(cv2.flip((img.astype(np.float32)/255.), 1), (image_height,\n",
    "                                                           image_width,\n",
    "                                                           image_channel))[:,:,0]\n",
    "    im = elastic_transform(im, im.shape[1] * 5, im.shape[1] * 0.3, im.shape[1] * 0.0001)\n",
    "    train_X.append(im)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 16211/16211 [03:48<00:00, 70.96it/s]\n"
     ]
    }
   ],
   "source": [
    "test_X = []\n",
    "for img in tqdm.tqdm(dataset['test']):\n",
    "    img = cv2.imread(img, 0)\n",
    "    img = cv2.bitwise_not(img)\n",
    "    img = img[:, np.min(np.where(img > 0)[1]) - 50:]\n",
    "    im = imresize(cv2.flip((img.astype(np.float32)/255.), 1), (image_height,\n",
    "                                                           image_width,\n",
    "                                                           image_channel))[:,:,0]\n",
    "    im = elastic_transform(im, im.shape[1] * 5, im.shape[1] * 0.3, im.shape[1] * 0.0001)\n",
    "    test_X.append(im)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(64840, 64840)"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(train_labels), len(train_X)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(16211, 16211)"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(test_labels), len(test_X)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pickle\n",
    "\n",
    "with open('jawi-to-malay-dataset.pkl', 'wb') as fopen:\n",
    "    pickle.dump({'train_X': train_X, 'train_Y': train_labels,\n",
    "                'test_X': test_X, 'test_Y': test_labels}, fopen)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "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.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
