{"cells":[{"metadata":{},"cell_type":"markdown","source":"## Motivation\n\nThe Global Wheat Detection dataset is collected from different places and they are different. Let's see some images from different sources.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"import os.path as osp\nimport pandas as pd\n\ndata_dir = '/kaggle/input/global-wheat-detection'\n\nlabels = pd.read_csv(osp.join(data_dir, 'train.csv'))\nsources = labels.source.unique()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import cv2 as cv\nimport numpy as np\nfrom matplotlib import pyplot as plt\n\ndef get_source_labels(source):\n    result = dict()\n    \n    source_labels = labels[labels.source == source]\n    source_image_ids = source_labels.image_id.unique()\n    for image_id in source_image_ids:\n        image_labels = labels[labels.image_id == image_id]\n        assert np.all(image_labels.source == source)\n        \n        width = image_labels.width.iloc[0]\n        assert np.all(image_labels.width == width)\n        \n        height = image_labels.height.iloc[0]\n        assert np.all(image_labels.height == height)\n        \n        bboxes = [list(map(int, eval(bbox))) for bbox in image_labels.bbox]\n        \n        result[image_id] = {\n            'width': width,\n            'height': height,\n            'bboxes': bboxes\n        }\n        \n    return result\n\ndef show_random_images(source_labels, source, nrows=2, ncols=4, gt=True):\n    image_ids = np.random.choice(list(source_labels.keys()), nrows * ncols).reshape((nrows, ncols))\n    \n    f, axes = plt.subplots(nrows, ncols)\n    f.set_figwidth(ncols * 10)\n    f.set_figheight(nrows * 10)\n    \n    for row, (row_ids, row_axes) in enumerate(zip(image_ids, axes)):\n        for col, (image_id, ax) in enumerate(zip(row_ids, row_axes)):\n            image = cv.imread(osp.join(data_dir, 'train', image_id + '.jpg'), cv.IMREAD_COLOR)\n            image = cv.cvtColor(image, cv.COLOR_BGR2RGB)\n            if gt:\n                bboxes = source_labels[image_id]['bboxes']\n                for x, y, w, h in bboxes:\n                    cv.rectangle(image, (x, y), (x + w, y + h), (255, 0, 0), 2)\n            \n            ax.imshow(image)\n            ax.set_axis_off()\n            \n    plt.suptitle('{} random images for {}'.format(nrows * ncols, source), fontsize=40)\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for source in sources:\n    source_labels = get_source_labels(source)\n    show_random_images(source_labels, source)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"As we can see the sources are very different from each other. The main interest for object detection is bounding boxes as we compute the loss for each bounding box. Therefore we should be careful with differences in bounding boxes between different sources. \n\n\n## Imbalance\n\nFirst, lets see on the number of images and bounding bboxes for different sources.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"sources, images_count, bboxes_count = [], [], []\nfor source in labels.source.unique():\n    source_labels = labels[labels.source == source]\n    sources.append(source)\n    images_count.append(source_labels.image_id.unique().shape[0])\n    bboxes_count.append(source_labels.shape[0])    \n\nfig, axes = plt.subplots(1, 2)\nfig.set_figwidth(20)\nfig.set_figheight(10)\n\naxes[0].pie(images_count, labels=sources)\naxes[0].set_title('Images count', fontsize=30)\n\naxes[1].pie(bboxes_count, labels=sources)\naxes[1].set_title('Bboxes count', fontsize=30)\n\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"There is high imbalance in images count and bboxes count. It means that our model will suffer on inrae_1, arvalis_3 and usask_1 sources. The easiest way to fix this is upsampling.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"source_multipliers = {source: int(np.round(np.max(images_count) / image_count)) \n                      for source, image_count in zip(sources, images_count)}\nsource_multipliers","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"We can simply increase images count for small sources just creating 5 new copies for inrae_1 (1 existing + 5 new = 6 total). This will give us images and bboxes distributions much more balanced.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"multiplied_images_counts, multiplied_bboxes_counts = [], []\nfor source, image_count, bb_count, multiplier in zip(sources, images_count, bboxes_count, list(source_multipliers.values())):\n    multiplied_images_counts.append(multiplier * image_count)\n    multiplied_bboxes_counts.append(multiplier * bb_count)\n    \nfig, axes = plt.subplots(1, 2)\nfig.set_figwidth(20)\nfig.set_figheight(10)\n\naxes[0].pie(multiplied_images_counts, labels=sources)\naxes[0].set_title('Multiplied images count', fontsize=30)\n\naxes[1].pie(multiplied_bboxes_counts, labels=sources)\naxes[1].set_title('Multiplied bboxes count', fontsize=30)\n\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"This simple procedure increased my LB score by 0.03.","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"## Bounding box coverage\n\nOne more interesting thing is to see bboxes distribution along images for different sources.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def show_bbox_coverage(source_labels, source):\n    result = np.zeros((1024, 1024), dtype=np.uint32)\n    for image_meta in source_labels.values():\n        for x, y, w, h in image_meta['bboxes']:\n            result[y: y + h, x: x + w] += 1\n            \n    plt.figure(figsize=(10, 10))\n    plt.matshow(result, fignum=0)\n    plt.title('Bboxes coverage ' + source, fontsize=20)\n    plt.xlabel('x')\n    plt.ylabel('y')\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for source in sources:\n    source_labels = get_source_labels(source)\n    show_bbox_coverage(source_labels, source)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"We can also see some imbalance in bboxes distribution. We can try to use flips augmentation as a baseline to fix it.\n\nGood luck!","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"","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}