{"cells":[{"metadata":{},"cell_type":"markdown","source":"# INSTALL LIBRARIES","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"!pip install /kaggle/input/wheels/torch-1.5.0cu101-cp37-cp37m-linux_x86_64.whl","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!pip install /kaggle/input/wheels/torchvision-0.6.0cu101-cp37-cp37m-linux_x86_64.whl","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!pip install /kaggle/input/wheels/yacs-0.1.7-py3-none-any.whl","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!pip install /kaggle/input/wheels/fvcore-0.1.1.post200513-py3-none-any.whl","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!pip install /kaggle/input/wheels/pycocotools-2.0-cp37-cp37m-linux_x86_64.whl","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!pip install /kaggle/input/wheels/detectron2-0.1.3cu101-cp37-cp37m-linux_x86_64.whl","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!pip install -U /kaggle/input/wheels/watermark-2.0.2-py2.py3-none-any.whl","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%reload_ext watermark\n%watermark -v -p numpy,pandas,pycocotools,torch,torchvision,detectron2","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# SET PATHS","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"from pathlib import Path","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"DATA_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":"# IMPORT NECESSARY LIBRARIES","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"import 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":"# EDA","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":"train_df.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df.info()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df['source'].unique()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df['image_id'].unique().shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"dataset = []\n\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)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df = pd.DataFrame(dataset)\n\ndf.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df.head()","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":{},"cell_type":"markdown","source":"# Prepare train and val","execution_count":null},{"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.95), replace=False))\ntrain_df = df[df.file_name.isin(train_files)]\nval_df = df[~df.file_name.isin(train_files)]\n","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\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"classes = df.class_name.unique().tolist()\nclasses\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Prepare Dataset for training","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# Convert to format used by detectron2\ndef 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","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\")\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Visualize prepared dict","execution_count":null},{"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":"# TRAINING CONFIG","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# DatasetCatalog.get(name='wheat_train')[1]\n\n# evaluator\nclass 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":"# Load the config file and the pre-trained model weights\ncfg = get_cfg()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"cfg.merge_from_file(\n  model_zoo.get_config_file(\n    \"COCO-InstanceSegmentation/mask_rcnn_X_101_32x8d_FPN_3x.yaml\")\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"WEIGHT_PATH = '/kaggle/input/weights/model_final.pth'\ncfg.MODEL.WEIGHTS = WEIGHT_PATH","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\"\"\"\ncfg.MODEL.WEIGHTS = model_zoo.get_checkpoint_url(\n  \"COCO-InstanceSegmentation/mask_rcnn_X_101_32x8d_FPN_3x.yaml\"\n)\n\"\"\"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# print(cfg.dump())\n\ncfg.DATASETS.TRAIN = (\"wheat_train\",)\ncfg.DATASETS.TEST = (\"wheat_val\",)\ncfg.DATALOADER.NUM_WORKERS = 4\n\ncfg.SOLVER.IMS_PER_BATCH = 4\ncfg.SOLVER.BASE_LR = 0.001\ncfg.SOLVER.WARMUP_ITERS = 1000\ncfg.SOLVER.MAX_ITER = 100\ncfg.SOLVER.STEPS = (10, 50)\ncfg.SOLVER.GAMMA = 0.05\n\ncfg.MODEL.ROI_HEADS.BATCH_SIZE_PER_IMAGE = 64\ncfg.MODEL.ROI_HEADS.NUM_CLASSES = len(classes)\ncfg.TEST.EVAL_PERIOD = 1000","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# print(cfg.dump())\nos.makedirs(cfg.OUTPUT_DIR, exist_ok=True)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# TRAIN MODEL","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"trainer = CocoTrainer(cfg)\ntrainer.resume_or_load(resume=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"trainer.train()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# EVALUATE","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"print(cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST)","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.85\n# predictor = DefaultPredictor(cfg)","execution_count":null,"outputs":[]},{"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":{},"cell_type":"markdown","source":"# TEST IMAGES","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# Finding wheats in images\n\n# cfg.MODEL.WEIGHTS = os.path.join(cfg.OUTPUT_DIR, \"model_final.pth\")\ncfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.45\npredictor = DefaultPredictor(cfg)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# os.makedirs(\"annotated_results\", exist_ok=True)\ntest_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)","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":{"trusted":true},"cell_type":"code","source":"img =cv2.cvtColor(annotated_results[9], 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[4], cv2.COLOR_BGR2RGB)\nplt.imshow(img)\nplt.axis('off')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 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        # 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":{"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}