{
  "id": 336639,
  "title": "How masks are obtained from polygons?",
  "url": "/competitions/hubmap-organ-segmentation/discussion/336639",
  "author_name": "",
  "post_date": "2022-07-12T08:30:16.499499300Z",
  "votes": 7,
  "comment_count": 2,
  "views": 0,
  "content": "<p>I'm trying to replicate the mask creation process but I couldn't get exact same rle masks. I'm currently using PIL to draw polygons on empty image but different libraries could yield different results.</p>\n<pre><code>def polygon_to_mask(polygons, shape):\n\n    \"\"\"\n    Create binary segmentation mask from polygons\n\n    Parameters\n    ----------\n    polygons (list of shape (n_polygons, n_points, 2)): Polygons\n    shape (tuple of shape (2)): Height and width of the mask\n\n    Returns\n    -------\n    segmentation_mask (numpy.ndarray of shape (height, width)): 2d segmentation mask\n    \"\"\"\n\n    segmentation_mask = Image.new('L', (shape[1], shape[0]), 0)\n\n    for polygon in polygons:\n        # Convert list of points to tuple pairs of X and Y coordinates\n        points = np.array(polygon).reshape(-1, 2)\n        points = [(point[0], point[1]) for point in points]\n\n        # Draw mask from the polygon\n        ImageDraw.Draw(segmentation_mask).polygon(points, outline=1, fill=1, width=1)\n\n    segmentation_mask = np.array(segmentation_mask).astype(np.uint8)\n\n    return segmentation_mask\n</code></pre>\n<p>This is how I convert polygons to binary masks.</p>\n<pre><code>RLE Mask Mean: 0.1489 Sum: 1340068\nPolygon Mask Mean: 0.1488 Sum 1338824\n</code></pre>\n<p>The result might be good enough but I don't want to add additional noise to labels. Can you share what was your approach so we can get identical results? <a href=\"https://www.kaggle.com/yashvrdnjain\" target=\"_blank\">@yashvrdnjain</a> </p>",
  "messages": [
    {
      "id": "1852671",
      "postDate": "07/12/2022 08:30:16",
      "content": "<p>I'm trying to replicate the mask creation process but I couldn't get exact same rle masks. I'm currently using PIL to draw polygons on empty image but different libraries could yield different results.</p>\n<pre><code>def polygon_to_mask(polygons, shape):\n\n    \"\"\"\n    Create binary segmentation mask from polygons\n\n    Parameters\n    ----------\n    polygons (list of shape (n_polygons, n_points, 2)): Polygons\n    shape (tuple of shape (2)): Height and width of the mask\n\n    Returns\n    -------\n    segmentation_mask (numpy.ndarray of shape (height, width)): 2d segmentation mask\n    \"\"\"\n\n    segmentation_mask = Image.new('L', (shape[1], shape[0]), 0)\n\n    for polygon in polygons:\n        # Convert list of points to tuple pairs of X and Y coordinates\n        points = np.array(polygon).reshape(-1, 2)\n        points = [(point[0], point[1]) for point in points]\n\n        # Draw mask from the polygon\n        ImageDraw.Draw(segmentation_mask).polygon(points, outline=1, fill=1, width=1)\n\n    segmentation_mask = np.array(segmentation_mask).astype(np.uint8)\n\n    return segmentation_mask\n</code></pre>\n<p>This is how I convert polygons to binary masks.</p>\n<pre><code>RLE Mask Mean: 0.1489 Sum: 1340068\nPolygon Mask Mean: 0.1488 Sum 1338824\n</code></pre>\n<p>The result might be good enough but I don't want to add additional noise to labels. Can you share what was your approach so we can get identical results? <a href=\"https://www.kaggle.com/yashvrdnjain\" target=\"_blank\">@yashvrdnjain</a> </p>",
      "rawMarkdown": "I'm trying to replicate the mask creation process but I couldn't get exact same rle masks. I'm currently using PIL to draw polygons on empty image but different libraries could yield different results.\n\n```\ndef polygon_to_mask(polygons, shape):\n\n    \"\"\"\n    Create binary segmentation mask from polygons\n\n    Parameters\n    ----------\n    polygons (list of shape (n_polygons, n_points, 2)): Polygons\n    shape (tuple of shape (2)): Height and width of the mask\n\n    Returns\n    -------\n    segmentation_mask (numpy.ndarray of shape (height, width)): 2d segmentation mask\n    \"\"\"\n\n    segmentation_mask = Image.new('L', (shape[1], shape[0]), 0)\n\n    for polygon in polygons:\n        # Convert list of points to tuple pairs of X and Y coordinates\n        points = np.array(polygon).reshape(-1, 2)\n        points = [(point[0], point[1]) for point in points]\n\n        # Draw mask from the polygon\n        ImageDraw.Draw(segmentation_mask).polygon(points, outline=1, fill=1, width=1)\n\n    segmentation_mask = np.array(segmentation_mask).astype(np.uint8)\n\n    return segmentation_mask\n```\n\nThis is how I convert polygons to binary masks.\n```\n\nRLE Mask Mean: 0.1489 Sum: 1340068\nPolygon Mask Mean: 0.1488 Sum 1338824\n```\n\nThe result might be good enough but I don't want to add additional noise to labels. Can you share what was your approach so we can get identical results? @yashvrdnjain",
      "votes": null
    },
    {
      "id": "1853092",
      "postDate": "07/12/2022 15:37:00",
      "content": "<p>We used <code>cv2.fillPoly</code>.</p>",
      "rawMarkdown": "We used `cv2.fillPoly`.",
      "votes": null
    },
    {
      "id": "1853108",
      "postDate": "07/12/2022 15:50:52",
      "content": "<p>Thanks. I can confirm that I got identical results.</p>",
      "rawMarkdown": "Thanks. I can confirm that I got identical results.",
      "votes": null
    }
  ],
  "comments": [
    {
      "id": 1853092,
      "author_name": "sohier",
      "author_url": "",
      "post_date": "07/12/2022 15:37:00",
      "content": "<p>We used <code>cv2.fillPoly</code>.</p>",
      "votes": null,
      "replies": [
        {
          "id": 1853108,
          "author_name": "gunesevitan",
          "author_url": "",
          "post_date": "07/12/2022 15:50:52",
          "content": "<p>Thanks. I can confirm that I got identical results.</p>",
          "votes": null,
          "replies": []
        }
      ]
    }
  ],
  "raw_markdown_by_id": {
    "1852671": "I'm trying to replicate the mask creation process but I couldn't get exact same rle masks. I'm currently using PIL to draw polygons on empty image but different libraries could yield different results.\n\n```\ndef polygon_to_mask(polygons, shape):\n\n    \"\"\"\n    Create binary segmentation mask from polygons\n\n    Parameters\n    ----------\n    polygons (list of shape (n_polygons, n_points, 2)): Polygons\n    shape (tuple of shape (2)): Height and width of the mask\n\n    Returns\n    -------\n    segmentation_mask (numpy.ndarray of shape (height, width)): 2d segmentation mask\n    \"\"\"\n\n    segmentation_mask = Image.new('L', (shape[1], shape[0]), 0)\n\n    for polygon in polygons:\n        # Convert list of points to tuple pairs of X and Y coordinates\n        points = np.array(polygon).reshape(-1, 2)\n        points = [(point[0], point[1]) for point in points]\n\n        # Draw mask from the polygon\n        ImageDraw.Draw(segmentation_mask).polygon(points, outline=1, fill=1, width=1)\n\n    segmentation_mask = np.array(segmentation_mask).astype(np.uint8)\n\n    return segmentation_mask\n```\n\nThis is how I convert polygons to binary masks.\n```\n\nRLE Mask Mean: 0.1489 Sum: 1340068\nPolygon Mask Mean: 0.1488 Sum 1338824\n```\n\nThe result might be good enough but I don't want to add additional noise to labels. Can you share what was your approach so we can get identical results? @yashvrdnjain",
    "1853092": "We used `cv2.fillPoly`.",
    "1853108": "Thanks. I can confirm that I got identical results."
  },
  "source": "meta"
}