{
  "id": 291311,
  "title": "How to get the contours of a binary mask?",
  "url": "/competitions/sartorius-cell-instance-segmentation/discussion/291311",
  "author_name": "",
  "post_date": "2021-11-28T17:12:10.664408300Z",
  "votes": 8,
  "comment_count": 2,
  "views": 0,
  "content": "<p>I'm wondering if there is a command to get contours of a binary mask. I thought plotting contour overlays makes me see the image better.</p>\n<p>I've tried searching in scipy.ndimage, scikit-image and opencv, but it's either hard to find or complex to apply. I've come up with <code>contours=mask &amp; (scipy.signal.convolve2d(mask, [[0,1,0],[1,0,1],[0,1,0]], mode=\"same\")&lt;4)</code>, but I still wonder if I've missed a simple existing command.</p>\n<p>Is there any?</p>",
  "messages": [
    {
      "id": "1598654",
      "postDate": "11/28/2021 17:12:10",
      "content": "<p>I'm wondering if there is a command to get contours of a binary mask. I thought plotting contour overlays makes me see the image better.</p>\n<p>I've tried searching in scipy.ndimage, scikit-image and opencv, but it's either hard to find or complex to apply. I've come up with <code>contours=mask &amp; (scipy.signal.convolve2d(mask, [[0,1,0],[1,0,1],[0,1,0]], mode=\"same\")&lt;4)</code>, but I still wonder if I've missed a simple existing command.</p>\n<p>Is there any?</p>",
      "rawMarkdown": "I'm wondering if there is a command to get contours of a binary mask. I thought plotting contour overlays makes me see the image better.\n\nI've tried searching in scipy.ndimage, scikit-image and opencv, but it's either hard to find or complex to apply. I've come up with `contours=mask & (scipy.signal.convolve2d(mask, [[0,1,0],[1,0,1],[0,1,0]], mode=\"same\")<4)`, but I still wonder if I've missed a simple existing command.\n\nIs there any?",
      "votes": null
    },
    {
      "id": "1598683",
      "postDate": "11/28/2021 17:36:10",
      "content": "<p>measure.find_contours()</p>",
      "rawMarkdown": "measure.find_contours()",
      "votes": null
    },
    {
      "id": "1598909",
      "postDate": "11/29/2021 01:30:53",
      "content": "<p>use my code:</p>\n<pre><code>def mask_to_inner_contour(mask):\n    mask = mask&gt;0.5\n    pad = np.lib.pad(mask, ((1, 1), (1, 1)), 'reflect')\n    contour = mask &amp; (\n            (pad[1:-1,1:-1] != pad[:-2,1:-1]) \\\n          | (pad[1:-1,1:-1] != pad[2:,1:-1])  \\\n          | (pad[1:-1,1:-1] != pad[1:-1,:-2]) \\\n          | (pad[1:-1,1:-1] != pad[1:-1,2:])\n    )\n    return contour\n\ndef mask_to_outer_contour(mask):\n    pad = np.lib.pad(mask, ((1, 1), (1, 1)), 'reflect')\n    contour = (~mask) &amp; (\n            (pad[1:-1, 1:-1] != pad[:-2, 1:-1]) \\\n            | (pad[1:-1, 1:-1] != pad[2:, 1:-1]) \\\n            | (pad[1:-1, 1:-1] != pad[1:-1, :-2]) \\\n            | (pad[1:-1, 1:-1] != pad[1:-1, 2:])\n    )\n    return contour\n\ndef draw_contour_overlay(image, mask, color=(0,0,255), thickness=1):\n    contour =  mask_to_inner_contour(mask)\n    if thickness==1:\n        image[contour] = color\n    else:\n        for y,x in np.stack(np.where(contour)).T:\n            cv2.circle(image, (x,y), thickness//2, color, lineType=cv2.LINE_4 )\n    return image\n</code></pre>",
      "rawMarkdown": "use my code:\n\n```\ndef mask_to_inner_contour(mask):\n    mask = mask>0.5\n    pad = np.lib.pad(mask, ((1, 1), (1, 1)), 'reflect')\n    contour = mask & (\n            (pad[1:-1,1:-1] != pad[:-2,1:-1]) \\\n          | (pad[1:-1,1:-1] != pad[2:,1:-1])  \\\n          | (pad[1:-1,1:-1] != pad[1:-1,:-2]) \\\n          | (pad[1:-1,1:-1] != pad[1:-1,2:])\n    )\n    return contour\n\ndef mask_to_outer_contour(mask):\n    pad = np.lib.pad(mask, ((1, 1), (1, 1)), 'reflect')\n    contour = (~mask) & (\n            (pad[1:-1, 1:-1] != pad[:-2, 1:-1]) \\\n            | (pad[1:-1, 1:-1] != pad[2:, 1:-1]) \\\n            | (pad[1:-1, 1:-1] != pad[1:-1, :-2]) \\\n            | (pad[1:-1, 1:-1] != pad[1:-1, 2:])\n    )\n    return contour\n\ndef draw_contour_overlay(image, mask, color=(0,0,255), thickness=1):\n    contour =  mask_to_inner_contour(mask)\n    if thickness==1:\n        image[contour] = color\n    else:\n        for y,x in np.stack(np.where(contour)).T:\n            cv2.circle(image, (x,y), thickness//2, color, lineType=cv2.LINE_4 )\n    return image\n\n\n```",
      "votes": null
    }
  ],
  "comments": [
    {
      "id": 1598683,
      "author_name": "atom1231",
      "author_url": "",
      "post_date": "11/28/2021 17:36:10",
      "content": "<p>measure.find_contours()</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 1598909,
      "author_name": "hengck23",
      "author_url": "",
      "post_date": "11/29/2021 01:30:53",
      "content": "<p>use my code:</p>\n<pre><code>def mask_to_inner_contour(mask):\n    mask = mask&gt;0.5\n    pad = np.lib.pad(mask, ((1, 1), (1, 1)), 'reflect')\n    contour = mask &amp; (\n            (pad[1:-1,1:-1] != pad[:-2,1:-1]) \\\n          | (pad[1:-1,1:-1] != pad[2:,1:-1])  \\\n          | (pad[1:-1,1:-1] != pad[1:-1,:-2]) \\\n          | (pad[1:-1,1:-1] != pad[1:-1,2:])\n    )\n    return contour\n\ndef mask_to_outer_contour(mask):\n    pad = np.lib.pad(mask, ((1, 1), (1, 1)), 'reflect')\n    contour = (~mask) &amp; (\n            (pad[1:-1, 1:-1] != pad[:-2, 1:-1]) \\\n            | (pad[1:-1, 1:-1] != pad[2:, 1:-1]) \\\n            | (pad[1:-1, 1:-1] != pad[1:-1, :-2]) \\\n            | (pad[1:-1, 1:-1] != pad[1:-1, 2:])\n    )\n    return contour\n\ndef draw_contour_overlay(image, mask, color=(0,0,255), thickness=1):\n    contour =  mask_to_inner_contour(mask)\n    if thickness==1:\n        image[contour] = color\n    else:\n        for y,x in np.stack(np.where(contour)).T:\n            cv2.circle(image, (x,y), thickness//2, color, lineType=cv2.LINE_4 )\n    return image\n</code></pre>",
      "votes": null,
      "replies": []
    }
  ],
  "raw_markdown_by_id": {
    "1598654": "I'm wondering if there is a command to get contours of a binary mask. I thought plotting contour overlays makes me see the image better.\n\nI've tried searching in scipy.ndimage, scikit-image and opencv, but it's either hard to find or complex to apply. I've come up with `contours=mask & (scipy.signal.convolve2d(mask, [[0,1,0],[1,0,1],[0,1,0]], mode=\"same\")<4)`, but I still wonder if I've missed a simple existing command.\n\nIs there any?",
    "1598683": "measure.find_contours()",
    "1598909": "use my code:\n\n```\ndef mask_to_inner_contour(mask):\n    mask = mask>0.5\n    pad = np.lib.pad(mask, ((1, 1), (1, 1)), 'reflect')\n    contour = mask & (\n            (pad[1:-1,1:-1] != pad[:-2,1:-1]) \\\n          | (pad[1:-1,1:-1] != pad[2:,1:-1])  \\\n          | (pad[1:-1,1:-1] != pad[1:-1,:-2]) \\\n          | (pad[1:-1,1:-1] != pad[1:-1,2:])\n    )\n    return contour\n\ndef mask_to_outer_contour(mask):\n    pad = np.lib.pad(mask, ((1, 1), (1, 1)), 'reflect')\n    contour = (~mask) & (\n            (pad[1:-1, 1:-1] != pad[:-2, 1:-1]) \\\n            | (pad[1:-1, 1:-1] != pad[2:, 1:-1]) \\\n            | (pad[1:-1, 1:-1] != pad[1:-1, :-2]) \\\n            | (pad[1:-1, 1:-1] != pad[1:-1, 2:])\n    )\n    return contour\n\ndef draw_contour_overlay(image, mask, color=(0,0,255), thickness=1):\n    contour =  mask_to_inner_contour(mask)\n    if thickness==1:\n        image[contour] = color\n    else:\n        for y,x in np.stack(np.where(contour)).T:\n            cv2.circle(image, (x,y), thickness//2, color, lineType=cv2.LINE_4 )\n    return image\n\n\n```"
  },
  "source": "meta"
}