{
  "id": 49674,
  "title": "buggy rle_encoding method?",
  "url": "/competitions/data-science-bowl-2018/discussion/49674",
  "author_name": "",
  "post_date": "2018-02-14T04:41:57.501765700Z",
  "votes": null,
  "comment_count": 8,
  "views": 0,
  "content": "<p>Not sure if this has been pointed out already but:</p>\n\n<p>The popular <code>rle_encoding</code> method:</p>\n\n<pre><code>def rle_encoding(x):\n    dots = np.where(x.T.flatten() == 1)[0]\n    run_lengths = []\n    prev = -2\n    for b in dots:\n        if (b &gt; prev+1): run_lengths.extend((int(b) + 1, 0))\n        run_lengths[-1] += 1\n        prev = b\n    return run_lengths\n</code></pre>\n\n<p>But after flattening it has the effect of \"toroidally\" wrapping the columns together. For example:</p>\n\n<pre><code>z = np.array([[1,0,1],[1,0,1]]).T\nrle_encoding(z)\n[1, 1, 3, 2, 6, 1]\n</code></pre>\n\n<p>Which is not right. The 3rd pixel should not wrap to the next column.</p>",
  "messages": [
    {
      "id": "282503",
      "postDate": "02/14/2018 04:41:57",
      "content": "<p>Not sure if this has been pointed out already but:</p>\n\n<p>The popular <code>rle_encoding</code> method:</p>\n\n<pre><code>def rle_encoding(x):\n    dots = np.where(x.T.flatten() == 1)[0]\n    run_lengths = []\n    prev = -2\n    for b in dots:\n        if (b &gt; prev+1): run_lengths.extend((int(b) + 1, 0))\n        run_lengths[-1] += 1\n        prev = b\n    return run_lengths\n</code></pre>\n\n<p>But after flattening it has the effect of \"toroidally\" wrapping the columns together. For example:</p>\n\n<pre><code>z = np.array([[1,0,1],[1,0,1]]).T\nrle_encoding(z)\n[1, 1, 3, 2, 6, 1]\n</code></pre>\n\n<p>Which is not right. The 3rd pixel should not wrap to the next column.</p>",
      "rawMarkdown": "Not sure if this has been pointed out already but:\n\nThe popular `rle_encoding` method:\n\n\n    def rle_encoding(x):\n        dots = np.where(x.T.flatten() == 1)[0]\n        run_lengths = []\n        prev = -2\n        for b in dots:\n            if (b &gt; prev+1): run_lengths.extend((int(b) + 1, 0))\n            run_lengths[-1] += 1\n            prev = b\n        return run_lengths\n\nBut after flattening it has the effect of \"toroidally\" wrapping the columns together. For example:\n\n    z = np.array([[1,0,1],[1,0,1]]).T\n    rle_encoding(z)\n    [1, 1, 3, 2, 6, 1]\n\n\nWhich is not right. The 3rd pixel should not wrap to the next column.",
      "votes": null
    },
    {
      "id": "282607",
      "postDate": "02/14/2018 08:45:47",
      "content": "<p>I am not sure if it answers your doubts, but it states that:</p>\n\n<blockquote>\n  <p>The competition format requires a space delimited list of pairs. For\n  example, '1 3 10 5' implies pixels 1,2,3,10,11,12,13,14 are to be\n  included in the mask. <strong>The pixels are one-indexed and numbered from top\n  to bottom, then left to right: 1 is pixel (1,1), 2 is pixel (2,1),\n  etc.</strong></p>\n</blockquote>\n\n<p>It means that pixels should be flattened. </p>",
      "rawMarkdown": "I am not sure if it answers your doubts, but it states that:\n\n&gt; The competition format requires a space delimited list of pairs. For\n&gt; example, '1 3 10 5' implies pixels 1,2,3,10,11,12,13,14 are to be\n&gt; included in the mask. **The pixels are one-indexed and numbered from top\n&gt; to bottom, then left to right: 1 is pixel (1,1), 2 is pixel (2,1),\n&gt; etc.**\n\nIt means that pixels should be flattened.",
      "votes": null
    },
    {
      "id": "282627",
      "postDate": "02/14/2018 09:29:26",
      "content": "<p>Hi thanks for taking the time to reply. The encoding scheme is OK, but there's a bug here in this particular implementation that ignores the boundaries (which are a real thing that ought to be taken into account).</p>\n\n<p>Imagine two nuclei at the top and bottom of an image, this implementation would mix their RLEs.</p>",
      "rawMarkdown": "Hi thanks for taking the time to reply. The encoding scheme is OK, but there's a bug here in this particular implementation that ignores the boundaries (which are a real thing that ought to be taken into account).\n\nImagine two nuclei at the top and bottom of an image, this implementation would mix their RLEs.",
      "votes": null
    },
    {
      "id": "282639",
      "postDate": "02/14/2018 09:50:14",
      "content": "<p>Hi @rijsttafel, not sure if I get your question correctly, but following might be relevant</p>\n\n<p>As per \"evaluation\" section: </p>\n\n<p>&gt; The metric checks that the pairs are sorted, positive, and the decoded pixel values are not duplicated. It also checks that no two predicted masks for the same image are overlapping.</p>\n\n<p>So, even if the two nuclei are overlapping, we need to have two masks non-overlapping, i.e. the overlapping region needs to be assigned to one or the other nucleus. Actually, the two masks should even touch each other (i.e. no pixel in mask m1 should have a common edge with another pixel in mask m2)</p>",
      "rawMarkdown": "Hi @rijsttafel, not sure if I get your question correctly, but following might be relevant\n\nAs per \"evaluation\" section: \n\n&gt; The metric checks that the pairs are sorted, positive, and the decoded pixel values are not duplicated. It also checks that no two predicted masks for the same image are overlapping.\n\nSo, even if the two nuclei are overlapping, we need to have two masks non-overlapping, i.e. the overlapping region needs to be assigned to one or the other nucleus. Actually, the two masks should even touch each other (i.e. no pixel in mask m1 should have a common edge with another pixel in mask m2)",
      "votes": null
    },
    {
      "id": "282645",
      "postDate": "02/14/2018 10:09:56",
      "content": "<p>Haha, thanks found my bug! Method is safe so long as it gets a single mask at a time; did something silly and ended up with all masks inside a single image. :)</p>",
      "rawMarkdown": "Haha, thanks found my bug! Method is safe so long as it gets a single mask at a time; did something silly and ended up with all masks inside a single image. :)",
      "votes": null
    },
    {
      "id": "282821",
      "postDate": "02/14/2018 16:42:04",
      "content": "<p>Just one clarification on what you've said, Vivek - two masks CAN touch each other! Just not overlap.</p>",
      "rawMarkdown": "Just one clarification on what you've said, Vivek - two masks CAN touch each other! Just not overlap.",
      "votes": null
    },
    {
      "id": "282824",
      "postDate": "02/14/2018 16:49:42",
      "content": "<p>Thanks for the clarification, Anne. In the given training examples, I could not spot masks which touch each  other (there is always minimum one pixel gap), so I just assumed that two masks cannot touch each other. I'll change my post processing to this effect and see if that helps.</p>",
      "rawMarkdown": "Thanks for the clarification, Anne. In the given training examples, I could not spot masks which touch each  other (there is always minimum one pixel gap), so I just assumed that two masks cannot touch each other. I'll change my post processing to this effect and see if that helps.",
      "votes": null
    },
    {
      "id": "282889",
      "postDate": "02/14/2018 18:29:08",
      "content": "<p>Whoa, that would be pretty surprising if annotations always have a one pixel gap. Can you verify that is really true in your hands? Can you show examples?</p>",
      "rawMarkdown": "Whoa, that would be pretty surprising if annotations always have a one pixel gap. Can you verify that is really true in your hands? Can you show examples?",
      "votes": null
    },
    {
      "id": "282924",
      "postDate": "02/14/2018 19:33:13",
      "content": "<p>I was curious, so I checked the training images and found a few examples where there’s no gap. However, Vivek is correct that a (surprising) number of objects are separated by one pixel (and the annotations look correct). </p>\n\n<p>I would check your model Vivek. 🤔</p>\n\n<p>You should also consider mildly dilating your masks. I experimented with this for my submission.</p>",
      "rawMarkdown": "I was curious, so I checked the training images and found a few examples where there’s no gap. However, Vivek is correct that a (surprising) number of objects are separated by one pixel (and the annotations look correct). \n\nI would check your model Vivek. 🤔\n\nYou should also consider mildly dilating your masks. I experimented with this for my submission.",
      "votes": null
    }
  ],
  "comments": [
    {
      "id": 282607,
      "author_name": "lukpawlucz",
      "author_url": "",
      "post_date": "02/14/2018 08:45:47",
      "content": "<p>I am not sure if it answers your doubts, but it states that:</p>\n\n<blockquote>\n  <p>The competition format requires a space delimited list of pairs. For\n  example, '1 3 10 5' implies pixels 1,2,3,10,11,12,13,14 are to be\n  included in the mask. <strong>The pixels are one-indexed and numbered from top\n  to bottom, then left to right: 1 is pixel (1,1), 2 is pixel (2,1),\n  etc.</strong></p>\n</blockquote>\n\n<p>It means that pixels should be flattened. </p>",
      "votes": null,
      "replies": [
        {
          "id": 282627,
          "author_name": "spnrpa",
          "author_url": "",
          "post_date": "02/14/2018 09:29:26",
          "content": "<p>Hi thanks for taking the time to reply. The encoding scheme is OK, but there's a bug here in this particular implementation that ignores the boundaries (which are a real thing that ought to be taken into account).</p>\n\n<p>Imagine two nuclei at the top and bottom of an image, this implementation would mix their RLEs.</p>",
          "votes": null,
          "replies": []
        },
        {
          "id": 282639,
          "author_name": "thevivekpandey",
          "author_url": "",
          "post_date": "02/14/2018 09:50:14",
          "content": "<p>Hi @rijsttafel, not sure if I get your question correctly, but following might be relevant</p>\n\n<p>As per \"evaluation\" section: </p>\n\n<p>&gt; The metric checks that the pairs are sorted, positive, and the decoded pixel values are not duplicated. It also checks that no two predicted masks for the same image are overlapping.</p>\n\n<p>So, even if the two nuclei are overlapping, we need to have two masks non-overlapping, i.e. the overlapping region needs to be assigned to one or the other nucleus. Actually, the two masks should even touch each other (i.e. no pixel in mask m1 should have a common edge with another pixel in mask m2)</p>",
          "votes": null,
          "replies": []
        },
        {
          "id": 282645,
          "author_name": "spnrpa",
          "author_url": "",
          "post_date": "02/14/2018 10:09:56",
          "content": "<p>Haha, thanks found my bug! Method is safe so long as it gets a single mask at a time; did something silly and ended up with all masks inside a single image. :)</p>",
          "votes": null,
          "replies": []
        },
        {
          "id": 282821,
          "author_name": "drannecarpenter",
          "author_url": "",
          "post_date": "02/14/2018 16:42:04",
          "content": "<p>Just one clarification on what you've said, Vivek - two masks CAN touch each other! Just not overlap.</p>",
          "votes": null,
          "replies": []
        },
        {
          "id": 282824,
          "author_name": "thevivekpandey",
          "author_url": "",
          "post_date": "02/14/2018 16:49:42",
          "content": "<p>Thanks for the clarification, Anne. In the given training examples, I could not spot masks which touch each  other (there is always minimum one pixel gap), so I just assumed that two masks cannot touch each other. I'll change my post processing to this effect and see if that helps.</p>",
          "votes": null,
          "replies": []
        },
        {
          "id": 282889,
          "author_name": "drannecarpenter",
          "author_url": "",
          "post_date": "02/14/2018 18:29:08",
          "content": "<p>Whoa, that would be pretty surprising if annotations always have a one pixel gap. Can you verify that is really true in your hands? Can you show examples?</p>",
          "votes": null,
          "replies": []
        },
        {
          "id": 282924,
          "author_name": "agoodman",
          "author_url": "",
          "post_date": "02/14/2018 19:33:13",
          "content": "<p>I was curious, so I checked the training images and found a few examples where there’s no gap. However, Vivek is correct that a (surprising) number of objects are separated by one pixel (and the annotations look correct). </p>\n\n<p>I would check your model Vivek. 🤔</p>\n\n<p>You should also consider mildly dilating your masks. I experimented with this for my submission.</p>",
          "votes": null,
          "replies": []
        }
      ]
    }
  ],
  "raw_markdown_by_id": {
    "282503": "Not sure if this has been pointed out already but:\n\nThe popular `rle_encoding` method:\n\n\n    def rle_encoding(x):\n        dots = np.where(x.T.flatten() == 1)[0]\n        run_lengths = []\n        prev = -2\n        for b in dots:\n            if (b &gt; prev+1): run_lengths.extend((int(b) + 1, 0))\n            run_lengths[-1] += 1\n            prev = b\n        return run_lengths\n\nBut after flattening it has the effect of \"toroidally\" wrapping the columns together. For example:\n\n    z = np.array([[1,0,1],[1,0,1]]).T\n    rle_encoding(z)\n    [1, 1, 3, 2, 6, 1]\n\n\nWhich is not right. The 3rd pixel should not wrap to the next column.",
    "282607": "I am not sure if it answers your doubts, but it states that:\n\n&gt; The competition format requires a space delimited list of pairs. For\n&gt; example, '1 3 10 5' implies pixels 1,2,3,10,11,12,13,14 are to be\n&gt; included in the mask. **The pixels are one-indexed and numbered from top\n&gt; to bottom, then left to right: 1 is pixel (1,1), 2 is pixel (2,1),\n&gt; etc.**\n\nIt means that pixels should be flattened.",
    "282627": "Hi thanks for taking the time to reply. The encoding scheme is OK, but there's a bug here in this particular implementation that ignores the boundaries (which are a real thing that ought to be taken into account).\n\nImagine two nuclei at the top and bottom of an image, this implementation would mix their RLEs.",
    "282639": "Hi @rijsttafel, not sure if I get your question correctly, but following might be relevant\n\nAs per \"evaluation\" section: \n\n&gt; The metric checks that the pairs are sorted, positive, and the decoded pixel values are not duplicated. It also checks that no two predicted masks for the same image are overlapping.\n\nSo, even if the two nuclei are overlapping, we need to have two masks non-overlapping, i.e. the overlapping region needs to be assigned to one or the other nucleus. Actually, the two masks should even touch each other (i.e. no pixel in mask m1 should have a common edge with another pixel in mask m2)",
    "282645": "Haha, thanks found my bug! Method is safe so long as it gets a single mask at a time; did something silly and ended up with all masks inside a single image. :)",
    "282821": "Just one clarification on what you've said, Vivek - two masks CAN touch each other! Just not overlap.",
    "282824": "Thanks for the clarification, Anne. In the given training examples, I could not spot masks which touch each  other (there is always minimum one pixel gap), so I just assumed that two masks cannot touch each other. I'll change my post processing to this effect and see if that helps.",
    "282889": "Whoa, that would be pretty surprising if annotations always have a one pixel gap. Can you verify that is really true in your hands? Can you show examples?",
    "282924": "I was curious, so I checked the training images and found a few examples where there’s no gap. However, Vivek is correct that a (surprising) number of objects are separated by one pixel (and the annotations look correct). \n\nI would check your model Vivek. 🤔\n\nYou should also consider mildly dilating your masks. I experimented with this for my submission."
  },
  "source": "meta"
}