{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Global Wheat Detection - Inference\n\nYou can get the training scripts [here](https://github.com/ufownl/global-wheat-detection).\n\n* YOLOv3 from [GluonCV](https://gluon-cv.mxnet.io/)\n* Use Darknet53 backbone\n* Use [WBF](https://github.com/ZFTurbo/Weighted-Boxes-Fusion) over TTA","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"## Dataset","execution_count":null},{"metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","trusted":true},"cell_type":"code","source":"import mxnet as mx\n\n\ndef load_image(path):\n    with open(path, \"rb\") as f:\n        buf = f.read()\n    return mx.image.imdecode(buf)\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Model","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"import mxnet as mx\nimport gluoncv as gcv\n\n\ndef load_model(path, ctx=mx.cpu()):\n    net = gcv.model_zoo.yolo3_darknet53_custom([\"wheat\"], pretrained_base=False)\n    net.set_nms(post_nms=150)\n    net.load_parameters(path, ctx=ctx)\n    return net\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Inference","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"!ln -snf /kaggle/input/weighted-boxes-fusion/ensemble_boxes && ls -lh","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import os\nimport random\nimport numpy as np\nimport mxnet as mx\nimport pandas as pd\nimport gluoncv as gcv\nfrom ensemble_boxes import *\n\nthreshold = 0.1\nimg_s = 512\ncontext = mx.gpu()\n\nprint(\"Loading test images...\")\nimages = [\n    (os.path.join(dirname, filename), os.path.splitext(filename)[0])\n        for dirname, _, filenames in os.walk('/kaggle/input/global-wheat-detection/test') for filename in filenames\n]\n\nprint(\"Loading model...\")\nmodel = load_model(\"/kaggle/input/global-wheat-detection-private/global-wheat-yolo3-darknet53.params\", ctx=context)\n\nprint(\"Inference...\")\nresults = []\nfor path, image_id in images:\n    print(path)\n    raw = load_image(path)\n    rh, rw, _ = raw.shape\n    classes_list = []\n    scores_list = []\n    bboxes_list = []\n    for _ in range(5):\n        img, flips = gcv.data.transforms.image.random_flip(raw, px=0.5, py=0.5)\n        x, _ = gcv.data.transforms.presets.yolo.transform_test(img, short=img_s)\n        _, _, xh, xw = x.shape\n        rot = random.randint(0, 3)\n        if rot > 0:\n            x = np.rot90(x.asnumpy(), k=rot, axes=(2, 3))\n        classes, scores, bboxes = model(mx.nd.array(x, ctx=context))\n        if rot > 0:\n            if rot == 1:\n                raw_bboxes = bboxes.copy()\n                bboxes[0, :, [0, 2]] = xh - raw_bboxes[0, :, [1, 3]]\n                bboxes[0, :, [1, 3]] = raw_bboxes[0, :, [2, 0]]\n            elif rot == 2:\n                bboxes[0, :, [0, 1, 2, 3]] = mx.nd.array([[xw], [xh], [xw], [xh]], ctx=context) - bboxes[0, :, [2, 3, 0, 1]]\n            elif rot == 3:\n                raw_bboxes = bboxes.copy()\n                bboxes[0, :, [0, 2]] = raw_bboxes[0, :, [1, 3]]\n                bboxes[0, :, [1, 3]] = xw - raw_bboxes[0, :, [2, 0]]\n            raw_bboxes = bboxes.copy()\n            bboxes[0, :, 0] = raw_bboxes[0, :, [0, 2]].min(axis=0)\n            bboxes[0, :, 1] = raw_bboxes[0, :, [1, 3]].min(axis=0)\n            bboxes[0, :, 2] = raw_bboxes[0, :, [0, 2]].max(axis=0)\n            bboxes[0, :, 3] = raw_bboxes[0, :, [1, 3]].max(axis=0)\n        bboxes[0, :, :] = gcv.data.transforms.bbox.flip(bboxes[0, :, :], (xw, xh), flip_x=flips[0], flip_y=flips[1])\n        bboxes[0, :, 0::2] = (bboxes[0, :, 0::2] / (xw - 1)).clip(0.0, 1.0)\n        bboxes[0, :, 1::2] = (bboxes[0, :, 1::2] / (xh - 1)).clip(0.0, 1.0)\n        classes_list.append([\n            int(classes[0, i].asscalar()) for i in range(classes.shape[1])\n                if classes[0, i].asscalar() >= 0.0\n\n        ])\n        scores_list.append([\n            scores[0, i].asscalar() for i in range(classes.shape[1])\n                if classes[0, i].asscalar() >= 0.0\n\n        ])\n        bboxes_list.append([\n            bboxes[0, i].asnumpy().tolist() for i in range(classes.shape[1])\n                if classes[0, i].asscalar() >= 0.0\n        ])\n    bboxes, scores, classes = weighted_boxes_fusion(bboxes_list, scores_list, classes_list)\n    bboxes[:, 0::2] *= rw - 1\n    bboxes[:, 1::2] *= rh - 1\n    bboxes[:, 2:4] -= bboxes[:, 0:2]\n    results.append({\n        \"image_id\": image_id,\n        \"PredictionString\": \" \".join([\n            \" \".join([str(x) for x in [scores[i]] + [round(x) for x in bboxes[i].tolist()]])\n                for i in range(classes.shape[0])\n                    if model.classes[int(classes[i])] == \"wheat\" and scores[i] > threshold\n        ])\n    })\npd.DataFrame(results, columns=['image_id', 'PredictionString']).to_csv('submission.csv', index=False)\n","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":4}