{"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":"markdown","source":"<div class=\"alert alert-danger\">\n  <strong>This notebook uses old DATASET - please do not use it for submission. </strong>\n</div>\n\n\n### STEP 2 - Find MNIST Numbers - NO ML MODEL REQUIRED\n\nHow to find MNIST number in ULTRA-MNIST? ..... model .... yolo ... Machine Learning ... annotations ... many many hours. Use just simple computer vision methods to achieve goal. It must be simple end effective. This notebook is as a result of inspiration from [Detecting multiple bright spots in an image with Python and OpenCV](https://pyimagesearch.com/2016/10/31/detecting-multiple-bright-spots-in-an-image-with-python-and-opencv/)","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19"}},{"cell_type":"markdown","source":"<div class=\"alert alert-success\">\n  <strong>Other my work in this competiton</strong>\n    <ul>\n        <li><a href=\"https://www.kaggle.com/remekkinas/funny-cv-eda-what-we-see-here\">STEP 0 - FUNNY CV EDA - what.... we see here ...</a></li>\n        <li><a href=\"https://www.kaggle.com/c/ultra-mnist/discussion/312003\">STEP 1 - Simplify problem - new DATASET - PLAIN BACKGROUND without checkboard</a></li>\n        <li>STEP 2 - Find MNIST Numbers - NO ML MODEL REQUIRED -> this notebook</li>\n    </ul>\n</div>","metadata":{}},{"cell_type":"code","source":"!pip install imutils -q","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-03-12T06:14:42.523682Z","iopub.execute_input":"2022-03-12T06:14:42.524063Z","iopub.status.idle":"2022-03-12T06:14:56.752688Z","shell.execute_reply.started":"2022-03-12T06:14:42.523969Z","shell.execute_reply":"2022-03-12T06:14:56.751537Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import argparse\nimport cv2\nimport imutils\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport pandas as pd\nfrom termcolor import colored\n\nfrom imutils import contours\nfrom PIL import Image as Img\nfrom IPython.display import Image\nfrom skimage import measure\n\nfrom joblib import Parallel, delayed\nfrom tqdm import tqdm_notebook as tqdm\n\nimport warnings\nwarnings.filterwarnings(\"ignore\")","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-03-12T06:14:56.75791Z","iopub.execute_input":"2022-03-12T06:14:56.758351Z","iopub.status.idle":"2022-03-12T06:14:58.274525Z","shell.execute_reply.started":"2022-03-12T06:14:56.758264Z","shell.execute_reply":"2022-03-12T06:14:58.273588Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## STEP 1 - Simplify - remove background from this game\n\nI provided new Dataset created from oryginal one (competition dataset). You can find this dataset here: [ULTRA-MNIST BLACK]()\n\n<div style=\"text-align:center;\">\n<h3>Oryginal</h3> </div>\n<div align=\"center\"><img src=\"https://i.ibb.co/zrgchbt/ultra-mnist-000a.jpg\" width=640/></div>\n\n<h3>&nbsp;</h3>\n<div style=\"text-align:center;\">\n<h3>Simplified</h3></div>\n<div align=\"center\"><img src=\"https://i.ibb.co/0DZYLQG/ultra-mnist.jpg\" width=640/></div>","metadata":{}},{"cell_type":"markdown","source":"## STEP 2 - Read image and make some adjustment\n1. Gausian Blur\n2. Threshold - erode and dilate","metadata":{}},{"cell_type":"code","source":"train_df = pd.read_csv(\"../input/ultra-mnist/train.csv\") \ntest_df = pd.read_csv(\"../input/ultra-mnist/sample_submission.csv\") ","metadata":{"execution":{"iopub.status.busy":"2022-03-12T06:14:58.281217Z","iopub.execute_input":"2022-03-12T06:14:58.28187Z","iopub.status.idle":"2022-03-12T06:14:58.367576Z","shell.execute_reply.started":"2022-03-12T06:14:58.281823Z","shell.execute_reply":"2022-03-12T06:14:58.366413Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img_id = 'flzibxgfvd'\n\nimage = cv2.imread(f\"../input/ultramnistblack/train/{img_id}.jpeg\", 0)\nimage_oryg = cv2.imread(f\"../input/ultra-mnist/train/{img_id}.jpeg\", 0)\n\ntrain_df.query(\"id == @img_id\")","metadata":{"execution":{"iopub.status.busy":"2022-03-12T07:04:40.602282Z","iopub.execute_input":"2022-03-12T07:04:40.602639Z","iopub.status.idle":"2022-03-12T07:04:40.707584Z","shell.execute_reply.started":"2022-03-12T07:04:40.602589Z","shell.execute_reply":"2022-03-12T07:04:40.706546Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def img_thresh(img_in):\n    blurred = cv2.GaussianBlur(img_in, (11, 11), 0) #(11,11)\n    thresh = cv2.threshold(blurred, 10, 255, cv2.THRESH_BINARY)[1]\n    #thresh = cv2.erode(thresh, None, iterations=2)\n    #thresh = cv2.dilate(thresh, None, iterations=4)\n    \n    return thresh","metadata":{"execution":{"iopub.status.busy":"2022-03-12T07:04:42.474966Z","iopub.execute_input":"2022-03-12T07:04:42.47575Z","iopub.status.idle":"2022-03-12T07:04:42.481792Z","shell.execute_reply.started":"2022-03-12T07:04:42.475712Z","shell.execute_reply":"2022-03-12T07:04:42.480299Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, axes = plt.subplots(1, 3, figsize=(40,50))\n\naxes[0].imshow(Img.fromarray(image_oryg))\naxes[0].axis('off')\naxes[0].set_title(\"ORYGINAL\", fontsize=36)\naxes[1].imshow(Img.fromarray(image))\naxes[1].axis('off')\naxes[1].set_title(\"CLEARED BACKGROUND\", fontsize=36)\naxes[2].imshow(Img.fromarray(img_thresh(image)))\naxes[2].axis('off')\naxes[2].set_title(\"THRESHOLD\", fontsize=36)\nplt.subplots_adjust(wspace=0.05, hspace=0.05)\nplt.axis('off')\nplt.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-03-12T07:04:44.028702Z","iopub.execute_input":"2022-03-12T07:04:44.029602Z","iopub.status.idle":"2022-03-12T07:04:48.843366Z","shell.execute_reply.started":"2022-03-12T07:04:44.029528Z","shell.execute_reply":"2022-03-12T07:04:48.842366Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## STEP 3 - Filter noisy region using connected-component from scikit-image library","metadata":{}},{"cell_type":"code","source":"def mask_img(img_in):\n    labels = measure.label(img_in,background = 0)\n    mask = np.zeros(img_in.shape, dtype=\"uint8\")\n\n    for label in np.unique(labels):\n        if label == 0:\n            continue\n\n        labelMask = np.zeros(img_in.shape, dtype=\"uint8\")\n        labelMask[labels == label] = 255\n        numPixels = cv2.countNonZero(labelMask)\n        if numPixels > 100:\n            mask = cv2.add(mask, labelMask)\n    return mask","metadata":{"execution":{"iopub.status.busy":"2022-03-12T06:45:19.423625Z","iopub.execute_input":"2022-03-12T06:45:19.423924Z","iopub.status.idle":"2022-03-12T06:45:19.433856Z","shell.execute_reply.started":"2022-03-12T06:45:19.423894Z","shell.execute_reply":"2022-03-12T06:45:19.431549Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mask = mask_img(img_thresh(image))","metadata":{"execution":{"iopub.status.busy":"2022-03-12T07:04:53.512596Z","iopub.execute_input":"2022-03-12T07:04:53.51287Z","iopub.status.idle":"2022-03-12T07:04:54.238498Z","shell.execute_reply.started":"2022-03-12T07:04:53.51284Z","shell.execute_reply":"2022-03-12T07:04:54.237526Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## STEP 4 - FIND CONTOURS AND DRAW BBOXES","metadata":{}},{"cell_type":"code","source":"def find_cont(img_in, mask, debug = False, draw = False):\n    bbox_list = []\n    backtorgb = None\n\n    cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n    cnts = imutils.grab_contours(cnts)\n    cnts = contours.sort_contours(cnts)[0]\n    if debug:\n        print(f'Found {len(cnts)} contours / numbers')\n        backtorgb = cv2.cvtColor(img_in.astype('float32'), cv2.COLOR_GRAY2RGB)\n\n    for (i, c) in enumerate(cnts):\n        (x, y, w, h) = cv2.boundingRect(c)\n        bbox_list.append([x, y, w, h])\n        if draw:\n            cv2.rectangle(backtorgb, (x,y), (x+w, y+h), (255,0,0), 5)\n\n    if debug:\n        print(f'BBoxes coordinates: {bbox_list}')\n    return bbox_list, backtorgb","metadata":{"execution":{"iopub.status.busy":"2022-03-12T07:04:54.978525Z","iopub.execute_input":"2022-03-12T07:04:54.978821Z","iopub.status.idle":"2022-03-12T07:04:54.988771Z","shell.execute_reply.started":"2022-03-12T07:04:54.978781Z","shell.execute_reply":"2022-03-12T07:04:54.987641Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"bbox_list, backtorgb = find_cont(image, mask, debug = True, draw = True)","metadata":{"execution":{"iopub.status.busy":"2022-03-12T07:04:57.226517Z","iopub.execute_input":"2022-03-12T07:04:57.227102Z","iopub.status.idle":"2022-03-12T07:04:57.320605Z","shell.execute_reply.started":"2022-03-12T07:04:57.227067Z","shell.execute_reply":"2022-03-12T07:04:57.317626Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"display(Img.fromarray(backtorgb.astype(np.uint8)).resize((480,480)))","metadata":{"execution":{"iopub.status.busy":"2022-03-12T07:04:58.540958Z","iopub.execute_input":"2022-03-12T07:04:58.541286Z","iopub.status.idle":"2022-03-12T07:04:58.749494Z","shell.execute_reply.started":"2022-03-12T07:04:58.541252Z","shell.execute_reply":"2022-03-12T07:04:58.748347Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## STEP 5 - CROP AND RESIZE","metadata":{}},{"cell_type":"code","source":"def mnist_numbers(img_in, bbox_list, display_img = False):    \n    # To look digits MNIST like I introduced margin and converted to 28x28\n    offset = 5\n    IMG_SIZE = 28\n\n    numbers = []\n\n    for bbox in bbox_list:\n                   \n        bbox_img = img_in[bbox[1]:bbox[1]+bbox[3], bbox[0]:bbox[0]+bbox[2]]\n        h, w = bbox_img.shape\n        \n        if bbox[3] > bbox[2]:\n            scale = bbox[3]\n            offset_w = int((scale - w) / 2)\n            offset_h = 0\n        else:\n            scale = bbox[2]\n            offset_h = int((scale - h) / 2)\n            offset_w = 0\n        \n        canvas = np.zeros((scale, scale))\n        canvas[0+offset_h:h+offset_h, 0+offset_w:w+offset_w] = bbox_img\n        \n        bbox_resized = cv2.resize(canvas, (IMG_SIZE - 2 * offset, IMG_SIZE - 2 * offset), interpolation = cv2.INTER_AREA)    \n        \n        letterbox = np.zeros((IMG_SIZE, IMG_SIZE))\n        letterbox[offset:IMG_SIZE-offset, offset:IMG_SIZE-offset] = bbox_resized\n        numbers.append(letterbox)\n        \n        if display_img:\n            display(Img.fromarray((letterbox).astype(np.uint8)))\n    \n    return numbers","metadata":{"execution":{"iopub.status.busy":"2022-03-12T07:05:01.354245Z","iopub.execute_input":"2022-03-12T07:05:01.355096Z","iopub.status.idle":"2022-03-12T07:05:01.37553Z","shell.execute_reply.started":"2022-03-12T07:05:01.355043Z","shell.execute_reply":"2022-03-12T07:05:01.373377Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"numbers = mnist_numbers(image, bbox_list, display_img = True)","metadata":{"execution":{"iopub.status.busy":"2022-03-12T07:05:03.544309Z","iopub.execute_input":"2022-03-12T07:05:03.544621Z","iopub.status.idle":"2022-03-12T07:05:03.575895Z","shell.execute_reply.started":"2022-03-12T07:05:03.544589Z","shell.execute_reply":"2022-03-12T07:05:03.574908Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Full pipeline\nmask = mask_img(img_thresh(image))\nbbox_list, backtorgb = find_cont(image, mask)\nnumbers = mnist_numbers(image, bbox_list, display_img = True)","metadata":{"execution":{"iopub.status.busy":"2022-03-12T07:05:06.103176Z","iopub.execute_input":"2022-03-12T07:05:06.10384Z","iopub.status.idle":"2022-03-12T07:05:06.858368Z","shell.execute_reply.started":"2022-03-12T07:05:06.103802Z","shell.execute_reply":"2022-03-12T07:05:06.857336Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## STEP 6 - MAKE STANDARD MNIST NUMBER RECOGNITION\n\nI decided to impelment this part as well. I used pretrained Keras model from Kaggle. Source: [MNIST with Keras for Beginners(.99457)](https://www.kaggle.com/adityaecdrid/mnist-with-keras-for-beginners-99457/notebook)","metadata":{}},{"cell_type":"code","source":"import keras\nfrom keras.models import Sequential\nfrom keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPool2D, BatchNormalization\nfrom keras.callbacks import ReduceLROnPlateau\nfrom sklearn.model_selection import train_test_split","metadata":{"execution":{"iopub.status.busy":"2022-03-12T06:22:26.706731Z","iopub.execute_input":"2022-03-12T06:22:26.707055Z","iopub.status.idle":"2022-03-12T06:22:32.363905Z","shell.execute_reply.started":"2022-03-12T06:22:26.707023Z","shell.execute_reply":"2022-03-12T06:22:32.362918Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"num_classes = 10\ninput_shape = (28, 28, 1)","metadata":{"execution":{"iopub.status.busy":"2022-03-12T06:22:35.264953Z","iopub.execute_input":"2022-03-12T06:22:35.265536Z","iopub.status.idle":"2022-03-12T06:22:35.270935Z","shell.execute_reply.started":"2022-03-12T06:22:35.265491Z","shell.execute_reply":"2022-03-12T06:22:35.269971Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = Sequential()\nmodel.add(Conv2D(32, kernel_size=(3, 3),activation='relu',kernel_initializer='he_normal',input_shape=input_shape))\nmodel.add(Conv2D(32, kernel_size=(3, 3),activation='relu',kernel_initializer='he_normal'))\nmodel.add(MaxPool2D((2, 2)))\nmodel.add(Dropout(0.20))\nmodel.add(Conv2D(64, (3, 3), activation='relu',padding='same',kernel_initializer='he_normal'))\nmodel.add(Conv2D(64, (3, 3), activation='relu',padding='same',kernel_initializer='he_normal'))\nmodel.add(MaxPool2D(pool_size=(2, 2)))\nmodel.add(Dropout(0.25))\nmodel.add(Conv2D(128, (3, 3), activation='relu',padding='same',kernel_initializer='he_normal'))\nmodel.add(Dropout(0.25))\nmodel.add(Flatten())\nmodel.add(Dense(128, activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(Dropout(0.25))\nmodel.add(Dense(num_classes, activation='softmax'))\n","metadata":{"execution":{"iopub.status.busy":"2022-03-12T06:22:37.027196Z","iopub.execute_input":"2022-03-12T06:22:37.027895Z","iopub.status.idle":"2022-03-12T06:22:39.896579Z","shell.execute_reply.started":"2022-03-12T06:22:37.027858Z","shell.execute_reply":"2022-03-12T06:22:39.893742Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# This is public model - everybody can use it ... as I understand it does not break competition rules.\n\nmodel.load_weights(\"../input/mnist-with-keras-for-beginners-99457/my_model_1.h5\")","metadata":{"execution":{"iopub.status.busy":"2022-03-12T06:22:42.298272Z","iopub.execute_input":"2022-03-12T06:22:42.298772Z","iopub.status.idle":"2022-03-12T06:22:42.379575Z","shell.execute_reply.started":"2022-03-12T06:22:42.298721Z","shell.execute_reply":"2022-03-12T06:22:42.378575Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def detect_sum(numbers_in, debug = False):\n    pred_numbers = []\n    mnist_sum = 0\n    for number in numbers_in:\n        x = number.reshape(1, 28, 28, 1)\n        n = np.argmax(model.predict(x))\n        pred_numbers.append(n)\n        mnist_sum += n\n\n        if debug:\n            print(f'Number: {n}')\n\n    if debug:\n        print(f\"\\nSUM: {colored(mnist_sum, 'red')}\")\n    return mnist_sum, pred_numbers","metadata":{"execution":{"iopub.status.busy":"2022-03-12T06:22:44.898012Z","iopub.execute_input":"2022-03-12T06:22:44.898653Z","iopub.status.idle":"2022-03-12T06:22:44.905882Z","shell.execute_reply.started":"2022-03-12T06:22:44.898614Z","shell.execute_reply":"2022-03-12T06:22:44.904776Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mnist_sum, _ = detect_sum(numbers, debug = True)","metadata":{"execution":{"iopub.status.busy":"2022-03-12T06:22:47.456359Z","iopub.execute_input":"2022-03-12T06:22:47.457044Z","iopub.status.idle":"2022-03-12T06:22:54.087775Z","shell.execute_reply.started":"2022-03-12T06:22:47.457006Z","shell.execute_reply":"2022-03-12T06:22:54.085157Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Let's make prediction for 9 images - this is demo only \nIMG_PATH = \"../input/ultramnistblack/train/\" \nN_SAMPLES = 9\ncorrect = 0\nindex = 0\n\npredictions = []\n\ndfx = train_df.sample(n = N_SAMPLES)\nfig, axes = plt.subplots(3, 3, figsize=(20,20))\nfig.subplots_adjust(top = 0.9)\n\n\nfor idx, row in dfx.iterrows():\n    file = f'{IMG_PATH}{row.id}.jpeg'\n    image = cv2.imread(file, 0)\n    \n    mask = mask_img(img_thresh(image))\n    bbox_list, backtorgb = find_cont(image, mask)\n    numbers = mnist_numbers(image, bbox_list)\n    predicted, pred_numbers = detect_sum(numbers)\n    predictions.append([row.id, predicted, pred_numbers])\n    if row.digit_sum == predicted:\n        correct += 1\n    \n    i = index % 3 \n    j = index // 3  \n    image = Img.open(file)\n    axes[i, j].imshow(image)\n    axes[i, j].set_title(f'file id: {row.id} GT: {row.digit_sum}  DETECTED: {predicted} \\n {predictions[index]}')\n    index += 1\n\nplt.subplots_adjust(wspace=0.1, hspace=0.2)\nfig.suptitle(f'% predicted: {correct / N_SAMPLES * 100}', fontsize=16, y = 0.95)\nplt.savefig(\"plot.png\")\nplt.show()\n\nprint(f'\\n>> % predicted: {correct / N_SAMPLES * 100} <<')\n    ","metadata":{"execution":{"iopub.status.busy":"2022-03-12T07:05:16.700529Z","iopub.execute_input":"2022-03-12T07:05:16.700838Z","iopub.status.idle":"2022-03-12T07:05:49.357241Z","shell.execute_reply.started":"2022-03-12T07:05:16.700799Z","shell.execute_reply":"2022-03-12T07:05:49.354568Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# This is debugger for prediction analysis\n\nfor preds in predictions:\n    print(f'{preds}')","metadata":{"execution":{"iopub.status.busy":"2022-03-12T07:04:30.034929Z","iopub.execute_input":"2022-03-12T07:04:30.035356Z","iopub.status.idle":"2022-03-12T07:04:30.04413Z","shell.execute_reply.started":"2022-03-12T07:04:30.035291Z","shell.execute_reply":"2022-03-12T07:04:30.042831Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## STEP 7 - VALIDATION","metadata":{}},{"cell_type":"code","source":"def gen_boxes(filename, path):\n    ultra_bboxes = []\n    file = f'{path}{filename}.jpeg'\n    image = cv2.imread(file, 0)\n    \n    mask = mask_img(img_thresh(image))\n    bbox_list, backtorgb = find_cont(image, mask)\n    numbers = mnist_numbers(image, bbox_list)\n    ultra_bboxes.append(numbers)\n    return ultra_bboxes","metadata":{"execution":{"iopub.status.busy":"2022-03-12T06:24:29.021143Z","iopub.execute_input":"2022-03-12T06:24:29.021511Z","iopub.status.idle":"2022-03-12T06:24:29.028279Z","shell.execute_reply.started":"2022-03-12T06:24:29.021465Z","shell.execute_reply":"2022-03-12T06:24:29.027279Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\n\nIMG_PATH = \"../input/ultramnistblack/train/\"\nVAL_IMG = 200\n\nsuccess = 0\ncount = 0\nsub = []\n\ndxx = train_df[0:VAL_IMG]\n\nmnist_preds = Parallel(n_jobs=8, backend='threading')(delayed(\n    gen_boxes)(filename, IMG_PATH) for filename in tqdm(dxx.id.values))\n\n\nfor sample in tqdm(mnist_preds):\n    predicted, pred_numbers = detect_sum(sample[0])\n    if dxx.iloc[count].digit_sum == predicted:\n        success += 1\n    sub.append(predicted)\n    count +=1\n\nprint(f\"VAL score: {success / VAL_IMG * 100} %\")","metadata":{"execution":{"iopub.status.busy":"2022-03-12T06:45:48.281424Z","iopub.execute_input":"2022-03-12T06:45:48.282076Z","iopub.status.idle":"2022-03-12T07:00:24.160431Z","shell.execute_reply.started":"2022-03-12T06:45:48.282028Z","shell.execute_reply":"2022-03-12T07:00:24.159385Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## STEP 8 - SUBMIT\nI use Parallel from joblib to speed up process. I am sure you can find better way to speed up process. ","metadata":{}},{"cell_type":"markdown","source":"### STEP 1 - GENERATE MNIST BBOXES","metadata":{}},{"cell_type":"code","source":"%%time\n\nIMG_PATH = \"../input/ultramnistblack/test/\"\n\nmnist_preds = Parallel(n_jobs=8, backend='threading')(delayed(\n    gen_boxes)(filename, IMG_PATH) for filename in tqdm(test_df.id.values))","metadata":{"execution":{"iopub.status.busy":"2022-03-11T16:46:38.582034Z","iopub.execute_input":"2022-03-11T16:46:38.582787Z","iopub.status.idle":"2022-03-11T16:46:43.4638Z","shell.execute_reply.started":"2022-03-11T16:46:38.582747Z","shell.execute_reply":"2022-03-11T16:46:43.463149Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### STEP 2 - DIGIT PREDICTION AND SUMMARY","metadata":{}},{"cell_type":"code","source":"%%time\nsub = []\n\nfor sample in tqdm(mnist_preds):\n    predicted, pred_numbers = detect_sum(sample[0])\n    sub.append(predicted)","metadata":{"execution":{"iopub.status.busy":"2022-03-11T16:46:43.467382Z","iopub.execute_input":"2022-03-11T16:46:43.469443Z","iopub.status.idle":"2022-03-11T16:47:15.725771Z","shell.execute_reply.started":"2022-03-11T16:46:43.469406Z","shell.execute_reply":"2022-03-11T16:47:15.725037Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df['digit_sum'] = sub\ntest_df.to_csv('submission.csv', index=False)\n\ntest_df.head(10)","metadata":{"execution":{"iopub.status.busy":"2022-03-11T16:47:15.727029Z","iopub.execute_input":"2022-03-11T16:47:15.72745Z","iopub.status.idle":"2022-03-11T16:47:15.762082Z","shell.execute_reply.started":"2022-03-11T16:47:15.727412Z","shell.execute_reply":"2022-03-11T16:47:15.75977Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Summary and observations:\n- digits are really good detected \n- very long computation time - to improve performance\n\nTO IMPROVE - there are many things to improve in this notebook. This is only demo which was created in 1 day only for demo purposes - many additional experiments are required and parameter optimizations.\n\n- letters extraction process - at this time parameters are almost randomly choosen - only tiny parameter adjustment \n- model - I took first one I found on Kaggle (I do not investigated model performance)\n- sum up part - I do not validate sum of prediction (max  27) - it can be improved ","metadata":{}}]}