{"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_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport numpy as np\nimport pandas as pd\nimport cv2\nimport matplotlib.pyplot as plt\nimport joblib\nimport multiprocessing as mp","metadata":{"_uuid":"a38a3262-b0d1-4470-8a76-51e591c81e96","_cell_guid":"e07f99f6-1be7-488d-bb6e-06935cddf9ca","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-03-14T13:47:34.049392Z","iopub.execute_input":"2022-03-14T13:47:34.050205Z","iopub.status.idle":"2022-03-14T13:47:34.055699Z","shell.execute_reply.started":"2022-03-14T13:47:34.050130Z","shell.execute_reply":"2022-03-14T13:47:34.054840Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Processing images to remove checkered background\nBasically the code to generate ultramnist-black dataset that has been shared already.","metadata":{}},{"cell_type":"code","source":"DATA_PATH = \"/kaggle/input/ultra-mnist/\"\nPROCESSED_DATA_PATH = \"/kaggle/working/processed_train/\"\nif not os.path.isdir(PROCESSED_DATA_PATH):\n    os.mkdir(PROCESSED_DATA_PATH)","metadata":{"_uuid":"bc62072b-ff19-49d3-b4d3-53c5d82d494d","_cell_guid":"7644b921-d6db-4f94-84a6-6a1a6dedc151","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-03-14T13:47:34.063674Z","iopub.execute_input":"2022-03-14T13:47:34.064454Z","iopub.status.idle":"2022-03-14T13:47:34.089083Z","shell.execute_reply.started":"2022-03-14T13:47:34.064406Z","shell.execute_reply":"2022-03-14T13:47:34.087894Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### So we want a black background with digits in white. This is how we do it really fast","metadata":{}},{"cell_type":"code","source":"def invert_pixels_fast(img):\n    img1d = img.reshape(-1)\n    pixels, counts = np.unique(img1d, return_counts=True)\n    pixel_count = {str(pixel): count for pixel, count in zip(pixels, counts)}\n    if \"1\" in pixel_count:\n        invert_pixel = lambda x: 0 if x == 1 else 1\n        v_invert_pixel = np.vectorize(invert_pixel)\n        # if only white pixels or majority pixels are white\n        if \"0\" not in pixel_count or pixel_count[\"0\"] < pixel_count[\"1\"]:\n            # perform vectorized pixel inversion on 1d numpy array\n            img_transformed = v_invert_pixel(img1d)\n            img = img_transformed.reshape(1000, 1000)    \n    return img","metadata":{"_uuid":"3d48ec58-b699-4d6b-9c65-3d042cb1638e","_cell_guid":"cd642b36-5f37-4968-919f-83636fb82526","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-03-14T13:47:34.090032Z","iopub.status.idle":"2022-03-14T13:47:34.090555Z","shell.execute_reply.started":"2022-03-14T13:47:34.090371Z","shell.execute_reply":"2022-03-14T13:47:34.090391Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# split the 4000 * 4000 binary_image into 16 tiles of 1000 * 1000 and tranform each tile to have a black background\n# with white digits\ndef split_and_transform_img(img):    \n    img_tiles = []\n    for x in range(4):\n        x_start = x * 1000\n        x_end = x_start + 1000\n        row_img_list = []\n        for y in range(4):\n            y_start = y * 1000\n            y_end = y_start + 1000            \n            row_img_list.append(invert_pixels_fast(img[x_start:x_end, y_start:y_end]))\n        img_tiles.append(row_img_list)\n    return np.array(img_tiles)","metadata":{"_uuid":"99f27066-6ff6-4886-9ee2-165d65716ebe","_cell_guid":"b33c8006-1c43-4270-842d-2a5b7237e8a2","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-03-14T13:47:34.091440Z","iopub.status.idle":"2022-03-14T13:47:34.091847Z","shell.execute_reply.started":"2022-03-14T13:47:34.091692Z","shell.execute_reply":"2022-03-14T13:47:34.091709Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# join the transformed tiled images to reconstruct 4000 * 4000 binary image\ndef join_tiles(tfmd_img_tiles):    \n    row_tiles = []\n    for i in range(4):\n        # join 4 tiles to create a row tile\n        row_tiles.append(np.concatenate(tfmd_img_tiles[i, :], axis=1))\n    return np.concatenate(row_tiles, axis=0)","metadata":{"_uuid":"41b71f1e-73fe-4a53-b7bf-8d139ed4aa9e","_cell_guid":"fb06f863-4757-4dd4-9a1f-6697480351be","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-03-14T13:47:34.092701Z","iopub.status.idle":"2022-03-14T13:47:34.093136Z","shell.execute_reply.started":"2022-03-14T13:47:34.092945Z","shell.execute_reply":"2022-03-14T13:47:34.092961Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_pixel_count(img):\n    img1d = img.reshape(-1)\n    pixels, counts = np.unique(img1d, return_counts=True)\n    return {str(pixel): count for pixel, count in zip(pixels, counts)}","metadata":{"_uuid":"30489ec9-f085-42ef-9f79-d65954dd11c4","_cell_guid":"cc7e782d-22cb-47f4-ad9f-a5816f81754c","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-03-14T13:47:34.093942Z","iopub.status.idle":"2022-03-14T13:47:34.094352Z","shell.execute_reply.started":"2022-03-14T13:47:34.094194Z","shell.execute_reply":"2022-03-14T13:47:34.094210Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def preprocess_train_image(img_name):\n    img = cv2.imread(DATA_PATH + \"train/\"+ img_name)  \n    # convert to graycale as original images don't have colors anyway\n    gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n    # convert all pixels greater than 0 to 1\n    binary_img = cv2.threshold(gray_img, 1, 1, cv2.THRESH_BINARY)[1]\n    pixel_count = get_pixel_count(binary_img)\n    if set(list(pixel_count.keys())) != {\"0\", \"1\"}:\n        raise AssertionError(\"There are pixels other than 0 and 1 in the image\")\n    img_tiles = split_and_transform_img(binary_img)\n    tfmd_binary_img = join_tiles(img_tiles)\n    plt.imsave(PROCESSED_DATA_PATH + img_name, tfmd_binary_img)\n    return img_name","metadata":{"_uuid":"475883ea-22b0-4fd2-b7ca-d2c0f3684068","_cell_guid":"ada3a27c-3acf-412a-bcc5-f61af8b029c4","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-03-14T13:47:34.095169Z","iopub.status.idle":"2022-03-14T13:47:34.095576Z","shell.execute_reply.started":"2022-03-14T13:47:34.095410Z","shell.execute_reply":"2022-03-14T13:47:34.095426Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Let's see how does the original train image looks like","metadata":{}},{"cell_type":"code","source":"img_to_process = [img for img in os.listdir(DATA_PATH + \"train\")][:10]\nimg = cv2.imread(DATA_PATH + \"train/\" + img_to_process[0])\n# matplotlib interprets images in RGB format, but OpenCV uses BGR format\n# so to convert the image so that it's properly loaded, convert it before loading\nrgb_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\nplt.figure(figsize = (8, 6))\nplt.imshow(rgb_img)","metadata":{"execution":{"iopub.status.busy":"2022-03-14T13:47:34.096355Z","iopub.status.idle":"2022-03-14T13:47:34.096761Z","shell.execute_reply.started":"2022-03-14T13:47:34.096604Z","shell.execute_reply":"2022-03-14T13:47:34.096621Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Use joblib multiprocessing capabilities to parallelize image processing","metadata":{}},{"cell_type":"code","source":"from joblib import delayed, Parallel\n\ndelayed_funcs = [delayed(preprocess_train_image)(img) for img in img_to_process]\nresults = Parallel(n_jobs=-1, verbose=5)(delayed_funcs)\nprint(results)","metadata":{"_uuid":"d2559af3-d8c4-4e84-97a9-c668e40f3a94","_cell_guid":"926c384d-2714-4cff-a26f-fa7eb400b215","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-03-14T13:47:34.097546Z","iopub.status.idle":"2022-03-14T13:47:34.097890Z","shell.execute_reply.started":"2022-03-14T13:47:34.097714Z","shell.execute_reply":"2022-03-14T13:47:34.097737Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Check out how does the processed image looks like","metadata":{}},{"cell_type":"code","source":"img = cv2.imread(PROCESSED_DATA_PATH + img_to_process[0])\nrgb_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\nplt.figure(figsize = (8, 6))\nplt.imshow(rgb_img)","metadata":{"execution":{"iopub.status.busy":"2022-03-14T13:47:34.099137Z","iopub.status.idle":"2022-03-14T13:47:34.099616Z","shell.execute_reply.started":"2022-03-14T13:47:34.099442Z","shell.execute_reply":"2022-03-14T13:47:34.099459Z"},"trusted":true},"execution_count":null,"outputs":[]}]}