{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import numpy as np\nimport os\nimport xml.etree.ElementTree as ET\nimport tensorflow as tf\nimport copy\nimport cv2\n\nclass BoundBox:\n    def __init__(self, xmin, ymin, xmax, ymax, c = None, classes = None):\n        self.xmin = xmin\n        self.ymin = ymin\n        self.xmax = xmax\n        self.ymax = ymax\n        \n        self.c     = c\n        self.classes = classes\n\n        self.label = -1\n        self.score = -1\n\n    def get_label(self):\n        if self.label == -1:\n            self.label = np.argmax(self.classes)\n        \n        return self.label\n    \n    def get_score(self):\n        if self.score == -1:\n            self.score = self.classes[self.get_label()]\n            \n        return self.score\n\nclass WeightReader:\n    def __init__(self, weight_file):\n        self.offset = 4\n        self.all_weights = np.fromfile(weight_file, dtype='float32')\n        \n    def read_bytes(self, size):\n        self.offset = self.offset + size\n        return self.all_weights[self.offset-size:self.offset]\n    \n    def reset(self):\n        self.offset = 4\n\ndef bbox_iou(box1, box2):\n    intersect_w = _interval_overlap([box1.xmin, box1.xmax], [box2.xmin, box2.xmax])\n    intersect_h = _interval_overlap([box1.ymin, box1.ymax], [box2.ymin, box2.ymax])  \n    \n    intersect = intersect_w * intersect_h\n\n    w1, h1 = box1.xmax-box1.xmin, box1.ymax-box1.ymin\n    w2, h2 = box2.xmax-box2.xmin, box2.ymax-box2.ymin\n    \n    union = w1*h1 + w2*h2 - intersect\n    \n    return float(intersect) / union\n\ndef draw_boxes(image, boxes, labels):\n    image_h, image_w, _ = image.shape\n\n    for box in boxes:\n        xmin = int(box.xmin*image_w)\n        ymin = int(box.ymin*image_h)\n        xmax = int(box.xmax*image_w)\n        ymax = int(box.ymax*image_h)\n\n        cv2.rectangle(image, (xmin,ymin), (xmax,ymax), (0,255,0), 3)\n        cv2.putText(image, \n                    labels[box.get_label()] + ' ' + str(box.get_score()), \n                    (xmin, ymin - 13), \n                    cv2.FONT_HERSHEY_SIMPLEX, \n                    1e-3 * image_h, \n                    (0,255,0), 2)\n        \n    return image          \n        \ndef decode_netout(netout, anchors, nb_class, obj_threshold=0.3, nms_threshold=0.3):\n    grid_h, grid_w, nb_box = netout.shape[:3]\n\n    boxes = []\n    \n    # decode the output by the network\n    netout[..., 4]  = _sigmoid(netout[..., 4])\n    netout[..., 5:] = netout[..., 4][..., np.newaxis] * _softmax(netout[..., 5:])\n    netout[..., 5:] *= netout[..., 5:] > obj_threshold\n    \n    for row in range(grid_h):\n        for col in range(grid_w):\n            for b in range(nb_box):\n                # from 4th element onwards are confidence and class classes\n                classes = netout[row,col,b,5:]\n                \n                if np.sum(classes) > 0:\n                    # first 4 elements are x, y, w, and h\n                    x, y, w, h = netout[row,col,b,:4]\n\n                    x = (col + _sigmoid(x)) / grid_w # center position, unit: image width\n                    y = (row + _sigmoid(y)) / grid_h # center position, unit: image height\n                    w = anchors[2 * b + 0] * np.exp(w) / grid_w # unit: image width\n                    h = anchors[2 * b + 1] * np.exp(h) / grid_h # unit: image height\n                    confidence = netout[row,col,b,4]\n                    \n                    box = BoundBox(x-w/2, y-h/2, x+w/2, y+h/2, confidence, classes)\n                    \n                    boxes.append(box)\n\n    # suppress non-maximal boxes\n    for c in range(nb_class):\n        sorted_indices = list(reversed(np.argsort([box.classes[c] for box in boxes])))\n\n        for i in range(len(sorted_indices)):\n            index_i = sorted_indices[i]\n            \n            if boxes[index_i].classes[c] == 0: \n                continue\n            else:\n                for j in range(i+1, len(sorted_indices)):\n                    index_j = sorted_indices[j]\n                    \n                    if bbox_iou(boxes[index_i], boxes[index_j]) >= nms_threshold:\n                        boxes[index_j].classes[c] = 0\n                        \n    # remove the boxes which are less likely than a obj_threshold\n    boxes = [box for box in boxes if box.get_score() > obj_threshold]\n    \n    return boxes    \n\ndef compute_overlap(a, b):\n    \"\"\"\n    Code originally from https://github.com/rbgirshick/py-faster-rcnn.\n    Parameters\n    ----------\n    a: (N, 4) ndarray of float\n    b: (K, 4) ndarray of float\n    Returns\n    -------\n    overlaps: (N, K) ndarray of overlap between boxes and query_boxes\n    \"\"\"\n    area = (b[:, 2] - b[:, 0]) * (b[:, 3] - b[:, 1])\n\n    iw = np.minimum(np.expand_dims(a[:, 2], axis=1), b[:, 2]) - np.maximum(np.expand_dims(a[:, 0], 1), b[:, 0])\n    ih = np.minimum(np.expand_dims(a[:, 3], axis=1), b[:, 3]) - np.maximum(np.expand_dims(a[:, 1], 1), b[:, 1])\n\n    iw = np.maximum(iw, 0)\n    ih = np.maximum(ih, 0)\n\n    ua = np.expand_dims((a[:, 2] - a[:, 0]) * (a[:, 3] - a[:, 1]), axis=1) + area - iw * ih\n\n    ua = np.maximum(ua, np.finfo(float).eps)\n\n    intersection = iw * ih\n\n    return intersection / ua  \n    \ndef compute_ap(recall, precision):\n    \"\"\" Compute the average precision, given the recall and precision curves.\n    Code originally from https://github.com/rbgirshick/py-faster-rcnn.\n\n    # Arguments\n        recall:    The recall curve (list).\n        precision: The precision curve (list).\n    # Returns\n        The average precision as computed in py-faster-rcnn.\n    \"\"\"\n    # correct AP calculation\n    # first append sentinel values at the end\n    mrec = np.concatenate(([0.], recall, [1.]))\n    mpre = np.concatenate(([0.], precision, [0.]))\n\n    # compute the precision envelope\n    for i in range(mpre.size - 1, 0, -1):\n        mpre[i - 1] = np.maximum(mpre[i - 1], mpre[i])\n\n    # to calculate area under PR curve, look for points\n    # where X axis (recall) changes value\n    i = np.where(mrec[1:] != mrec[:-1])[0]\n\n    # and sum (\\Delta recall) * prec\n    ap = np.sum((mrec[i + 1] - mrec[i]) * mpre[i + 1])\n    return ap      \n        \ndef _interval_overlap(interval_a, interval_b):\n    x1, x2 = interval_a\n    x3, x4 = interval_b\n\n    if x3 < x1:\n        if x4 < x1:\n            return 0\n        else:\n            return min(x2,x4) - x1\n    else:\n        if x2 < x3:\n             return 0\n        else:\n            return min(x2,x4) - x3          \n\ndef _sigmoid(x):\n    return 1. / (1. + np.exp(-x))\n\ndef _softmax(x, axis=-1, t=-100.):\n    x = x - np.max(x)\n    \n    if np.min(x) < t:\n        x = x/np.min(x)*t\n        \n    e_x = np.exp(x)\n    \n    return e_x / e_x.sum(axis, keepdims=True)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import argparse\nimport os\nimport cv2\nimport numpy as np\nimport json\n\nimport tensorflow as tf\nimport keras\nfrom keras.layers import Reshape, Activation, Conv2D, Input, MaxPooling2D, BatchNormalization, Flatten, Dense, Lambda\nfrom keras.layers.advanced_activations import LeakyReLU\nfrom keras.layers.merge import concatenate\nfrom keras.models import Model\n\nimport matplotlib.pyplot as plt","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"nb_box = 10\nnb_class = 1\nmax_box_per_image = 64\ninput_size = 512\ntrue_boxes = Input(shape=(1, 1, 1, max_box_per_image , 4))\nanchors = [0.60,1.18, 0.88,0.58, 1.03,0.98, 1.06,1.56, 1.39,2.48, 1.42,1.19, 1.58,0.71, 1.82,1.66, 2.32,1.13, 2.90,2.48]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"input_image = Input(shape=(input_size, input_size, 3))\n\n# the function to implement the orgnization layer (thanks to github.com/allanzelener/YAD2K)\ndef space_to_depth_x2(x):\n    import tensorflow as tf\n    return tf.compat.v1.space_to_depth(x, block_size=2)\n\n# Layer 1\nx = Conv2D(32, (3,3), strides=(1,1), padding='same', name='conv_1', use_bias=False)(input_image)\nx = BatchNormalization(name='norm_1')(x)\nx = LeakyReLU(alpha=0.1)(x)\nx = MaxPooling2D(pool_size=(2, 2))(x)\n\n# Layer 2\nx = Conv2D(64, (3,3), strides=(1,1), padding='same', name='conv_2', use_bias=False)(x)\nx = BatchNormalization(name='norm_2')(x)\nx = LeakyReLU(alpha=0.1)(x)\nx = MaxPooling2D(pool_size=(2, 2))(x)\n\n# Layer 3\nx = Conv2D(128, (3,3), strides=(1,1), padding='same', name='conv_3', use_bias=False)(x)\nx = BatchNormalization(name='norm_3')(x)\nx = LeakyReLU(alpha=0.1)(x)\n\n# Layer 4\nx = Conv2D(64, (1,1), strides=(1,1), padding='same', name='conv_4', use_bias=False)(x)\nx = BatchNormalization(name='norm_4')(x)\nx = LeakyReLU(alpha=0.1)(x)\n\n# Layer 5\nx = Conv2D(128, (3,3), strides=(1,1), padding='same', name='conv_5', use_bias=False)(x)\nx = BatchNormalization(name='norm_5')(x)\nx = LeakyReLU(alpha=0.1)(x)\nx = MaxPooling2D(pool_size=(2, 2))(x)\n\n# Layer 6\nx = Conv2D(256, (3,3), strides=(1,1), padding='same', name='conv_6', use_bias=False)(x)\nx = BatchNormalization(name='norm_6')(x)\nx = LeakyReLU(alpha=0.1)(x)\n\n# Layer 7\nx = Conv2D(128, (1,1), strides=(1,1), padding='same', name='conv_7', use_bias=False)(x)\nx = BatchNormalization(name='norm_7')(x)\nx = LeakyReLU(alpha=0.1)(x)\n\n# Layer 8\nx = Conv2D(256, (3,3), strides=(1,1), padding='same', name='conv_8', use_bias=False)(x)\nx = BatchNormalization(name='norm_8')(x)\nx = LeakyReLU(alpha=0.1)(x)\nx = MaxPooling2D(pool_size=(2, 2))(x)\n\n# Layer 9\nx = Conv2D(512, (3,3), strides=(1,1), padding='same', name='conv_9', use_bias=False)(x)\nx = BatchNormalization(name='norm_9')(x)\nx = LeakyReLU(alpha=0.1)(x)\n\n# Layer 10\nx = Conv2D(256, (1,1), strides=(1,1), padding='same', name='conv_10', use_bias=False)(x)\nx = BatchNormalization(name='norm_10')(x)\nx = LeakyReLU(alpha=0.1)(x)\n\n# Layer 11\nx = Conv2D(512, (3,3), strides=(1,1), padding='same', name='conv_11', use_bias=False)(x)\nx = BatchNormalization(name='norm_11')(x)\nx = LeakyReLU(alpha=0.1)(x)\n\n# Layer 12\nx = Conv2D(256, (1,1), strides=(1,1), padding='same', name='conv_12', use_bias=False)(x)\nx = BatchNormalization(name='norm_12')(x)\nx = LeakyReLU(alpha=0.1)(x)\n\n# Layer 13\nx = Conv2D(512, (3,3), strides=(1,1), padding='same', name='conv_13', use_bias=False)(x)\nx = BatchNormalization(name='norm_13')(x)\nx = LeakyReLU(alpha=0.1)(x)\n\nskip_connection = x\n\nx = MaxPooling2D(pool_size=(2, 2))(x)\n\n# Layer 14\nx = Conv2D(1024, (3,3), strides=(1,1), padding='same', name='conv_14', use_bias=False)(x)\nx = BatchNormalization(name='norm_14')(x)\nx = LeakyReLU(alpha=0.1)(x)\n\n# Layer 15\nx = Conv2D(512, (1,1), strides=(1,1), padding='same', name='conv_15', use_bias=False)(x)\nx = BatchNormalization(name='norm_15')(x)\nx = LeakyReLU(alpha=0.1)(x)\n\n# Layer 16\nx = Conv2D(1024, (3,3), strides=(1,1), padding='same', name='conv_16', use_bias=False)(x)\nx = BatchNormalization(name='norm_16')(x)\nx = LeakyReLU(alpha=0.1)(x)\n\n# Layer 17\nx = Conv2D(512, (1,1), strides=(1,1), padding='same', name='conv_17', use_bias=False)(x)\nx = BatchNormalization(name='norm_17')(x)\nx = LeakyReLU(alpha=0.1)(x)\n\n# Layer 18\nx = Conv2D(1024, (3,3), strides=(1,1), padding='same', name='conv_18', use_bias=False)(x)\nx = BatchNormalization(name='norm_18')(x)\nx = LeakyReLU(alpha=0.1)(x)\n\n# Layer 19\nx = Conv2D(1024, (3,3), strides=(1,1), padding='same', name='conv_19', use_bias=False)(x)\nx = BatchNormalization(name='norm_19')(x)\nx = LeakyReLU(alpha=0.1)(x)\n\n# Layer 20\nx = Conv2D(1024, (3,3), strides=(1,1), padding='same', name='conv_20', use_bias=False)(x)\nx = BatchNormalization(name='norm_20')(x)\nx = LeakyReLU(alpha=0.1)(x)\n\n# Layer 21\nskip_connection = Conv2D(64, (1,1), strides=(1,1), padding='same', name='conv_21', use_bias=False)(skip_connection)\nskip_connection = BatchNormalization(name='norm_21')(skip_connection)\nskip_connection = LeakyReLU(alpha=0.1)(skip_connection)\nskip_connection = Lambda(space_to_depth_x2)(skip_connection)\n\nx = concatenate([skip_connection, x])\n\n# Layer 22\nx = Conv2D(1024, (3,3), strides=(1,1), padding='same', name='conv_22', use_bias=False)(x)\nx = BatchNormalization(name='norm_22')(x)\nx = LeakyReLU(alpha=0.1)(x)\n\nfeature_extractor = Model(input_image, x)\n \n\n#grid_h, grid_w = feature_extractor.get_output_shape()\ngrid_h, grid_w = 16, 16\nfeatures = feature_extractor(input_image)            \n\n# make the object detection layer\noutput = Conv2D(nb_box * (4 + 1 + nb_class), \n                (1,1), strides=(1,1), \n                padding='same', \n                name='DetectionLayer', \n                kernel_initializer='lecun_normal')(features)\noutput = Reshape((grid_h, grid_w, nb_box, 4 + 1 + nb_class))(output)\noutput = Lambda(lambda args: args[0])([output, true_boxes])\n\nmodel = Model([input_image, true_boxes], output)\n\n\n# initialize the weights of the detection layer\nlayer = model.layers[-4]\nweights = layer.get_weights()\n\nnew_kernel = np.random.normal(size=weights[0].shape)/(grid_h*grid_w)\nnew_bias   = np.random.normal(size=weights[1].shape)/(grid_h*grid_w)\n\nlayer.set_weights([new_kernel, new_bias])\n\n# print a summary of the whole model\nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"def predict(image):\n    image_h, image_w, _ = image.shape\n    image = cv2.resize(image, (input_size, input_size))\n    image = image / 255.\n\n    input_image = image[:,:,::-1]\n    input_image = np.expand_dims(input_image, 0)\n    dummy_array = np.zeros((1,1,1,1,max_box_per_image,4))\n\n    netout = model.predict([input_image, dummy_array])[0]\n    boxes  = decode_netout(netout, anchors, nb_class)\n\n    return boxes","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.load_weights(\"../input/wheat-yolo/yolo_v2.5.h5\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"image = cv2.imread(\"../input/global-wheat-detection/test/51b3e36ab.jpg\")\nplt.imshow(image)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"boxes = predict(image)\nprint(boxes)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"image = draw_boxes(image, boxes, ['head'])\nplt.imshow(image)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import pandas as pd\n\nim_ids = []\npreds = []\n\nfor f in os.listdir(\"../input/global-wheat-detection/test/\"):\n    im = cv2.imread(\"../input/global-wheat-detection/test/\"+f)\n    im_ids.append(f.split(\".\")[0])\n    \n    boxes = predict(im)\n    \n    all_boxes = []\n    for box in boxes:\n        x = [box.c, int(box.xmin*1024), int(box.ymin*1024), int((box.xmax - box.xmin)*1024), int((box.ymax - box.ymin)*1024)]\n        x = [str(i) for i in x]\n        x = \" \".join(x)\n        #print(x)\n        all_boxes.append(x)\n    \n    preds.append(\" \".join(all_boxes))\n    \nsub = pd.DataFrame({'image_id':im_ids, 'PredictionString':preds})\nsub.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sub.to_csv(\"submission.csv\", index=False)","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}