{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 5GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"import tensorflow as tf","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"_BATCH_NORM_DECAY = 0.9\n_BATCH_NORM_EPSILON = 1e-05\n_LEAKY_RELU = 0.1\n_ANCHORS = [(10, 13), (16, 30), (33, 23),\n            (30, 61), (62, 45), (59, 119),\n            (116, 90), (156, 198), (373, 326)]\n_MODEL_SIZE = (416, 416)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def batch_norm(inputs,training,data_format):\n    return tf.layers.batch_normalization(\n        inputs=inputs, axis=1 if data_format == 'channels_first' else 3,\n        momentum=_BATCH_NORM_DECAY, epsilon=_BATCH_NORM_EPSILON,\n        scale=True, training=training)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def fixed_padding(inputs,kernel_size, data_format):\n    pad_total = kernel_size - 1\n    pad_beg = pad_total // 2\n    pad_end = pad_total - pad_beg\n\n    if data_format == 'channels_first':\n        padded_inputs = tf.pad(inputs, [[0, 0], [0, 0],\n                                        [pad_beg, pad_end],\n                                        [pad_beg, pad_end]])\n    else:\n        padded_inputs = tf.pad(inputs, [[0, 0], [pad_beg, pad_end],\n                                        [pad_beg, pad_end], [0, 0]])\n    return padded_inputs","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def conv2d_fixed_padding(inputs, filters, kernel_size, data_format, strides=1):\n    \"\"\"Strided 2-D convolution with explicit padding.\"\"\"\n    if strides > 1:\n        inputs = fixed_padding(inputs, kernel_size, data_format)\n\n    return tf.layers.conv2d(\n        inputs=inputs, filters=filters, kernel_size=kernel_size,\n        strides=strides, padding=('SAME' if strides == 1 else 'VALID'),\n        use_bias=False, data_format=data_format)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def darknet53_residual_block(inputs, filters, training, data_format,\n                             strides=1):\n    \"\"\"Creates a residual block for Darknet.\"\"\"\n    shortcut = inputs\n\n    inputs = conv2d_fixed_padding(\n        inputs, filters=filters, kernel_size=1, strides=strides,\n        data_format=data_format)\n    inputs = batch_norm(inputs, training=training, data_format=data_format)\n    inputs = tf.nn.leaky_relu(inputs, alpha=_LEAKY_RELU)\n\n    inputs = conv2d_fixed_padding(\n        inputs, filters=2 * filters, kernel_size=3, strides=strides,\n        data_format=data_format)\n    inputs = batch_norm(inputs, training=training, data_format=data_format)\n    inputs = tf.nn.leaky_relu(inputs, alpha=_LEAKY_RELU)\n\n    inputs += shortcut\n\n    return inputs","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def darknet53(inputs, training, data_format):\n    \"\"\"Creates Darknet53 model for feature extraction.\"\"\"\n    inputs = conv2d_fixed_padding(inputs, filters=32, kernel_size=3,\n                                  data_format=data_format)\n    inputs = batch_norm(inputs, training=training, data_format=data_format)\n    inputs = tf.nn.leaky_relu(inputs, alpha=_LEAKY_RELU)\n    inputs = conv2d_fixed_padding(inputs, filters=64, kernel_size=3,\n                                  strides=2, data_format=data_format)\n    inputs = batch_norm(inputs, training=training, data_format=data_format)\n    inputs = tf.nn.leaky_relu(inputs, alpha=_LEAKY_RELU)\n\n    inputs = darknet53_residual_block(inputs, filters=32, training=training,\n                                      data_format=data_format)\n\n    inputs = conv2d_fixed_padding(inputs, filters=128, kernel_size=3,\n                                  strides=2, data_format=data_format)\n    inputs = batch_norm(inputs, training=training, data_format=data_format)\n    inputs = tf.nn.leaky_relu(inputs, alpha=_LEAKY_RELU)\n\n    for _ in range(2):\n        inputs = darknet53_residual_block(inputs, filters=64,\n                                          training=training,\n                                          data_format=data_format)\n\n    inputs = conv2d_fixed_padding(inputs, filters=256, kernel_size=3,\n                                  strides=2, data_format=data_format)\n    inputs = batch_norm(inputs, training=training, data_format=data_format)\n    inputs = tf.nn.leaky_relu(inputs, alpha=_LEAKY_RELU)\n\n    for _ in range(8):\n        inputs = darknet53_residual_block(inputs, filters=128,\n                                          training=training,\n                                          data_format=data_format)\n\n    route1 = inputs\n\n    inputs = conv2d_fixed_padding(inputs, filters=512, kernel_size=3,\n                                  strides=2, data_format=data_format)\n    inputs = batch_norm(inputs, training=training, data_format=data_format)\n    inputs = tf.nn.leaky_relu(inputs, alpha=_LEAKY_RELU)\n\n    for _ in range(8):\n        inputs = darknet53_residual_block(inputs, filters=256,\n                                          training=training,\n                                          data_format=data_format)\n\n    route2 = inputs\n\n    inputs = conv2d_fixed_padding(inputs, filters=1024, kernel_size=3,\n                                  strides=2, data_format=data_format)\n    inputs = batch_norm(inputs, training=training, data_format=data_format)\n    inputs = tf.nn.leaky_relu(inputs, alpha=_LEAKY_RELU)\n\n    for _ in range(4):\n        inputs = darknet53_residual_block(inputs, filters=512,\n                                          training=training,\n                                          data_format=data_format)\n\n    return route1, route2, inputs","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def yolo_convolution_block(inputs, filters, training, data_format):\n    \"\"\"Creates convolution operations layer used after Darknet.\"\"\"\n    inputs = conv2d_fixed_padding(inputs, filters=filters, kernel_size=1,\n                                  data_format=data_format)\n    inputs = batch_norm(inputs, training=training, data_format=data_format)\n    inputs = tf.nn.leaky_relu(inputs, alpha=_LEAKY_RELU)\n\n    inputs = conv2d_fixed_padding(inputs, filters=2 * filters, kernel_size=3,\n                                  data_format=data_format)\n    inputs = batch_norm(inputs, training=training, data_format=data_format)\n    inputs = tf.nn.leaky_relu(inputs, alpha=_LEAKY_RELU)\n\n    inputs = conv2d_fixed_padding(inputs, filters=filters, kernel_size=1,\n                                  data_format=data_format)\n    inputs = batch_norm(inputs, training=training, data_format=data_format)\n    inputs = tf.nn.leaky_relu(inputs, alpha=_LEAKY_RELU)\n\n    inputs = conv2d_fixed_padding(inputs, filters=2 * filters, kernel_size=3,\n                                  data_format=data_format)\n    inputs = batch_norm(inputs, training=training, data_format=data_format)\n    inputs = tf.nn.leaky_relu(inputs, alpha=_LEAKY_RELU)\n\n    inputs = conv2d_fixed_padding(inputs, filters=filters, kernel_size=1,\n                                  data_format=data_format)\n    inputs = batch_norm(inputs, training=training, data_format=data_format)\n    inputs = tf.nn.leaky_relu(inputs, alpha=_LEAKY_RELU)\n\n    route = inputs\n\n    inputs = conv2d_fixed_padding(inputs, filters=2 * filters, kernel_size=3,\n                                  data_format=data_format)\n    inputs = batch_norm(inputs, training=training, data_format=data_format)\n    inputs = tf.nn.leaky_relu(inputs, alpha=_LEAKY_RELU)\n\n    return route, inputs","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def yolo_layer(inputs, n_classes, anchors, img_size, data_format):\n    \"\"\"Creates Yolo final detection layer.\n\n    Detects boxes with respect to anchors.\n\n    Args:\n        inputs: Tensor input.\n        n_classes: Number of labels.\n        anchors: A list of anchor sizes.\n        img_size: The input size of the model.\n        data_format: The input format.\n\n    Returns:\n        Tensor output.\n    \"\"\"\n    n_anchors = len(anchors)\n\n    inputs = tf.layers.conv2d(inputs, filters=n_anchors * (5 + n_classes),\n                              kernel_size=1, strides=1, use_bias=True,\n                              data_format=data_format)\n\n    shape = inputs.get_shape().as_list()\n    grid_shape = shape[2:4] if data_format == 'channels_first' else shape[1:3]\n    if data_format == 'channels_first':\n        inputs = tf.transpose(inputs, [0, 2, 3, 1])\n    inputs = tf.reshape(inputs, [-1, n_anchors * grid_shape[0] * grid_shape[1],\n                                 5 + n_classes])\n\n    strides = (img_size[0] // grid_shape[0], img_size[1] // grid_shape[1])\n\n    box_centers, box_shapes, confidence, classes = \\\n        tf.split(inputs, [2, 2, 1, n_classes], axis=-1)\n\n    x = tf.range(grid_shape[0], dtype=tf.float32)\n    y = tf.range(grid_shape[1], dtype=tf.float32)\n    x_offset, y_offset = tf.meshgrid(x, y)\n    x_offset = tf.reshape(x_offset, (-1, 1))\n    y_offset = tf.reshape(y_offset, (-1, 1))\n    x_y_offset = tf.concat([x_offset, y_offset], axis=-1)\n    x_y_offset = tf.tile(x_y_offset, [1, n_anchors])\n    x_y_offset = tf.reshape(x_y_offset, [1, -1, 2])\n    box_centers = tf.nn.sigmoid(box_centers)\n    box_centers = (box_centers + x_y_offset) * strides\n\n    anchors = tf.tile(anchors, [grid_shape[0] * grid_shape[1], 1])\n    box_shapes = tf.exp(box_shapes) * tf.to_float(anchors)\n\n    confidence = tf.nn.sigmoid(confidence)\n\n    classes = tf.nn.sigmoid(classes)\n\n    inputs = tf.concat([box_centers, box_shapes,\n                        confidence, classes], axis=-1)\n\n    return inputs","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def upsample(inputs, out_shape, data_format):\n    \"\"\"Upsamples to `out_shape` using nearest neighbor interpolation.\"\"\"\n    if data_format == 'channels_first':\n        inputs = tf.transpose(inputs, [0, 2, 3, 1])\n        new_height = out_shape[3]\n        new_width = out_shape[2]\n    else:\n        new_height = out_shape[2]\n        new_width = out_shape[1]\n\n    inputs = tf.image.resize_nearest_neighbor(inputs, (new_height, new_width))\n\n    if data_format == 'channels_first':\n        inputs = tf.transpose(inputs, [0, 3, 1, 2])\n\n    return inputs","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def build_boxes(inputs):\n    \"\"\"Computes top left and bottom right points of the boxes.\"\"\"\n    center_x, center_y, width, height, confidence, classes = \\\n        tf.split(inputs, [1, 1, 1, 1, 1, -1], axis=-1)\n\n    top_left_x = center_x - width / 2\n    top_left_y = center_y - height / 2\n    bottom_right_x = center_x + width / 2\n    bottom_right_y = center_y + height / 2\n\n    boxes = tf.concat([top_left_x, top_left_y,\n                       bottom_right_x, bottom_right_y,\n                       confidence, classes], axis=-1)\n\n    return boxes","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def non_max_suppression(inputs, n_classes, max_output_size, iou_threshold,\n                        confidence_threshold):\n    batch = tf.unstack(inputs)\n    boxes_dicts = []\n    for boxes in batch:\n        boxes = tf.boolean_mask(boxes, boxes[:, 4] > confidence_threshold)\n        classes = tf.argmax(boxes[:, 5:], axis=-1)\n        classes = tf.expand_dims(tf.to_float(classes), axis=-1)\n        boxes = tf.concat([boxes[:, :5], classes], axis=-1)\n\n        boxes_dict = dict()\n        for cls in range(n_classes):\n            mask = tf.equal(boxes[:, 5], cls)\n            mask_shape = mask.get_shape()\n            if mask_shape.ndims != 0:\n                class_boxes = tf.boolean_mask(boxes, mask)\n                boxes_coords, boxes_conf_scores, _ = tf.split(class_boxes,\n                                                              [4, 1, -1],\n                                                              axis=-1)\n                boxes_conf_scores = tf.reshape(boxes_conf_scores, [-1])\n                indices = tf.image.non_max_suppression(boxes_coords,\n                                                       boxes_conf_scores,\n                                                       max_output_size,\n                                                       iou_threshold)\n                class_boxes = tf.gather(class_boxes, indices)\n                boxes_dict[cls] = class_boxes[:, :5]\n\n        boxes_dicts.append(boxes_dict)\n\n    return boxes_dicts","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def load_images(img_names, model_size):\n    \"\"\"Loads images in a 4D array.\n\n    Args:\n        img_names: A list of images names.\n        model_size: The input size of the model.\n        data_format: A format for the array returned\n            ('channels_first' or 'channels_last').\n\n    Returns:\n        A 4D NumPy array.\n    \"\"\"\n    imgs = []\n\n    for img_name in img_names:\n        img = Image.open(img_name)\n        img = img.resize(size=model_size)\n        img = np.array(img, dtype=np.float32)\n        img = np.expand_dims(img, axis=0)\n        imgs.append(img)\n\n    imgs = np.concatenate(imgs)\n\n    return imgs\n\n\ndef load_class_names(file_name):\n    \"\"\"Returns a list of class names read from `file_name`.\"\"\"\n    with open(file_name, 'r') as f:\n        class_names = f.read().splitlines()\n    return class_names\n\n\ndef draw_boxes(img_names, boxes_dicts, class_names, model_size):\n    \"\"\"Draws detected boxes.\n\n    Args:\n        img_names: A list of input images names.\n        boxes_dict: A class-to-boxes dictionary.\n        class_names: A class names list.\n        model_size: The input size of the model.\n\n    Returns:\n        None.\n    \"\"\"\n    colors = ((np.array(color_palette(\"hls\", 80)) * 255)).astype(np.uint8)\n    for num, img_name, boxes_dict in zip(range(len(img_names)), img_names,\n                                         boxes_dicts):\n        img = Image.open(img_name)\n        draw = ImageDraw.Draw(img)\n        font = ImageFont.truetype(font='../input/futur.ttf',\n                                  size=(img.size[0] + img.size[1]) // 100)\n        resize_factor = \\\n            (img.size[0] / model_size[0], img.size[1] / model_size[1])\n        for cls in range(len(class_names)):\n            boxes = boxes_dict[cls]\n            if np.size(boxes) != 0:\n                color = colors[cls]\n                for box in boxes:\n                    xy, confidence = box[:4], box[4]\n                    xy = [xy[i] * resize_factor[i % 2] for i in range(4)]\n                    x0, y0 = xy[0], xy[1]\n                    thickness = (img.size[0] + img.size[1]) // 200\n                    for t in np.linspace(0, 1, thickness):\n                        xy[0], xy[1] = xy[0] + t, xy[1] + t\n                        xy[2], xy[3] = xy[2] - t, xy[3] - t\n                        draw.rectangle(xy, outline=tuple(color))\n                    text = '{} {:.1f}%'.format(class_names[cls],\n                                               confidence * 100)\n                    text_size = draw.textsize(text, font=font)\n                    draw.rectangle(\n                        [x0, y0 - text_size[1], x0 + text_size[0], y0],\n                        fill=tuple(color))\n                    draw.text((x0, y0 - text_size[1]), text, fill='black',\n                              font=font)\n\n        display(img)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def load_weights(variables, file_name):\n    \"\"\"Reshapes and loads official pretrained Yolo weights.\n\n    Args:\n        variables: A list of tf.Variable to be assigned.\n        file_name: A name of a file containing weights.\n\n    Returns:\n        A list of assign operations.\n    \"\"\"\n    with open(file_name, \"rb\") as f:\n        # Skip first 5 values containing irrelevant info\n        np.fromfile(f, dtype=np.int32, count=5)\n        weights = np.fromfile(f, dtype=np.float32)\n\n        assign_ops = []\n        ptr = 0\n\n        # Load weights for Darknet part.\n        # Each convolution layer has batch normalization.\n        for i in range(52):\n            conv_var = variables[5 * i]\n            gamma, beta, mean, variance = variables[5 * i + 1:5 * i + 5]\n            batch_norm_vars = [beta, gamma, mean, variance]\n\n            for var in batch_norm_vars:\n                shape = var.shape.as_list()\n                num_params = np.prod(shape)\n                var_weights = weights[ptr:ptr + num_params].reshape(shape)\n                ptr += num_params\n                assign_ops.append(tf.assign(var, var_weights))\n\n            shape = conv_var.shape.as_list()\n            num_params = np.prod(shape)\n            var_weights = weights[ptr:ptr + num_params].reshape(\n                (shape[3], shape[2], shape[0], shape[1]))\n            var_weights = np.transpose(var_weights, (2, 3, 1, 0))\n            ptr += num_params\n            assign_ops.append(tf.assign(conv_var, var_weights))\n\n        # Loading weights for Yolo part.\n        # 7th, 15th and 23rd convolution layer has biases and no batch norm.\n        ranges = [range(0, 6), range(6, 13), range(13, 20)]\n        unnormalized = [6, 13, 20]\n        for j in range(3):\n            for i in ranges[j]:\n                current = 52 * 5 + 5 * i + j * 2\n                conv_var = variables[current]\n                gamma, beta, mean, variance =  \\\n                    variables[current + 1:current + 5]\n                batch_norm_vars = [beta, gamma, mean, variance]\n\n                for var in batch_norm_vars:\n                    shape = var.shape.as_list()\n                    num_params = np.prod(shape)\n                    var_weights = weights[ptr:ptr + num_params].reshape(shape)\n                    ptr += num_params\n                    assign_ops.append(tf.assign(var, var_weights))\n\n                shape = conv_var.shape.as_list()\n                num_params = np.prod(shape)\n                var_weights = weights[ptr:ptr + num_params].reshape(\n                    (shape[3], shape[2], shape[0], shape[1]))\n                var_weights = np.transpose(var_weights, (2, 3, 1, 0))\n                ptr += num_params\n                assign_ops.append(tf.assign(conv_var, var_weights))\n\n            bias = variables[52 * 5 + unnormalized[j] * 5 + j * 2 + 1]\n            shape = bias.shape.as_list()\n            num_params = np.prod(shape)\n            var_weights = weights[ptr:ptr + num_params].reshape(shape)\n            ptr += num_params\n            assign_ops.append(tf.assign(bias, var_weights))\n\n            conv_var = variables[52 * 5 + unnormalized[j] * 5 + j * 2]\n            shape = conv_var.shape.as_list()\n            num_params = np.prod(shape)\n            var_weights = weights[ptr:ptr + num_params].reshape(\n                (shape[3], shape[2], shape[0], shape[1]))\n            var_weights = np.transpose(var_weights, (2, 3, 1, 0))\n            ptr += num_params\n            assign_ops.append(tf.assign(conv_var, var_weights))\n\n    return assign_ops","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"mg_names = ['../input/dog.jpg', '../input/office.jpg']\nfor img in img_names: display(Image.open(img))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"batch_size = len(img_names)\nbatch = load_images(img_names, model_size=_MODEL_SIZE)\nclass_names = load_class_names('../input/coco.names')\nn_classes = len(class_names)\nmax_output_size = 10\niou_threshold = 0.5\nconfidence_threshold = 0.5\n\nmodel = Yolo_v3(n_classes=n_classes, model_size=_MODEL_SIZE,\n                max_output_size=max_output_size,\n                iou_threshold=iou_threshold,\n                confidence_threshold=confidence_threshold)\n\ninputs = tf.placeholder(tf.float32, [batch_size, 416, 416, 3])\n\ndetections = model(inputs, training=False)\n\nmodel_vars = tf.global_variables(scope='yolo_v3_model')\nassign_ops = load_weights(model_vars, '../input/yolov3.weights')\n\nwith tf.Session() as sess:\n    sess.run(assign_ops)\n    detection_result = sess.run(detections, feed_dict={inputs: batch})\n    \ndraw_boxes(img_names, detection_result, class_names, _MODEL_SIZE)","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}