{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"markdown","source":"# Description\nThis kernel creates an image dataset for train based on the competition data. Use of images allows to avoid loading the entire dataset into memory, which may be important for running experiments at kaggle. Meanwhile the inference can be done  by loading the dataset part by part without saving it as images to improve the speed.\n\nThe original images are cropped keeping only the characters and resized to 128x128 with adding the corresponding padding to maintain the aspect ratio (see images plot in the kernel). The stats of the produced images are also computed."},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"import cv2\nfrom tqdm import tqdm_notebook as tqdm\nimport zipfile\nimport io\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport warnings\nwarnings.filterwarnings(\"ignore\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"HEIGHT = 137\nWIDTH = 236\nSIZE = 128\n\nTRAIN = ['/kaggle/input/bengaliai-cv19/train_image_data_0.parquet',\n         '/kaggle/input/bengaliai-cv19/train_image_data_1.parquet',\n         '/kaggle/input/bengaliai-cv19/train_image_data_2.parquet',\n         '/kaggle/input/bengaliai-cv19/train_image_data_3.parquet']\n\nOUT_TRAIN = 'train.zip'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def bbox(img):\n    rows = np.any(img, axis=1)\n    cols = np.any(img, axis=0)\n    rmin, rmax = np.where(rows)[0][[0, -1]]\n    cmin, cmax = np.where(cols)[0][[0, -1]]\n    return rmin, rmax, cmin, cmax\n\ndef crop_resize(img0, size=SIZE, pad=16):\n    #crop a box around pixels large than the threshold \n    #some images contain line at the sides\n    ymin,ymax,xmin,xmax = bbox(img0[5:-5,5:-5] > 80)\n    #cropping may cut too much, so we need to add it back\n    xmin = xmin - 13 if (xmin > 13) else 0\n    ymin = ymin - 10 if (ymin > 10) else 0\n    xmax = xmax + 13 if (xmax < WIDTH - 13) else WIDTH\n    ymax = ymax + 10 if (ymax < HEIGHT - 10) else HEIGHT\n    img = img0[ymin:ymax,xmin:xmax]\n    #remove lo intensity pixels as noise\n    img[img < 28] = 0\n    lx, ly = xmax-xmin,ymax-ymin\n    l = max(lx,ly) + pad\n    #make sure that the aspect ratio is kept in rescaling\n    img = np.pad(img, [((l-ly)//2,), ((l-lx)//2,)], mode='constant')\n    return cv2.resize(img,(size,size))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df = pd.read_parquet(TRAIN[0])\nn_imgs = 8\nfig, axs = plt.subplots(n_imgs, 2, figsize=(10, 5*n_imgs))\n\nfor idx in range(n_imgs):\n    #somehow the original input is inverted\n    img0 = 255 - df.iloc[idx, 1:].values.reshape(HEIGHT, WIDTH).astype(np.uint8)\n    #normalize each image by its max val\n    img = (img0*(255.0/img0.max())).astype(np.uint8)\n    img = crop_resize(img)\n\n    axs[idx,0].imshow(img0)\n    axs[idx,0].set_title('Original image')\n    axs[idx,0].axis('off')\n    axs[idx,1].imshow(img)\n    axs[idx,1].set_title('Crop & resize')\n    axs[idx,1].axis('off')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-output":true,"trusted":true},"cell_type":"code","source":"x_tot,x2_tot = [],[]\nwith zipfile.ZipFile(OUT_TRAIN, 'w') as img_out:\n    for fname in TRAIN:\n        df = pd.read_parquet(fname)\n        #the input is inverted\n        data = 255 - df.iloc[:, 1:].values.reshape(-1, HEIGHT, WIDTH).astype(np.uint8)\n        for idx in tqdm(range(len(df))):\n            name = df.iloc[idx,0]\n            #normalize each image by its max val\n            img = (data[idx]*(255.0/data[idx].max())).astype(np.uint8)\n            img = crop_resize(img)\n        \n            x_tot.append((img/255.0).mean())\n            x2_tot.append(((img/255.0)**2).mean()) \n            img = cv2.imencode('.png',img)[1]\n            img_out.writestr(name + '.png', img)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#image stats\nimg_avr =  np.array(x_tot).mean()\nimg_std =  np.sqrt(np.array(x2_tot).mean() - img_avr**2)\nprint('mean:',img_avr, ', std:', img_std)","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":1}