{"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_minor":4,"nbformat":4,"cells":[{"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 in \n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nfrom skimage.data import imread\nimport matplotlib.pyplot as plt\n\n# Input data files are available in the \"../input/\" directory.\n# For example, running this (by clicking run or pressing Shift+Enter) will list the files in the input directory\n\nimport os\nprint(os.listdir(\"../input/\"))\n\n# Any results you write to the current directory are saved as output.","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# ref: https://www.kaggle.com/paulorzp/run-length-encode-and-decode\ndef rle_decode(mask_rle, shape=(768, 768)):\n    '''\n    mask_rle: run-length as string formated (start length)\n    shape: (height,width) of array to return \n    Returns numpy array, 1 - mask, 0 - background\n\n    '''\n    s = mask_rle.split()\n    starts, lengths = [np.asarray(x, dtype=int) for x in (s[0:][::2], s[1:][::2])]\n    starts -= 1\n    ends = starts + lengths\n    img = np.zeros(shape[0]*shape[1], dtype=np.uint8)\n    for lo, hi in zip(starts, ends):\n        img[lo:hi] = 1\n    return img.reshape(shape).T  # Needed to align to RLE direction","metadata":{"_uuid":"6122ccb9e58bfac6fa5e11c86121e78d9e5151b1","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"masks = pd.read_csv(\"../input/train_ship_segmentations_v2.csv\")\n\nmasks.head()","metadata":{"_uuid":"206104f888afa9c62a0bbcb45229f58111094f18","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"is_boat = masks.EncodedPixels.notnull()\nprint('Found {} boats'.format(is_boat.sum()))\nmasks = masks[is_boat].reset_index().drop(['index'], axis=1)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"masks.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for r, row in masks.iterrows():\n    if r == 10: \n        break\n    ImageId = masks.iloc[r]['ImageId']\n\n    img = imread('../input/train_v2/' + ImageId)\n    img_masks = masks.loc[masks['ImageId'] == ImageId, 'EncodedPixels'].tolist()\n\n    # Take the individual ship masks and create a single mask array for all ships\n    all_masks = np.zeros((768, 768))\n    for mask in img_masks:\n        all_masks += rle_decode(mask)\n\n    fig, axarr = plt.subplots(1, 3, figsize=(15, 40))\n    axarr[0].axis('off')\n    axarr[1].axis('off')\n    axarr[2].axis('off')\n    axarr[0].imshow(img)\n    axarr[1].imshow(all_masks)\n    axarr[2].imshow(img)\n    axarr[2].imshow(all_masks, alpha=0.4)\n    plt.tight_layout(h_pad=0.1, w_pad=0.1)\n    plt.show()\n","metadata":{"_uuid":"63e18e8573dbb3fe1d3ff1d72b6dc756e067d43a","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def circular_hist(ax, x, bins=16, density=True, offset=0, gaps=True):\n    \"\"\"\n    Produce a circular histogram of angles on ax.\n\n    Parameters\n    ----------\n    ax : matplotlib.axes._subplots.PolarAxesSubplot\n        axis instance created with subplot_kw=dict(projection='polar').\n\n    x : array\n        Angles to plot, expected in units of radians.\n\n    bins : int, optional\n        Defines the number of equal-width bins in the range. The default is 16.\n\n    density : bool, optional\n        If True plot frequency proportional to area. If False plot frequency\n        proportional to radius. The default is True.\n\n    offset : float, optional\n        Sets the offset for the location of the 0 direction in units of\n        radians. The default is 0.\n\n    gaps : bool, optional\n        Whether to allow gaps between bins. When gaps = False the bins are\n        forced to partition the entire [-pi, pi] range. The default is True.\n\n    Returns\n    -------\n    n : array or list of arrays\n        The number of values in each bin.\n\n    bins : array\n        The edges of the bins.\n\n    patches : `.BarContainer` or list of a single `.Polygon`\n        Container of individual artists used to create the histogram\n        or list of such containers if there are multiple input datasets.\n    \"\"\"\n    # Wrap angles to [-pi, pi)\n    x = (x+np.pi) % (2*np.pi) - np.pi\n\n    # Force bins to partition entire circle\n    if not gaps:\n        bins = np.linspace(-np.pi, np.pi, num=bins+1)\n\n    # Bin data and record counts\n    n, bins = np.histogram(x, bins=bins)\n\n    # Compute width of each bin\n    widths = np.diff(bins)\n\n    # By default plot frequency proportional to area\n    if density:\n        # Area to assign each bin\n        area = n / x.size\n        # Calculate corresponding bin radius\n        radius = (area/np.pi) ** .5\n    # Otherwise plot frequency proportional to radius\n    else:\n        radius = n\n\n    # Plot data on ax\n    patches = ax.bar(bins[:-1], radius, zorder=1, align='edge', width=widths)\n\n    # Set the direction of the zero angle\n    ax.set_theta_offset(offset)\n\n    # Remove ylabels for area plots (they are mostly obstructive)\n    if density:\n        ax.set_yticks([])\n\n    return n, bins, patches","metadata":{"_uuid":"0a38d343b2654f87934a88524ebc14a5759e07cb","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def azimuth(point1, point2):\n    '''azimuth between 2 shapely points (interval 0 - 360)'''\n    \n    angle = np.arctan2(point2[0] - point1[0], point2[1] - point1[1])\n    return np.degrees(angle) if angle >= 0 else np.degrees(angle) + 360\n\ndef get_angle(point1, point2):\n    degrees = azimuth(point1, point2)\n    return degrees * np.pi / 180\n\ndef distance(point1, point2):\n    return np.sqrt((point1[0] - point2[0])**2 + (point1[1] - point2[1])**2)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install rasterio fiona shapely geopandas","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import rasterio\nimport shapely.geometry\nimport rasterio.features\nfrom shapely.geometry import Polygon\nimport glob","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"xs = []\nfor r,row in masks.iterrows():\n     \n    img = (np.squeeze(rle_decode(masks.iloc[r]['EncodedPixels'])))\n    img = (img > 0).astype('int16')\n    shapes = rasterio.features.shapes(img)\n    polygons = [shapely.geometry.Polygon(s[0][\"coordinates\"][0]) for s in shapes if s[1] == 1]\n    sole_polygon = polygons[0]\n    \n    rect = sole_polygon.minimum_rotated_rectangle\n    points = list(rect.exterior.coords)\n    max_dist = 0\n    max_idx = None\n    \n    dist_arr = []\n    for i in range(4):\n        dist = distance(points[i], points[i+1])\n        dist_arr.append(dist)\n        if dist >= max_dist:\n            max_dist = dist\n            max_idx = i\n            \n    for i in range(4):\n        dist = distance(points[i], points[i+1])\n        if dist == max_dist:\n            point1 = points[i]\n            point2 = points[i+1]\n            radians = get_angle(point1, point2)\n            xs.append(radians)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"offset=360-36\noffset_r = 350\n\nfig, ax = plt.subplots(1,1,figsize=(8,8), subplot_kw=dict(projection='polar'))\n\nhist, bin_edges, patches = circular_hist(ax, np.array(xs), density=False, bins=60, gaps=True)\n#plt.plot([(180+offset)*np.pi/180,offset*np.pi/180], [offset_r,offset_r], color=\"#ccc\", linewidth=0.5, zorder=1)\n\nax.set_rlabel_position(offset)\n\nplt.title(name)\nplt.yticks([100,200,300], fontsize=14, backgroundcolor=\"#cccc\")\nplt.tick_params(axis=\"y\", zorder=3)\nplt.xticks([0,np.pi/2,np.pi, 3*np.pi/2], fontsize=15)\n\nax.grid(b=True, which='major', axis='x', color='#000', linestyle='-', linewidth=1)\nax.grid(b=False, which='minor', axis='x', color='#000', linestyle='-', linewidth=1)\nax.grid(b=True, which='major', axis='y', color='#ccc', linestyle='-', linewidth=0.6, zorder=0)\nax.grid(b=False, which='minor', axis='y')\n\nax.spines['polar'].set_visible(False)\n\nplt.show()\nplt.close()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(xs)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(xs2)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(masks)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"asr_arr = []\nfor r,row in masks.iterrows():\n    img = (np.squeeze(rle_decode(masks.iloc[r]['EncodedPixels'])))\n    img = (img > 0).astype('int16')\n    shapes = rasterio.features.shapes(img)\n    polygons = [shapely.geometry.Polygon(s[0][\"coordinates\"][0]) for s in shapes if s[1] == 1]\n    sole_polygon = polygons[0]\n    \n    rect = sole_polygon.minimum_rotated_rectangle\n    points = list(rect.exterior.coords)\n    dist_arr = []\n    for i in range(4):\n        dist = distance(points[i], points[i+1])\n        dist_arr.append(dist)\n        if dist >= max_dist:\n            max_dist = dist\n            max_idx = i\n    wh = (sorted(np.unique(dist_arr)))\n    if (len(wh) == 1):\n        asr_arr.append(1.0)\n    else:\n        asr = (wh[1] / wh[0])\n        asr_arr.append(asr)\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, ax = plt.subplots(1,1)\nax.hist(np.array(asr_arr), bins=np.logspace(0,1,num=20))\nax.set_xscale(\"log\")\nax.set_xlabel('Aspect Ratio')\nax.set_ylabel('Frequency')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"asr_arr = np.array(asr_arr)\nlen(asr_arr)\nlen(asr_arr[asr_arr < 1.01]) / len(asr_arr)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"count = 0\nfor i in asr_arr:\n    if i < 1.1:\n        count+=1\n        \nprint(count / len(asr_arr))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"xs2 = xs","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}