{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import tensorflow as tf\nimport keras\nfrom keras.layers import Input , Conv2D , MaxPool2D , BatchNormalization , LeakyReLU , GlobalAveragePooling2D  , UpSampling2D\nfrom keras.layers import Dense , Flatten , add , Concatenate\nfrom keras.models import Model\nfrom tensorflow.keras.optimizers import Adam\nimport numpy as np\n\ndef focal_loss(true, pred, shape, eps=10e-10, alpha=0.75, gama=2.0):\n    b, h, w, c = shape\n    fl = - tf.math.log(tf.clip_by_value(pred, eps, 1.)) * true * alpha * tf.pow(1 - pred, gama)             - tf.math.log(tf.clip_by_value(1 - pred, eps, 1.)) * (1 - true) * (1 - alpha) * tf.pow(pred, gama)\n    fl = tf.reshape(fl, (b, h * w * c))\n    fl = tf.reduce_sum(fl, axis=-1)\n    return fl\n\ndef l2(true, pred, shape):\n    b, h, w, c = shape\n    verts = tf.reshape(tf.square(true-pred), (b, h*w*c))\n    verts = tf.reduce_sum(verts, 1)\n    return verts\n\ndef focal_multi_class_entropy_loss(true, pred, shape, eps=10e-10, alpha=0.75, gama=2.0):\n    b, h, w, c = shape\n    cl = tf.clip_by_value(pred, eps, 1.)\n    cl = -tf.math.log(cl) * true * tf.pow(1 - cl, gama) * alpha\n    cl = tf.reshape(cl, (b, h * w * c))\n    cl = tf.reduce_sum(cl, axis=1)\n    return cl\n\ndef total_loss(Y_true, Y_pred):\n    \n    shape = tf.shape(Y_true)\n    b , h , w = shape[0] , shape[1] , shape[2]\n    y_true_loc = tf.reshape(Y_true[..., 0], (b, h, w, 1))\n    y_pred_loc = tf.reshape(Y_pred[..., 0], (b, h, w, 1))\n    y_true_vertex = Y_true[..., 1:5]\n    y_pred_vertex = Y_pred[..., 1:5]\n    #y_true_class = Y_true[..., 5:]\n    #y_pred_class = Y_pred[..., 5:]\n    region_lp = tf.reshape(y_true_loc, (b, h, w, 1))\n    \n    loc_loss = focal_loss(y_true_loc, y_pred_loc, (b, h, w, 1)) * 1.0\n    vertex_loss = l2(y_true_vertex * region_lp, y_pred_vertex * region_lp, (b, h, w, 4)) * 1.0\n    #class_loss = focal_multi_class_entropy_loss(y_true_class, y_pred_class, (b, h, w, 2)) * 1.0\n    \n    return loc_loss + vertex_loss #+ class_loss\n\ndef bn_and_activation_layer(x):\n    x = BatchNormalization()(x)\n    x = LeakyReLU()(x)\n    return x\n\ndef res_block(x , out_ch ):\n    if list(x.shape)[-1] == out_ch:\n        res = x\n    else :\n        res = Conv2D(out_ch , kernel_size=(1,1) , padding = 'same')(x)\n        res = bn_and_activation_layer(res)\n    x = Conv2D(int(out_ch / 2) , kernel_size=(1,1) , padding = 'same')(x)\n    x = bn_and_activation_layer(x)\n    x = Conv2D(int(out_ch / 2) , kernel_size=(3,3) , padding = 'same')(x)\n    x = bn_and_activation_layer(x)\n    x = Conv2D(out_ch , kernel_size=(1,1) , padding = 'same')(x)\n    x = BatchNormalization()(x)\n    x = add([res , x])\n    x = LeakyReLU()(x)\n    return x\n\ndef hourglass(x):\n    ch = list(x.shape)[-1]\n    \n    d1 = res_block(x , ch)\n    y = MaxPool2D(pool_size=(2, 2), strides=(2, 2))(d1)\n    d2 = res_block(y , ch)\n    y = MaxPool2D(pool_size=(2, 2), strides=(2, 2))(d2)\n    d3 = res_block(y , ch)\n    y = MaxPool2D(pool_size=(2, 2), strides=(2, 2))(d3)\n    d4 = res_block(y , ch)\n    \n    u4 = res_block(d4 , ch)\n    u4 = res_block(u4 , ch)\n    u4 = res_block(u4 , ch)\n    d4 = res_block(d4 , ch)\n    u4 = add([u4 , d4])\n    u3 = UpSampling2D()(u4)\n    d3 = res_block(d3 , ch)\n    u3 = add([u3 , d3])\n    u3 = res_block(u3 , ch)\n    u2 = UpSampling2D()(u3)\n    d2 = res_block(d2 , ch)\n    u2 = add([u2 , d2])\n    u2 = res_block(u2 , ch)\n    u1 = UpSampling2D()(u2)\n    d1 = res_block(d1 , ch)\n    u1 = add([u1 , d1])\n    u1 = res_block(u1 , ch)\n    \n    y = Conv2D(ch , kernel_size=(1,1) , padding = 'same')(u1)\n    y = bn_and_activation_layer(y)\n    \n    return x , y\n\ndef join_hourglass(x , y ):\n    ch = list(x.shape)[-1]\n    y1 = Conv2D(ch , kernel_size=(1,1) , activation='linear' , padding = 'same')(y)\n    y2 = Conv2D(ch , kernel_size=(1,1) , activation='linear' , padding = 'same')(y)\n    y2 = Conv2D(ch , kernel_size=(1,1) , activation='linear' , padding = 'same')(y2)\n    x = add([y1 , y2 ,x])\n    return x\n\ndef create_heads(out):\n    head_loc = Conv2D(1, kernel_size=(3, 3), activation='sigmoid', padding='same')(out)\n    head_vertex = Conv2D(4, kernel_size=(3, 3), activation='linear', padding='same')(out)\n    #head_class = Conv2D(2, kernel_size=(3, 3), activation='softmax', padding='same')(out)\n    out = Concatenate(3)([head_loc, head_vertex])#, head_class])\n    return out\n\ndef model(out_channels = 256 , no_of_hgs = 2 , inp = Input((None,None,3))):\n    x = Conv2D(64 , kernel_size=(7,7) , strides=(2,2)  , padding = 'same')(inp)\n    x = bn_and_activation_layer(x)\n    x = res_block(x , out_channels//2 )\n    x = MaxPool2D(pool_size=(2, 2), strides=(2, 2))(x)\n    x = res_block(x , out_channels//2 )\n    x = res_block(x , out_channels )\n    out = None\n    for i in range(no_of_hgs):\n        x , out = hourglass(x)\n        if i<no_of_hgs-1:\n            x = join_hourglass(x , out)\n    out = create_heads(out)\n    model = Model(inp , out)\n    loss = total_loss\n    #lr = 0.000001\n    #lr_schedule = tf.keras.optimizers.schedules.ExponentialDecay(lr , decay_steps=20000 , decay_rate = 0.96 , staircase = True)\n    #opt = Adam(lr_schedule)\n    model.compile(loss=loss, optimizer='adam')#opt)\n    #model.summary()\n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def iou(box1, box2):\n    \n    (box1_x1, box1_y1, box1_x2, box1_y2) = box1\n    (box2_x1, box2_y1, box2_x2, box2_y2) = box2\n        \n    xi1 = max(box1_x1,box2_x1)\n    yi1 = max(box1_y1,box2_y1)\n    xi2 = min(box1_x2,box2_x2)\n    yi2 = min(box1_y2,box2_y2)\n    inter_width = xi2-xi1\n    inter_height = yi2-yi1\n    inter_area = max(inter_height, 0)*max(inter_width, 0)\n    \n    box1_area = (box1_y2 - box1_y1)*(box1_x2 - box1_x1) \n    box2_area = (box2_y2 - box2_y1)*(box2_x2 - box2_x1)\n    union_area = box1_area + box2_area - inter_area\n\n    iou = inter_area / union_area\n\n    return iou\n\ndef nms(detections, thresh=.5):\n\n    if len(detections) == 0:\n        return []\n    \n    detections = sorted(detections, key=lambda detections: detections[4],\n            reverse=True)\n    \n    new_detections=[]\n    new_detections.append(detections[0])\n    del detections[0]\n    for index, detection in enumerate(detections):\n        for new_detection in new_detections:\n            if iou(detection[:4], new_detection[:4]) > thresh:\n                del detections[index]\n                break\n        else:\n            new_detections.append(detection)\n            del detections[index]\n    return new_detections","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"inp = Input((256 , 256 , 3))\nlp = model(256 , 3 , inp)\nlp.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"lp.load_weights('../input/weights-file/lp300000.h5')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import os\nimport cv2\npaths = os.listdir('../input/global-wheat-detection/test/')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def test(img):\n    pred = lp.predict(np.expand_dims(img , 0))[0]\n    def scale_points(box , scale1 , scale2):\n            pts = [int(int(box[0])/scale2*scale1) , int(int(box[1])/scale2*scale1) , int(int(box[2])/scale2*scale1) , int(int(box[3])/scale2*scale1)]\n            return np.array(pts)\n    objs=[]\n    for y in range(pred.shape[0]):\n        for x in range(pred.shape[1]):\n            prob = pred[y,x,0]\n            if prob>.1:\n                pts = pred[y,x,1:5]\n                pts = scale_points(pts, 256 , 64)\n                for i in range(4):\n                    pts[i] = np.clip(pts[i], 0, 256)\n                objs.append(np.array([pts[0] , pts[1] , pts[2] , pts[3] ,prob]))          \n    objs = np.array(objs)\n    if len(objs)>0:\n        aft_nms = np.array(nms(objs,0.0))\n        return aft_nms","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"results=[]\nfor path in paths:\n    img = cv2.imread('../input/global-wheat-detection/test/'+path)\n    img = cv2.resize(img , (256,256))\n    box_scores = test(img/255.0)\n    ind = np.argsort(-box_scores[:,4])\n    box_scores = box_scores[ind]\n    sub=[]\n    for box in box_scores:\n        sub.append(f'{box[4]:.2f} {int(box[0])*4} {int(box[1])*4} {int(box[2] - box[0])*4} {int(box[3] - box[1])*4}')\n    sub = \" \".join(sub)\n    result={'image_id':path[:-4] , 'PredictionString': sub}\n    results.append(result)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import pandas as pd\ntest_df = pd.DataFrame(results, columns=['image_id', 'PredictionString'])\ntest_df.head()\ntest_df.to_csv('submission.csv', index=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"results","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}