{"cells":[{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"import cv2\nfrom matplotlib import pyplot as plt\nimport numpy as np\nimport albumentations as A\nfrom albumentations.pytorch.transforms import ToTensor,ToTensorV2\nimport glob\nfrom sklearn.model_selection import train_test_split\nimport torchvision.models as models\nimport pandas as pd\n\n#sklearn\nfrom sklearn.model_selection import StratifiedKFold\n\n\nfrom torch.utils.data import Dataset, DataLoader\nimport torch\nimport torch.nn as nn\nimport numpy as np\nimport torch.nn.functional as F","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import time\nimport random\nimport os\n\ndef seed_everything(seed):\n    random.seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n    torch.backends.cudnn.deterministic = True\n    torch.backends.cudnn.benchmark = True\n\nseed_everything(42)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df=pd.read_csv(\"../input/global-wheat-detection/train.csv\")\ndf.head()\ndf['image_id']=df['image_id']+'.jpg'\nbboxs = np.stack(df['bbox'].apply(lambda x: np.fromstring(x[1:-1], sep=',')))\nfor i, column in enumerate(['x', 'y', 'w', 'h']):\n    df[column] = bboxs[:,i]\ndf.drop(columns=['bbox'], inplace=True)\ndf.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"BOX_COLOR = (255, 0, 0)\nTEXT_COLOR = (255, 255, 255)\n\ndef visualize_bbox(img, bbox, class_id, class_idx_to_name, color=BOX_COLOR, thickness=2):\n    x_min, y_min, w, h = bbox\n    x_min, x_max, y_min, y_max = int(x_min), int(x_min + w), int(y_min), int(y_min + h)\n    cv2.rectangle(img, (x_min, y_min), (x_max, y_max), color=color, thickness=thickness)\n    class_name = class_idx_to_name[class_id]\n    ((text_width, text_height), _) = cv2.getTextSize(class_name, cv2.FONT_HERSHEY_SIMPLEX, 0.35, 1)    \n    cv2.rectangle(img, (x_min, y_min - int(1.3 * text_height)), (x_min + text_width, y_min), BOX_COLOR, -1)\n    cv2.putText(img, class_name, (x_min, y_min - int(0.3 * text_height)), cv2.FONT_HERSHEY_SIMPLEX, 0.35,TEXT_COLOR, lineType=cv2.LINE_AA)\n    return img\n\n\ndef visualize(annotations, category_id_to_name,img2):\n    img = annotations['image'].copy()\n    for idx, bbox in enumerate(annotations['bboxes']):\n      img = visualize_bbox(img, bbox, annotations['labels'][idx], category_id_to_name)\n    plt.figure(figsize=(15, 15))\n    plt.subplot(1,2,1)\n    print(type(img))\n    plt.imshow(img)\n    plt.subplot(1,2,2)\n    plt.imshow(img2)\n    plt.show()\n\ndef get_aug(aug, min_area=0., min_visibility=0.):\n    return Compose(aug, bbox_params=BboxParams(format='coco', min_area=min_area, \n                                               min_visibility=min_visibility, label_fields=['labels']))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"aug=[A.VerticalFlip(p=1),A.HorizontalFlip(p=1),A.Rotate(p=1),\n     A.RandomSunFlare(p=1,flare_roi=(0.3, 0.3, 0.5, 0.7),\n                     num_flare_circles_lower=2, num_flare_circles_upper=5, src_radius=50),\n     A.OneOf([\n             A.RandomBrightness(p=1,limit=0.3),\n           A.RandomBrightnessContrast(p=1,brightness_limit=0.3, contrast_limit=0.2),\n           A.RandomContrast(p=1,limit=0.1)\n           ],p=1),\n      ]\n\ntransform=A.Compose(aug, bbox_params=A.BboxParams(format='coco', label_fields=['labels']))\n\nimage_ids = df['image_id'].unique()\nrandom.shuffle(image_ids)\nvalid_ids = image_ids[-500:]\ntrain_ids = image_ids[:-500]\n\nfor i in range(0,len(valid_ids),15):\n    p=valid_ids[i]\n    img=cv2.imread('../input/global-wheat-detection/train/'+p)\n    img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)\n    #img=image1\n    record=df[df['image_id'] == p]\n    box=record[['x', 'y', 'w', 'h']].values\n    img2=img.copy()\n\n    sample={'image': img,'bboxes': box,'labels': [1]*len(box)}\n    category_id_to_name = {0: '0',1:'100%'}\n    annotation=transform(**sample)\n    box=annotation['bboxes']\n\n    visualize(annotation,category_id_to_name,img2)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#AverageMeter - class for averaging loss,metric\nclass AverageMeter(object):\n    \"\"\"Computes and stores the average and current value\"\"\"\n    def __init__(self):\n        self.reset()\n\n    def reset(self):\n        self.val = 0\n        self.avg = 0\n        self.sum = 0\n        self.count = 0\n\n    def update(self, val, n=1):\n        self.val = val\n        self.sum += val * n\n        self.count += n\n        self.avg = self.sum / self.count","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\n\n\nclass WheatDataset(Dataset):\n\n  def __init__(self, path,df, transforms=None):\n    self.path=path\n    self.df=df\n    self.transforms=transforms\n\n  def __len__(self):\n    return len(self.path)\n\n  def __getitem__(self, idx):\n    p=self.path[idx]\n    \n    image1=cv2.imread('../input/global-wheat-detection/train/'+p,cv2.IMREAD_COLOR)\n    image1=cv2.cvtColor(image1,cv2.COLOR_BGR2RGB).astype(np.float32)\n    image1 /= 255.0\n    \n\n    records = self.df[self.df['image_id'] == p]\n    boxes = records[['x', 'y', 'w', 'h']].values\n    area = boxes[:,2]*boxes[:,3]\n    area = torch.as_tensor(area, dtype=torch.float32)\n    boxes[:, 2] = boxes[:, 0] + boxes[:, 2]\n    boxes[:, 3] = boxes[:, 1] + boxes[:, 3]\n    boxes = torch.as_tensor(boxes, dtype=torch.float32)\n\n    target={}\n    labels = torch.ones((len(boxes),), dtype=torch.int64)\n    iscrowd = torch.zeros((len(boxes),), dtype=torch.int64)\n    \n    if self.transforms:\n      sample = {\n        'image': image1,\n        'bboxes': boxes,\n        'labels': labels\n      }\n      sample=self.transforms(**sample)\n      image1 = sample['image']\n      boxes  = sample['bboxes']\n      labels = sample['labels']\n\n\n    target['boxes']=torch.as_tensor(boxes, dtype=torch.float32)\n    target[\"iscrowd\"]=torch.as_tensor(iscrowd,dtype=torch.int64 )\n    target['labels'] =  torch.as_tensor(labels,dtype=torch.int64 )\n    target['area'] = area\n    target[\"image_id\"] = torch.tensor([idx])\n    image1=torch.as_tensor(image1,dtype=torch.float32)\n    return image1,target","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"category_id_to_name = {0: '0',1:'100%'}\n\nimage_ids = df['image_id'].unique()\nrandom.shuffle(image_ids)\nvalid_ids = image_ids[-500:]\ntrain_ids = image_ids[:-500]\n\nvalid_df = df[df['image_id'].isin(image_ids)]\ntrain_df = df[df['image_id'].isin(image_ids)]\n\n#Cutout  RandomShadow CLAHE\n\naug=[A.VerticalFlip(p=0.5),A.HorizontalFlip(p=0.5),A.Rotate(p=0.5),\n          A.RandomSunFlare(p=0.5,flare_roi=(0.3, 0.3, 0.5, 0.7),\n                     num_flare_circles_lower=2, num_flare_circles_upper=5, src_radius=50),\n     A.OneOf([\n             A.RandomBrightness(p=0.5,limit=0.3),\n           A.RandomBrightnessContrast(p=0.5,brightness_limit=0.3, contrast_limit=0.2),\n       A.RandomContrast(p=0.5,limit=0.1)\n           ],p=1),\n      ToTensorV2(p=1.0)]\n\nbbox=A.BboxParams(format='pascal_voc',label_fields=['labels'])\ntransform=A.Compose(aug, bbox_params=bbox,p=1)\n\ntransformValid=A.Compose([ ToTensorV2(p=1.0)], bbox_params=bbox,p=1)\n\ndef collate_fn(batch):\n    return tuple(zip(*batch))\n\nbatch_s=4\ndataset_train=WheatDataset(train_ids,df,transforms=transform)\ntrain_loader=DataLoader(dataset_train,batch_size=batch_s,shuffle=True,collate_fn=collate_fn)\n\ndataset_val=WheatDataset(valid_ids,df,transforms=transformValid)\nval_loader=DataLoader(dataset_val,batch_size=4,collate_fn=collate_fn,shuffle=True)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"len(train_ids),len(valid_ids)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from tqdm import tqdm, notebook\n\ndef train_detr(epoch_number,model,optim,criterion,train_losses):\n  model.train()\n  criterion.train()\n  train_losses.reset()\n\n  tqdm_loader=tqdm(train_loader_detr)\n  for  index,(img,target) in enumerate(tqdm_loader):\n    img = list(image.to(device) for image in img)\n    target = [{k: v.to(device) for k, v in t.items()} for t in target]\n\n\n    out=model(img)\n    loss_dict = criterion(out, target)\n    weight_dict = criterion.weight_dict\n\n    loss1 =sum(loss_dict[k] * weight_dict[k] for k in loss_dict.keys() if k in weight_dict)\n    \n    optim.zero_grad()\n    # track the loss\n    loss1.backward()\n    optim.step()\n    train_losses.update(loss1.item(),n=batch_s)\n\n    tqdm_loader.set_description(\"Epoch {} loss item ={:4} avg={:4} \".format(epoch_number,round(loss1.item(),4),round(train_losses.avg,4)))\n\ndef train(epoch_number,model,optim,train_losses):\n  model.train()\n  train_losses.reset()\n  tqdm_loader=tqdm(train_loader)\n  for  index,(img,target) in enumerate(tqdm_loader):\n    img = list(image.to(device) for image in img)\n    target = [{k: v.to(device) for k, v in t.items()} for t in target]\n\n    out=model(img,target)\n    loss1 = sum(loss1 for loss1 in out.values())\n\n    # track the loss\n    optim.zero_grad()\n    loss1.backward()\n    optim.step()\n\n    train_losses.update(loss1.item(),n=batch_s)\n\n    tqdm_loader.set_description(\"Epoch {} loss item ={:4} avg={:4} \".format(epoch_number,round(loss1.item(),4),round(train_losses.avg,4)))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def calculate_iou(gt, pr, form='pascal_voc') -> float:\n    if form == 'coco':\n        gt = gt.copy()\n        pr = pr.copy()\n\n        gt[2] = gt[0] + gt[2]\n        gt[3] = gt[1] + gt[3]\n        pr[2] = pr[0] + pr[2]\n        pr[3] = pr[1] + pr[3]\n\n    # Calculate overlap area\n    dx = min(gt[2], pr[2]) - max(gt[0], pr[0]) + 1\n    \n    if dx < 0:\n        return 0.0\n    \n    dy = min(gt[3], pr[3]) - max(gt[1], pr[1]) + 1\n\n    if dy < 0:\n        return 0.0\n\n    overlap_area = dx * dy\n\n    # Calculate union area\n    union_area = (\n            (gt[2] - gt[0] + 1) * (gt[3] - gt[1] + 1) +\n            (pr[2] - pr[0] + 1) * (pr[3] - pr[1] + 1) -\n            overlap_area\n    )\n\n    return overlap_area / union_area","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\ndef find_best_match(gts, pred, pred_idx, threshold = 0.5, form = 'pascal_voc', ious=None) -> int:\n    best_match_iou = -np.inf\n    best_match_idx = -1\n\n    for gt_idx in range(len(gts)):\n        \n        if gts[gt_idx][0] < 0:\n            # Already matched GT-box\n            continue\n        \n        iou = -1 if ious is None else ious[gt_idx][pred_idx]\n\n        if iou < 0:\n            iou = calculate_iou(gts[gt_idx], pred, form=form)\n            \n            if ious is not None:\n                ious[gt_idx][pred_idx] = iou\n\n        if iou < threshold:\n            continue\n\n        if iou > best_match_iou:\n            best_match_iou = iou\n            best_match_idx = gt_idx\n\n    return best_match_idx\n\ndef calculate_precision(gts, preds, threshold = 0.5, form = 'coco', ious=None) -> float:\n\n    n = len(preds)\n    tp = 0\n    fp = 0\n    \n    # for pred_idx, pred in enumerate(preds_sorted):\n    for pred_idx in range(n):\n\n        best_match_gt_idx = find_best_match(gts, preds[pred_idx], pred_idx,\n                                            threshold=threshold, form=form, ious=ious)\n\n        if best_match_gt_idx >= 0:\n            # True positive: The predicted box matches a gt box with an IoU above the threshold.\n            tp += 1\n            # Remove the matched GT box\n            gts[best_match_gt_idx] = -1\n\n        else:\n            # No match\n            # False positive: indicates a predicted box had no associated gt box.\n            fp += 1\n\n    # False negative: indicates a gt box had no associated predicted box.\n    fn = (gts.sum(axis=1) > 0).sum()\n\n    return tp / (tp + fp + fn)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\ndef calculate_image_precision(gts, preds, thresholds = (0.5, ), form = 'coco') -> float:\n\n    n_threshold = len(thresholds)\n    image_precision = 0.0\n    \n    ious = np.ones((len(gts), len(preds))) * -1\n    # ious = None\n\n    for threshold in thresholds:\n        precision_at_threshold = calculate_precision(gts.copy(), preds, threshold=threshold,\n                                                     form=form, ious=ious)\n        image_precision += precision_at_threshold / n_threshold\n\n    return image_precision","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def val(epoch_number,model,train_losses):\n    train_losses.reset()\n    tqdm_loader=tqdm(val_loader)\n    model.eval()\n    iou_thresholds = [x for x in np.arange(0.5, 0.76, 0.05)]\n    validation_image_precisions = []\n    \n    with torch.no_grad():\n    \n        for step, (images, targets) in enumerate(tqdm_loader):\n            \n            images = list(image.to(device) for image in images)\n            targets = [{k: v.to(device) for k, v in t.items()} for t in targets]\n\n            outputs = model(images)\n\n            for i, image in enumerate(images):\n                boxes = outputs[i]['boxes'].data.cpu().numpy()\n                scores = outputs[i]['scores'].data.cpu().numpy()\n                gt_boxes = targets[i]['boxes'].cpu().numpy()\n                preds_sorted_idx = np.argsort(scores)[::-1]\n                preds_sorted = boxes[preds_sorted_idx]\n                image_precision = calculate_image_precision(preds_sorted, gt_boxes, thresholds=iou_thresholds,form='pascal_voc')\n                validation_image_precisions.append(image_precision)\n                train_losses.update(image_precision,n=1)\n            tqdm_loader.set_description(\"Val Epoch {}  avg={:4} \".format(epoch_number,round(np.mean(validation_image_precisions),4)))\n\n    valid_prec = np.mean(validation_image_precisions)\n  \n    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import torchvision\nfrom torchvision.models.detection.faster_rcnn import FastRCNNPredictor\n# load a model pre-trained pre-trained on COCO\nmodel1 = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True)\n\n\nnum_classes = 2  # 1 class (person) + background\n# get number of input features for the classifier\nin_features = model1.roi_heads.box_predictor.cls_score.in_features\n# replace the pre-trained head with a new one\nmodel1.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes)\n\ndevice = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\nmodel1=model1.to(device)\nadam=torch.optim.Adam(model1.parameters(),lr=0.0001)\ntrain_losses = AverageMeter()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for i in range(3):\n    val(i,model1,train_losses)\n    train(i,model1,adam,train_losses)\n    \n  ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#val example\nindex_img=0\n#torch.reshape(img,(3,1024,1024)) val_loader train_loader\nimages, targets = next(iter(val_loader))\nimages = list(img.to(device) for img in images)\ntargets = [{k: v.to(device) for k, v in t.items()} for t in targets]\nboxes = targets[index_img]['boxes'].cpu().numpy().astype(np.float32)\nsample2 = images[index_img].permute(1,2,0).cpu().numpy()\n#pred val\nmodel1.eval()\ncpu_device = torch.device(\"cpu\")\noutputs = model1(images)\noutputs=outputs[index_img]\noutputs = [{k: v.to(cpu_device) for k, v in outputs.items()} ]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#get box&score to plot \nbox1=outputs[0]['boxes'].cpu().detach().numpy()\nscores=outputs[0]['scores'].cpu().detach().numpy()\nimage1=images[index_img].cpu().numpy()\nprint(len(boxes),\" \",len(box1),\"  \",scores)\nprint(\"boxes : \", sum(scores >0.4))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"image1=np.reshape(image1,(1024,1024,3))\nplt.subplot(1,2,1)\nplt.imshow(image1)\nplt.subplot(1,2,2)\nplt.imshow(sample2)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"collapsed":true},"cell_type":"code","source":"image1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for i in range(len(boxes)):\n  cv2.rectangle(sample2,(int(boxes[i][0]),int(boxes[i][1])),(int(boxes[i][2]),int(boxes[i][3])),\n                (0,255,0),2)\n\ndef get_box(box11):\n  box_sample=[int(box11[0]),int(box11[1]),int(box11[2]),int(box11[3])]\n  box_sample[2]=box_sample[2]-box_sample[0]\n  box_sample[3]=box_sample[3]-box_sample[1]\n  return box_sample\n\n\n\naug=[]\ntransform=A.Compose(aug, bbox_params=A.BboxParams(format='coco', min_area=0, \n                                               min_visibility=0, label_fields=['labels']),p=1)\nlist_box=[]\nfor i in range(len(box1)):\n  if scores[i] >0.5:\n    list_box.append(get_box(box1[i]))\n\nsample={'image': sample2,'bboxes': list_box,'labels': [1]*len(list_box)}\ncategory_id_to_name = {0: '0',1:'100%'}\nannotation=transform(**sample)\nplt.figure(figsize=[12,12])\nvisualize(annotation,category_id_to_name,sample2)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\nclass WheatDatasetTest(Dataset):\n\n  def __init__(self, path,df, transforms=None):\n    self.path=path\n    self.df=df\n    self.transforms=transforms\n\n  def __len__(self):\n    return len(self.path)\n\n  def __getitem__(self, idx):\n    p=self.path[idx]\n    \n    image1=cv2.imread('../input/global-wheat-detection/test/'+p,cv2.IMREAD_COLOR)\n    image1=cv2.cvtColor(image1,cv2.COLOR_BGR2RGB).astype(np.float32)\n    image1 /= 255.0\n    \n\n\n    target={}\n    labels = torch.ones((len(boxes),), dtype=torch.int64)\n    iscrowd = torch.zeros((len(boxes),), dtype=torch.int64)\n    \n    if self.transforms:\n      sample = {\n        'image': image1,\n        'labels':labels\n      }\n      sample=self.transforms(**sample)\n      image1 = sample['image']\n      labels = sample['labels']\n\n\n    target[\"iscrowd\"]=torch.as_tensor(iscrowd,dtype=torch.int64 )\n    target['labels'] =  torch.as_tensor(labels,dtype=torch.int64 )\n\n    image1=torch.as_tensor(image1,dtype=torch.float32)\n    \n    return image1,target,p","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_df=pd.read_csv(\"../input/global-wheat-detection/sample_submission.csv\")\nlist_path=glob.glob(\"../input/global-wheat-detection/test/*\")\nvalid_ids=[]\nfor path in list_path:\n    valid_ids.append(path.split('/')[-1])\n    \ntest_dataset = WheatDatasetTest(valid_ids,test_df,transforms=transformValid)\n\ntest_data_loader = DataLoader(\n    test_dataset,\n    batch_size=4,\n    shuffle=False\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"valid_ids","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def format_prediction_string(boxes, scores):\n    pred_strings = []\n    for j in zip(scores, boxes):\n        pred_strings.append(\"{0:.4f} {1} {2} {3} {4}\".format(j[0], j[1][0], j[1][1], j[1][2], j[1][3]))\n\n    return \" \".join(pred_strings)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"detection_threshold = 0.5\nresults = []\n\nfor images, target,image_ids in test_data_loader:\n\n    images = list(image.to(device) for image in images)\n    outputs = model1(images)\n\n    for i, image in enumerate(images):\n\n        boxes = outputs[i]['boxes'].data.cpu().numpy()\n        scores = outputs[i]['scores'].data.cpu().numpy()\n        \n        boxes = boxes[scores >= detection_threshold].astype(np.int32)\n        scores = scores[scores >= detection_threshold]\n        image_id = image_ids[i]\n        \n        boxes[:, 2] = boxes[:, 2] - boxes[:, 0]\n        boxes[:, 3] = boxes[:, 3] - boxes[:, 1]\n        print(image_ids)\n        \n        result = {\n            'image_id': image_id,\n            'PredictionString': format_prediction_string(boxes, scores)\n        }\n\n        \n        results.append(result)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_df = pd.DataFrame(results, columns=['image_id', 'PredictionString'])\ntest_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_df.to_csv('submission.csv', index=False)","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}