{"cells":[{"metadata":{"trusted":true},"cell_type":"code","source":"!pip install ../input/wheat-detection/torch-1.5.0cu101-cp37-cp37m-linux_x86_64.whl\n!pip install ../input/wheat-detection/torchvision-0.6.0cu101-cp37-cp37m-linux_x86_64.whl","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!pip install ../input/wheat-detection/Pillow-7.2.0-cp37-cp37m-manylinux1_x86_64.whl\n!pip install ../input/wheat-detection/pycocotools-2.0.1-cp37-cp37m-linux_x86_64.whl\n!pip install ../input/wheat-detection/yacs-0.1.7-py3-none-any.whl\n!pip install ../input/wheat-detection/fvcore-0.1.1.post20200716-py3-none-any.whl\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!pip install ../input/wheat-detection/detectron2-0.2cu101-cp37-cp37m-linux_x86_64.whl","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from pathlib import Path\nDATA_DIR = Path('/kaggle/input/global-wheat-detection')\nTRAIN_PATH = Path(DATA_DIR / 'train')\nTEST_PATH = Path(DATA_DIR / 'test')\n\nSUB_PATH = Path(DATA_DIR / 'sample_submission.csv')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Importing libraries","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"\nimport torch, torchvision\nimport detectron2\nfrom detectron2.utils.logger import setup_logger\nsetup_logger()\n\nimport glob\n\nimport os\nimport ntpath\nimport numpy as np\nimport cv2\nimport random\nimport itertools\nimport pandas as pd\nfrom tqdm import tqdm\nimport urllib\nimport json\nimport PIL.Image as Image\n\nfrom detectron2 import model_zoo\nfrom detectron2.engine import DefaultPredictor, DefaultTrainer\nfrom detectron2.config import get_cfg\nfrom detectron2.utils.visualizer import Visualizer, ColorMode\nfrom detectron2.data import DatasetCatalog, MetadataCatalog, build_detection_test_loader\nfrom detectron2.evaluation import COCOEvaluator, inference_on_dataset\nfrom detectron2.structures import BoxMode\n\nimport seaborn as sns\nfrom pylab import rcParams\nimport matplotlib.pyplot as plt\nfrom matplotlib import rc\n\n%matplotlib inline\n%config InlineBackend.figure_format='retina'\nsns.set(style='whitegrid', palette='muted', font_scale=1.2)\n\nHAPPY_COLORS_PALETTE = [\"#01BEFE\", \"#FFDD00\", \"#FF7D00\", \"#FF006D\", \"#ADFF02\", \"#8F00FF\"]\n\nsns.set_palette(sns.color_palette(HAPPY_COLORS_PALETTE))\n\nrcParams['figure.figsize'] = 12, 8\n\nRANDOM_SEED = 42\nnp.random.seed(RANDOM_SEED)\ntorch.manual_seed(RANDOM_SEED)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"torch.device('cuda' if torch.cuda.is_available() else 'cpu')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Importing data","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df = pd.read_csv(DATA_DIR / 'train.csv')\n\ntrain_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"dataset = []\nfor index, row in tqdm(train_df.iterrows(), total=train_df.shape[0]):\n    image_name = f\"{row['image_id']}.jpg\"\n\n    bboxes = row['bbox']\n    bboxes = bboxes.replace('[', '')\n    bboxes = bboxes.replace(']', '')\n    bboxes = bboxes.split(',')\n\n    x_min = float(bboxes[0])\n    y_min = float(bboxes[1])\n    x_max = float(bboxes[2])\n    y_max = float(bboxes[3])\n\n    data = {}\n\n    width = row['width']\n    height = row['height']\n\n    data['file_name'] = image_name\n    data['width'] = width\n    data['height'] = height\n\n    data[\"x_min\"] = x_min\n    data[\"y_min\"] = y_min\n    data[\"x_max\"] = x_max\n    data[\"y_max\"] = y_max\n\n    data['class_name'] = 'wheat'\n      \n    dataset.append(data)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df = pd.DataFrame(dataset)\n\ndf.shape\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df.head(2)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def annotate_image(annotations, resize=True, path=str(TRAIN_PATH)):\n    file_name = annotations.file_name.to_numpy()[0]\n    img = cv2.cvtColor(cv2.imread(f'{path}/{file_name}'), cv2.COLOR_BGR2RGB)\n    for i, a in annotations.iterrows():\n        cv2.rectangle(img, (int(a.x_min), int(a.y_min)), (int(a.x_max) + int(a.x_min), int(a.y_max) + int(a.y_min)), (0, 255, 0), 2)\n    if not resize:\n        return img\n    return cv2.resize(img, (384, 384), interpolation = cv2.INTER_AREA)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"img_id = np.random.randint(len(df.file_name.unique())) \nimg_df = df[df.file_name == df.file_name.unique()[img_id]]\n# img_df\n\nimg = annotate_image(img_df, resize=False)\nplt.imshow(img)\nplt.axis('off')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# import torch, torchvision\nsample_images = [annotate_image(df[df.file_name == f]) for f in df.file_name.unique()[:10]]\nsample_images = torch.as_tensor(sample_images)\n\nsample_images = sample_images.permute(0, 3, 1, 2)\n\nplt.figure(figsize=(24, 12))\ngrid_img = torchvision.utils.make_grid(sample_images, nrow=5)\n\nplt.imshow(grid_img.permute(1, 2, 0))\nplt.axis('off')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# TRAINING\nunique_files = df.file_name.unique()\n\ntrain_files = set(np.random.choice(unique_files, int(len(unique_files) * 0.98), replace=False))\ntrain_df = df[df.file_name.isin(train_files)]\nval_df = df[~df.file_name.isin(train_files)]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"val_df.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"classes = df.class_name.unique().tolist()\nclasses","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Create dataset in Detectron 2 format","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def create_dataset_dicts(df, classes):\n  dataset_dicts = []\n  for image_id, img_name in enumerate(df.file_name.unique()):\n    record = {}\n    image_df = df[df.file_name == img_name]\n    file_path = f'{TRAIN_PATH}/{img_name}'\n    record[\"file_name\"] = file_path\n    record[\"image_id\"] = image_id\n    record[\"height\"] = int(image_df.iloc[0].height)\n    record[\"width\"] = int(image_df.iloc[0].width)\n    objs = []\n    for _, row in image_df.iterrows():\n      xmin = int(row.x_min)\n      ymin = int(row.y_min)\n      xmax = int(row.x_max)\n      ymax = int(row.y_max)\n\n      poly = [\n          (xmin, ymin), (xmin+xmax, ymin),\n          (xmin+xmax, ymin+ymax), (xmin, ymin+ymax)\n      ]\n      poly = list(itertools.chain.from_iterable(poly))\n\n      obj = {\n        \"bbox\": [xmin, ymin, xmin+xmax, ymin+ymax],\n        \"bbox_mode\": BoxMode.XYXY_ABS,\n        \"segmentation\": [poly],\n        \"category_id\": classes.index(row.class_name),\n        \"iscrowd\": 0\n      }\n      objs.append(obj)\n    record[\"annotations\"] = objs\n    dataset_dicts.append(record)\n  return dataset_dicts\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# register dataset inot the dataset and metadata catalogues\nfor d in [\"train\", \"val\"]:\n  DatasetCatalog.register(\"wheat_\" + d, lambda d=d: create_dataset_dicts(train_df if d == \"train\" else val_df, classes))\n  MetadataCatalog.get(\"wheat_\" + d).set(thing_classes=classes)\n  \nstatement_metadata = MetadataCatalog.get(\"wheat_train\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"dataset_dicts = create_dataset_dicts(train_df, classes)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"nrows = 1\nncols = 3\n\n# Index for iterating over images\npic_index = 0\n\n\nfig = plt.gcf()\n\nfig.set_size_inches(ncols * 8, nrows * 12)\n\nfor i, d in enumerate(random.sample(dataset_dicts, 3)):\n    \n    sp = plt.subplot(nrows, ncols, i + 1, facecolor='red')\n    sp.axis('Off')\n    \n    img = cv2.imread(d[\"file_name\"])\n    visualizer = Visualizer(img[:, :, ::-1], metadata=statement_metadata, scale=0.5)\n    vis = visualizer.draw_dataset_dict(d)\n    plt.imshow(vis.get_image()[:, :, ::-1], interpolation = 'bicubic')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Creating Model - Faster RCNN","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"class CocoTrainer(DefaultTrainer):\n  @classmethod\n  def build_evaluator(cls, cfg, dataset_name, output_folder=None):\n    if output_folder is None:\n        os.makedirs(\"coco_eval\", exist_ok=True)\n        output_folder = \"coco_eval\"\n    return COCOEvaluator(dataset_name, cfg, False, output_folder)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\ncfg = get_cfg()\ncfg.merge_from_file(model_zoo.get_config_file(\"COCO-Detection/faster_rcnn_X_101_32x8d_FPN_3x.yaml\"))\ncfg.DATASETS.TRAIN = (\"wheat_train\",)\ncfg.DATASETS.TEST = ()\ncfg.DATALOADER.NUM_WORKERS = 2\n#cfg.MODEL.WEIGHTS = model_zoo.get_checkpoint_url(\"COCO-Detection/faster_rcnn_X_101_32x8d_FPN_3x.yaml\")  \ncfg.MODEL.WEIGHTS = os.path.join('../input/wheat-detection-model/output/model_final.pth')\ncfg.SOLVER.IMS_PER_BATCH = 8\ncfg.SOLVER.BASE_LR = 0.0001  \ncfg.SOLVER.MAX_ITER = 5000   \ncfg.MODEL.ROI_HEADS.BATCH_SIZE_PER_IMAGE = 128   \ncfg.MODEL.ROI_HEADS.NUM_CLASSES = 1  \n\nos.makedirs(cfg.OUTPUT_DIR, exist_ok=True)\ntrainer = DefaultTrainer(cfg) \ntrainer.resume_or_load(resume=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"os.makedirs(cfg.OUTPUT_DIR, exist_ok=True)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Training","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"trainer.train()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#cfg.MODEL.WEIGHTS = os.path.join(cfg.OUTPUT_DIR, \"model_final.pth\")\ncfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.6\ncfg.DATASETS.TEST = (\"wheat_val\", )\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Evaluating","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"evaluator = COCOEvaluator(\"wheat_val\", cfg, False, output_dir=\"./output/\")\nval_loader = build_detection_test_loader(cfg, \"wheat_val\")\ninference_on_dataset(trainer.model, val_loader, evaluator)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Finding wheats in images\n\ncfg.MODEL.WEIGHTS = os.path.join(cfg.OUTPUT_DIR, \"model_final.pth\")\ncfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.50\npredictor = DefaultPredictor(cfg)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_image_paths = os.listdir(TEST_PATH)\n\ntest_image_paths","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"annotated_results = []\n\nfor wheat_image in test_image_paths:\n  file_path = f'{TEST_PATH}/{wheat_image}'\n  im = cv2.imread(file_path)\n  outputs = predictor(im)\n  v = Visualizer(\n    im[:, :, ::-1],\n    metadata=statement_metadata,\n    scale=1.,\n    instance_mode=ColorMode.IMAGE\n  )\n  instances = outputs[\"instances\"].to(\"cpu\")\n  # instances.remove('pred_masks')\n  v = v.draw_instance_predictions(instances)\n  result = v.get_image()[:, :, ::-1]\n  file_name = ntpath.basename(wheat_image)\n  annotated_results.append(result)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"img =cv2.cvtColor(annotated_results[0], cv2.COLOR_BGR2RGB)\nplt.imshow(img)\nplt.axis('off')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"img =cv2.cvtColor(annotated_results[1], cv2.COLOR_BGR2RGB)\nplt.imshow(img)\nplt.axis('off')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Creating submission","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"sub_df = pd.read_csv(SUB_PATH)\nsub_df","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def submit():\n    for idx, row in tqdm(sub_df.iterrows(), total=len(sub_df)):\n        img_path = os.path.join(TEST_PATH, row.image_id + '.jpg')\n        \n        img = cv2.imread(img_path)\n        outputs = predictor(img)['instances']\n        #print(outputs)\n        # instances.remove('pred_masks')\n        #outputs.remove('pred_masks')\n        boxes = [i.cpu().detach().numpy() for i in outputs.pred_boxes]\n        scores = outputs.scores.cpu().detach().numpy()\n        list_str = []\n        for box, score in zip(boxes, scores):\n            box[3] -= box[1]\n            box[2] -= box[0]\n            box = list(map(int,box))\n            score = round(score, 4)\n            list_str.append(score)\n            list_str.extend(box)\n        sub_df.loc[idx, 'PredictionString'] = ' '.join(map(str, list_str))\n        \n    return sub_df","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"subm_df = submit()\nsubm_df.to_csv('submission.csv', index=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"subm_df","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"subm_df['PredictionString'][2]","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}