Kaggle competition: Global Wheat Detection
<SOS> metric: custom metric Kaggle data source: global-wheat-detection<save_to_csv>
!pip install --no-deps '.. /input/timm-package/timm-0.1.26-py3-none-any.whl' > /dev/null
!pip install --no-deps '.. /input/pycocotools/pycocotools-2.0-cp37-cp37m-linux_x86_64.whl' > /dev/null
submission = pd.DataFrame({"row_id": row_ids, "meter_reading": np.clip(predict, 0, a_max=None)})
 submission.to_csv("submission.csv", index=False)
<install_modules>
def get_valid_transforms() :
return A.Compose([
A.Resize(height=512, width=512, p=1.0),
ToTensorV2(p=1.0),
], p=1.0 )
!pip install -U segmentation-models==0.2.1
!pip install albumentations<import_modules>
DATA_ROOT_PATH = '.. /input/global-wheat-detection/test'
class DatasetRetriever(Dataset):
def __init__(self, image_ids, transforms=None):
super().__init__()
self.image_ids = image_ids
self.transforms = transforms
def __getitem__(self, index: int):
image_id = self.image_ids[index]
image = cv2.imread(f'{DATA_ROOT_PATH}/{image_id}.jpg', cv2.IMREAD_COLOR)
 image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB ).astype(np.float32)
 image /= 255.0
if self.transforms:
sample = {'image': image}
sample = self.transforms(**sample)
 image = sample['image']
return image, image_id
def __len__(self)-> int:
return self.image_ids.shape[0]
import os, sys, gc
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from tqdm.auto import tqdm
from multiprocessing import Pool, cpu_count
from cv2 import resize
from skimage.io import imread as skiImgRead
from skimage.morphology import label
from sklearn.model_selection import train_test_split
from segmentation_models import Unet
from segmentation_models.backbones import get_preprocessing
from segmentation_models.utils import set_trainable
from segmentation_models.losses import bce_jaccard_loss, bce_dice_loss
from segmentation_models.metrics import iou_score, f2_score
from keras.callbacks import ReduceLROnPlateau, ModelCheckpoint, EarlyStopping, LearningRateScheduler<define_variables>
dataset = DatasetRetriever(
 image_ids=np.array([path.split('/')[-1][:-4] for path in glob(f'{DATA_ROOT_PATH}/*.jpg')]),
transforms=get_valid_transforms() 
)
 def collate_fn(batch):
return tuple(zip(*batch))
data_loader = DataLoader(
 dataset,
batch_size=4,
shuffle=False,
num_workers=2,
drop_last=False,
collate_fn=collate_fn
)
IMG_HW = 768
ZOOM_HW = 384
DATA_DIR = '.. /input/airbus-ship-detection'
TRAIN_DIR = os.path.join(DATA_DIR, 'train_v2')
 TEST_DIR = os.path.join(DATA_DIR, 'test_v2')
 BACKBONE = 'resnet34'
preprocess_input = get_preprocessing(BACKBONE )<categorify>
def load_net(checkpoint_path):
config = get_efficientdet_config('tf_efficientdet_d5')
 net = EfficientDet(config, pretrained_backbone=False)
 config.num_classes = 1
config.image_size=512
net.class_net = HeadNet(config, num_outputs=config.num_classes, norm_kwargs=dict(eps=.001, momentum=.01))
checkpoint = torch.load(checkpoint_path)
 net.load_state_dict(checkpoint['model_state_dict'])
 del checkpoint
gc.collect()
net = DetBenchEval(net, config)
 net.eval() ;
return net.cuda()
net = load_net('.. /input/wheat-effdet5-fold0-best-checkpoint/fold0-best-all-states.bin' )
def rle_decode(rle_mask):

 s = rle_mask.split()
starts, lengths = [np.asarray(x, dtype=int)for x in(s[0:][::2], s[1:][::2])]
starts -= 1
ends = starts + lengths
img = np.zeros(IMG_HW*IMG_HW, dtype=np.uint8)
 for lo, hi in zip(starts, ends):
img[lo:hi] = 1
return img.reshape(IMG_HW,IMG_HW ).T
def rle_encode(im):

 pixels = im.flatten(order = 'F')
 pixels = np.concatenate([[0], pixels, [0]])
 runs = np.where(pixels[1:] != pixels[:-1])[0] + 1
runs[1::2] -= runs[::2]
return ' '.join(str(x)for x in runs )<load_from_csv>
class BaseWheatTTA:

 image_size = 512
def augment(self, image):
raise NotImplementedError
def batch_augment(self, images):
raise NotImplementedError
def deaugment_boxes(self, boxes):
raise NotImplementedError
class TTAHorizontalFlip(BaseWheatTTA):

 def augment(self, image):
return image.flip(1)
 def batch_augment(self, images):
return images.flip(2)
 def deaugment_boxes(self, boxes):
boxes[:, [1,3]] = self.image_size - boxes[:, [3,1]]
return boxes
class TTAVerticalFlip(BaseWheatTTA):

 def augment(self, image):
return image.flip(2)
 def batch_augment(self, images):
return images.flip(3)
 def deaugment_boxes(self, boxes):
boxes[:, [0,2]] = self.image_size - boxes[:, [2,0]]
return boxes
class TTARotate90(BaseWheatTTA):

 def augment(self, image):
return torch.rot90(image, 1,(1, 2))
def batch_augment(self, images):
return torch.rot90(images, 1,(2, 3))
def deaugment_boxes(self, boxes):
res_boxes = boxes.copy()
res_boxes[:, [0,2]] = self.image_size - boxes[:, [1,3]]
res_boxes[:, [1,3]] = boxes[:, [2,0]]
return res_boxes
class TTACompose(BaseWheatTTA):

 def __init__(self, transforms):
self.transforms = transforms
def augment(self, image):
for transform in self.transforms:
image = transform.augment(image)
 return image
def batch_augment(self, images):
for transform in self.transforms:
images = transform.batch_augment(images)
 return images
def prepare_boxes(self, boxes):
result_boxes = boxes.copy()
result_boxes[:,0] = np.min(boxes[:, [0,2]], axis=1)
 result_boxes[:,2] = np.max(boxes[:, [0,2]], axis=1)
 result_boxes[:,1] = np.min(boxes[:, [1,3]], axis=1)
 result_boxes[:,3] = np.max(boxes[:, [1,3]], axis=1)
 return result_boxes
def deaugment_boxes(self, boxes):
for transform in self.transforms[::-1]:
boxes = transform.deaugment_boxes(boxes)
 return self.prepare_boxes(boxes )
train_csv = pd.read_csv(os.path.join(DATA_DIR, 'train_ship_segmentations_v2.csv'))
train_csv['withShip'] = ~train_csv['EncodedPixels'].isnull()
train_csv['npixel'] = count_pix_inpool(train_csv['EncodedPixels'] )<split>
def process_det(index, det, score_threshold=0.25):
boxes = det[index].detach().cpu().numpy() [:,:4]
scores = det[index].detach().cpu().numpy() [:,4]
boxes[:, 2] = boxes[:, 2] + boxes[:, 0]
boxes[:, 3] = boxes[:, 3] + boxes[:, 1]
boxes =(boxes ).clip(min=0, max=511 ).astype(int)
 indexes = np.where(scores>score_threshold)
 boxes = boxes[indexes]
scores = scores[indexes]
return boxes, scores
b_train_csv, b_valid_csv = train_test_split(balanced_train_csv['ImageId'], test_size = 0.2)
 b_train_csv = balanced_train_csv.set_index('ImageId' ).loc[b_train_csv].reset_index()
b_valid_csv = balanced_train_csv.set_index('ImageId' ).loc[b_valid_csv].reset_index()<prepare_x_and_y>
tta_transforms = []
for tta_combination in product([TTAHorizontalFlip() , None],
[TTAVerticalFlip() , None],
[TTARotate90() , None]):
tta_transforms.append(TTACompose([tta_transform for tta_transform in tta_combination if tta_transform]))
def batch_data_gen(csv_df, dir_prefix, batch_size, augmentation=None):
name_idx_df = csv_df.set_index('ImageId')
 img_ids = np.array(name_idx_df.index.unique().tolist())
 n_imgs = img_ids.shape[0]
while True:
np.random.shuffle(img_ids)
 for idx in range(0, n_imgs, batch_size):
batch_x = np.zeros(( batch_size,)+(ZOOM_HW, ZOOM_HW, 3))
batch_y = np.zeros(( batch_size,)+(ZOOM_HW, ZOOM_HW, 1))
end_idx = idx + batch_size
batch_img_ids = img_ids[idx:end_idx]
for i,img_id in enumerate(batch_img_ids):
img_df = name_idx_df.loc[[img_id]]
x, y = load_paired_data(img_df, dir_prefix, augmentation=augmentation)
 batch_x[i] += x
batch_y[i] += y
yield batch_x, batch_y
def load_paired_data(df, dir_prefix, augmentation=None):
img_id = df.index.unique() [0]
try:
image = preprocess_input(skiImgRead(os.path.join(dir_prefix, img_id)))
 except:
image = preprocess_input(np.zeros(( IMG_HW, IMG_HW, 3), dtype=np.uint8))
mask = np.zeros(( IMG_HW, IMG_HW, 1))
for _,mask_rle in df['EncodedPixels'].iteritems() :
if mask_rle is np.nan:
continue
mask[:,:,0] += rle_decode(mask_rle)
 if augmentation:
augmented = augmentation(image=image, mask=mask)
 image = augmented['image']
mask = augmented['mask']
image = resize(image,(ZOOM_HW,ZOOM_HW))
mask = resize(mask.reshape(IMG_HW,IMG_HW),(ZOOM_HW,ZOOM_HW)).reshape(( ZOOM_HW,ZOOM_HW,1))
return image, mask<set_options>
def make_tta_predictions(images, score_threshold=0.25):
with torch.no_grad() :
images = torch.stack(images ).float().cuda()
predictions = []
for tta_transform in tta_transforms:
result = []
det = net(tta_transform.batch_augment(images.clone()), torch.tensor([1]*images.shape[0] ).float().cuda())
 for i in range(images.shape[0]):
boxes = det[i].detach().cpu().numpy() [:,:4]
scores = det[i].detach().cpu().numpy() [:,4]
indexes = np.where(scores > score_threshold)[0]
boxes = boxes[indexes]
boxes[:, 2] = boxes[:, 2] + boxes[:, 0]
boxes[:, 3] = boxes[:, 3] + boxes[:, 1]
boxes = tta_transform.deaugment_boxes(boxes.copy())
 result.append({
'boxes': boxes,
'scores': scores[indexes],
})
 predictions.append(result)
 return predictions
def run_wbf(predictions, image_index, image_size=512, iou_thr=0.44, skip_box_thr=0.43, weights=None):
boxes = [(prediction[image_index]['boxes']/(image_size-1)).tolist() for prediction in predictions]
scores = [prediction[image_index]['scores'].tolist() for prediction in predictions]
labels = [np.ones(prediction[image_index]['scores'].shape[0] ).astype(int ).tolist() for prediction in predictions]
boxes, scores, labels = ensemble_boxes.ensemble_boxes_wbf.weighted_boxes_fusion(boxes, scores, labels, weights=None, iou_thr=iou_thr, skip_box_thr=skip_box_thr)
 boxes = boxes*(image_size-1)
 return boxes, scores, labels
Compose, HorizontalFlip, VerticalFlip, RandomRotate90, ShiftScaleRotate, Transpose,
OneOf, ToFloat,
RandomBrightness, RandomContrast, RandomGamma, CLAHE,
GridDistortion, ElasticTransform, JpegCompression,
RGBShift, GaussNoise, IAAAdditiveGaussianNoise, HueSaturationValue,
Blur, MotionBlur, MedianBlur, RandomBrightnessContrast,
GridDistortion, OpticalDistortion, RandomSizedCrop, CenterCrop 
)
 augmentor = Compose([
OneOf([
HorizontalFlip() ,
VerticalFlip() ,
RandomRotate90() ,
Transpose() ,
], p=0.8),
ShiftScaleRotate(rotate_limit=20),
OneOf([
MotionBlur(blur_limit=3),
MedianBlur(blur_limit=3),
Blur(blur_limit=3),
], p=0.3),
OneOf([
RandomGamma() ,
RandomContrast() ,
RandomBrightness() ,
CLAHE() ,
], p=0.3),
OneOf([
IAAAdditiveGaussianNoise() ,
HueSaturationValue() ,
GaussNoise() ,
], p=0.2),
OneOf([
ElasticTransform() ,
OpticalDistortion() ,
GridDistortion() ,
], p=0.3),
RandomSizedCrop(min_max_height=(IMG_HW/2, IMG_HW), height=IMG_HW, width=IMG_HW, p=0.3),
ToFloat(max_value=1),
],p=1 )<choose_model_class>
def format_prediction_string(boxes, scores):
pred_strings = []
for j in zip(scores, boxes):
pred_strings.append("{0:.4f} {1} {2} {3} {4}".format(j[0], j[1][0], j[1][1], j[1][2], j[1][3]))
return " ".join(pred_strings )
model = Unet(
 BACKBONE,
encoder_weights='imagenet',
classes=1,
activation='sigmoid',
input_shape=(ZOOM_HW, ZOOM_HW, 3),
decoder_filters=(128, 64, 32, 16, 8), 
)
 model.compile(optimizer='Adam', loss=bce_dice_loss, metrics=[iou_score])
<define_variables>
results = []
for images, image_ids in data_loader:
predictions = make_tta_predictions(images)
 for i, image in enumerate(images):
boxes, scores, labels = run_wbf(predictions, image_index=i)
 boxes =(boxes*2 ).round().astype(np.int32 ).clip(min=0, max=1023)
 image_id = image_ids[i]
boxes[:, 2] = boxes[:, 2] - boxes[:, 0]
boxes[:, 3] = boxes[:, 3] - boxes[:, 1]
result = {
'image_id': image_id,
'PredictionString': format_prediction_string(boxes, scores)
 }
results.append(result )
<choose_model_class><EOS> 
test_df = pd.DataFrame(results, columns=['image_id', 'PredictionString'])
 test_df.to_csv('submission.csv', index=False)
 test_df.head()