{"cells":[{"metadata":{"_uuid":"c7b14717ef2d34e514861dd0477bb291bf36c565"},"cell_type":"markdown","source":"### Overview\nIn this kernel I want to demonstrate the content of \"train_ship_segmentations_boxes.csv\" dataset that I created. It is an extended version of \"train_ship_segmentations.csv\" file from Airbus Ship Detection Challenge in which in addition to pixel masks I included the information about rotating bounding boxes."},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nfrom PIL import Image\nimport os\nimport matplotlib.pyplot as plt\nimport matplotlib.patches as patches\nimport math","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"77d824c0448a6c2022d342b4c0d2b352f0207377"},"cell_type":"code","source":"BOXES_PATH = '../input/rotating-bounding-boxes-for-ship-localization/train_ship_segmentations_boxes.csv'\nIMG_PATH = '../input/airbus-ship-detection/train/'","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"6655029d983278f3d3af9294be12e19a8525eeb7"},"cell_type":"markdown","source":"The meaning of columes is the following. \"ImageId\" is name of an image from train dataset (https://www.kaggle.com/c/airbus-ship-detection/data); \"EncodedPixelsPixel\" is Run-Length Encoding of the mask; \"x\" and \"y\" are X and Y coordinate of box center; \"lx\" and \"ly\" are length of the box along X and Y; and \"angle\" is the rotation angle of the box in radians."},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true,"scrolled":true},"cell_type":"code","source":"box_df = pd.read_csv(BOXES_PATH)\nbox_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"195a78c5e04f92631748bd9dd8dc2e7c6f18ab6e"},"cell_type":"code","source":"#convert RLE mask into 2d pixel array\ndef encode_mask(mask, shape=(768,768)):\n    img = np.zeros(shape[0]*shape[1], dtype=np.uint8)\n    s = mask.split()\n    for i in range(len(s)//2):\n        start = int(s[2*i]) - 1\n        length = int(s[2*i+1])\n        img[start:start+length] = 1\n    return img.reshape(shape).T\n\n#get bounding box for a mask\ndef get_bbox(img):\n    rows = np.any(img, axis=1)\n    cols = np.any(img, axis=0)\n    rmin, rmax = np.where(rows)[0][[0, -1]]\n    cmin, cmax = np.where(cols)[0][[0, -1]]\n    return rmin, rmax, cmin, cmax\n\n#add padding to the bounding box\ndef get_bbox_p(img, padding=5):\n    x1,x2,y1,y2 = get_bbox(img)\n    lx,ly = img.shape\n    x1 = max(x1-padding,0)\n    x2 = min(x2+padding+1, lx-1)\n    y1 = max(y1-padding,0)\n    y2 = min(y2+padding+1, ly-1)\n    return x1,x2,y1,y2\n\n#convert parameters of the box for plotting\ndef convert_box(box):\n    rot1 = math.cos(box[4])\n    rot2 = math.sin(box[4])\n    bx1 = box[0] - 0.5*(box[2]*rot1 - box[3]*rot2)\n    bx2 = box[1] - 0.5*(box[2]*rot2 + box[3]*rot1)\n    return (bx1,bx2,box[2],box[3],box[4]*180.0/math.pi)\n\ndef get_rec(box,width=1):\n    b = convert_box(box)\n    return patches.Rectangle((b[0],b[1]),b[2],b[3],b[4],linewidth=width,edgecolor='g',facecolor='none')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"1186970c8a9e46af384fcdde48824d6662f23cc9"},"cell_type":"code","source":"#plot image, mask, zoomed image, and zoomed mask with rotating bounding boxes\ndef show_box(idx):\n    row = box_df.iloc[idx]\n    name, encoding, x, y, lx, ly, rot = row.ImageId, row.EncodedPixels, \\\n        row.x, row.y, row.lx, row.ly, row.angle\n    if(type(encoding) == float): return #empty image\n\n    mask = encode_mask(encoding)\n    box = (x,y,lx,ly,rot)\n    image = np.asarray(Image.open(os.path.join(IMG_PATH,name)))\n    \n    fig,ax = plt.subplots(2, 2, figsize=(16, 16))\n    ax[0,0].imshow(image)\n    ax[0,1].imshow(mask)\n    ax[0,0].add_patch(get_rec(box))\n    ax[0,1].add_patch(get_rec(box))\n    \n    y1,y2,x1,x2 = get_bbox_p(mask,10)\n    box_c = (x-x1,y-y1,lx,ly,rot)\n    ax[1,0].imshow(image[y1:y2,x1:x2,:])\n    ax[1,1].imshow(mask[y1:y2,x1:x2])\n    ax[1,0].add_patch(get_rec(box_c,3))\n    ax[1,1].add_patch(get_rec(box_c,3))\n    \n    for item in ax.flatten():\n        item.axis('off')\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"b483b7306519a1070cd427624d6e938f31fe07a1"},"cell_type":"markdown","source":"Below I provide several examples of rotating bounding boxes."},{"metadata":{"trusted":true,"_uuid":"17d92079c4d1f14d7b0debbdeac89f69a32a1c14"},"cell_type":"code","source":"show_box(20)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"87af1d317a9b7784111dd92e49776a13323e4247"},"cell_type":"code","source":"show_box(19)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"62229702bb14e9a7174dca21b4d70823ce867828"},"cell_type":"code","source":"show_box(11)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"9a8f6868886b636687f8ef4503fd35d295a941df"},"cell_type":"code","source":"show_box(10)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"8459c01f2ffedb713bebb1fcafc37c90ec0ba547"},"cell_type":"code","source":"show_box(31)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"1841eec19d71160db0569485b2f5455fb80e6546"},"cell_type":"code","source":"show_box(1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a572542ea8f81af85b49ed8b56eb9f9e86535e41"},"cell_type":"code","source":"show_box(39)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"37a6d5607db35942335d4e66694ab01b0c6fd124"},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}