{
  "id": 553126,
  "title": "Origin of the Grid is Actually the Center of the First Pixel (Not the Corner)",
  "url": "/competitions/czii-cryo-et-object-identification/discussion/553126",
  "author_name": "",
  "post_date": "2024-12-23T21:54:08.824653600Z",
  "votes": 37,
  "comment_count": 6,
  "views": 0,
  "content": "<p>Pretty minor point, but you can see this if you add all of the images together for a given particle.  If you do, you will see the images are slightly off center by about 1/2 a pixel.  What this means is the correct transformation to get from the x,y,z coordinate grid to the i,j,k pixel grid is actually:</p>\n<p>i = int(x/10.012 + 0.5)</p>\n<p>and not</p>\n<p>i = int(x/10.012)</p>\n<p>The latter works when the origin is the corner of the first pixel instead of the center.  (Obviously replace i and x for the other dimensions.)</p>\n<p>Here is Apo-Ferritin without the correction:</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F10704200%2F958e1f592da9e12b52487d337303748e%2FUncorrected.png?generation=1734991531448658&amp;alt=media\" alt=\"\"></p>\n<p>And here is the corrected version:</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F10704200%2Fe2bcd60a8a5b33af5e9d8639089b776a%2FCorrected.png?generation=1734991554870650&amp;alt=media\" alt=\"\"></p>\n<p>Note that the outer circle is there to prove that the issue isn't with the circle graphic.</p>",
  "messages": [
    {
      "id": "3079596",
      "postDate": "12/23/2024 21:54:08",
      "content": "<p>Pretty minor point, but you can see this if you add all of the images together for a given particle.  If you do, you will see the images are slightly off center by about 1/2 a pixel.  What this means is the correct transformation to get from the x,y,z coordinate grid to the i,j,k pixel grid is actually:</p>\n<p>i = int(x/10.012 + 0.5)</p>\n<p>and not</p>\n<p>i = int(x/10.012)</p>\n<p>The latter works when the origin is the corner of the first pixel instead of the center.  (Obviously replace i and x for the other dimensions.)</p>\n<p>Here is Apo-Ferritin without the correction:</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F10704200%2F958e1f592da9e12b52487d337303748e%2FUncorrected.png?generation=1734991531448658&amp;alt=media\" alt=\"\"></p>\n<p>And here is the corrected version:</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F10704200%2Fe2bcd60a8a5b33af5e9d8639089b776a%2FCorrected.png?generation=1734991554870650&amp;alt=media\" alt=\"\"></p>\n<p>Note that the outer circle is there to prove that the issue isn't with the circle graphic.</p>",
      "rawMarkdown": "Pretty minor point, but you can see this if you add all of the images together for a given particle.  If you do, you will see the images are slightly off center by about 1/2 a pixel.  What this means is the correct transformation to get from the x,y,z coordinate grid to the i,j,k pixel grid is actually:\n\ni = int(x/10.012 + 0.5)\n\nand not\n\ni = int(x/10.012)\n\nThe latter works when the origin is the corner of the first pixel instead of the center.  (Obviously replace i and x for the other dimensions.)\n\nHere is Apo-Ferritin without the correction:\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F10704200%2F958e1f592da9e12b52487d337303748e%2FUncorrected.png?generation=1734991531448658&alt=media)\n\nAnd here is the corrected version:\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F10704200%2Fe2bcd60a8a5b33af5e9d8639089b776a%2FCorrected.png?generation=1734991554870650&alt=media)\n\nNote that the outer circle is there to prove that the issue isn't with the circle graphic.",
      "votes": null
    },
    {
      "id": "3079618",
      "postDate": "12/23/2024 22:56:47",
      "content": "<p>Hi. What about <code>i = np.rint(x/10.012)</code>?</p>",
      "rawMarkdown": "Hi. What about `i = np.rint(x/10.012)`?",
      "votes": null
    },
    {
      "id": "3079625",
      "postDate": "12/23/2024 23:10:02",
      "content": "<p>Yeah, that should work.  Adding 0.5 and then truncating is essentially the same as rounding.  np.rint() has some weird rounding rules, but those almost certainly would have no meaningful effect.</p>",
      "rawMarkdown": "Yeah, that should work.  Adding 0.5 and then truncating is essentially the same as rounding.  np.rint() has some weird rounding rules, but those almost certainly would have no meaningful effect.",
      "votes": null
    },
    {
      "id": "3079854",
      "postDate": "12/24/2024 08:25:49",
      "content": "<p>Good catch, but it shouldn't matter if you are consistent in your training/inference approaches. The model learns such systematic errors without problems.</p>",
      "rawMarkdown": "Good catch, but it shouldn't matter if you are consistent in your training/inference approaches. The model learns such systematic errors without problems.",
      "votes": null
    },
    {
      "id": "3079867",
      "postDate": "12/24/2024 08:49:25",
      "content": "<p>It may matter for labels…well, probably not by much…but it certainly shouldn't hurt.  Honestly, it may only answer the question, why are things a little off when you add all the particles together.  😀</p>",
      "rawMarkdown": "It may matter for labels...well, probably not by much...but it certainly shouldn't hurt.  Honestly, it may only answer the question, why are things a little off when you add all the particles together.  😀",
      "votes": null
    },
    {
      "id": "3081940",
      "postDate": "12/27/2024 12:44:28",
      "content": "<p>Such errors will no longer be systematic in case of rotation or flip augmentations. So IMO such details may matter especially considering the variability of labeling and that the maximal distance to GT for prediction to be correct is 3-7 pixels depending on particle type.<br>\nIn my case, this is also supported by empirical results in 4 out of 4 comparisons.</p>",
      "rawMarkdown": "Such errors will no longer be systematic in case of rotation or flip augmentations. So IMO such details may matter especially considering the variability of labeling and that the maximal distance to GT for prediction to be correct is 3-7 pixels depending on particle type.\nIn my case, this is also supported by empirical results in 4 out of 4 comparisons.",
      "votes": null
    },
    {
      "id": "3086343",
      "postDate": "01/02/2025 08:29:13",
      "content": "<p><a href=\"https://www.kaggle.com/bohdanmahometa\" target=\"_blank\">@bohdanmahometa</a> <br>\nDo you see a difference between masks generated with voxel size 10 and 10.012? I don't see any difference as masks are generated in fp64 and then thresholded to 0-1. This allows for subpixel mask accuracy. I checked for masks created both ways and couldn't find any difference between them. But I didn't dig too deply into it.</p>",
      "rawMarkdown": "bohdanmahometa \nDo you see a difference between masks generated with voxel size 10 and 10.012? I don't see any difference as masks are generated in fp64 and then thresholded to 0-1. This allows for subpixel mask accuracy. I checked for masks created both ways and couldn't find any difference between them. But I didn't dig too deply into it.",
      "votes": null
    }
  ],
  "comments": [
    {
      "id": 3079618,
      "author_name": "sacuscreed",
      "author_url": "",
      "post_date": "12/23/2024 22:56:47",
      "content": "<p>Hi. What about <code>i = np.rint(x/10.012)</code>?</p>",
      "votes": null,
      "replies": [
        {
          "id": 3079625,
          "author_name": "davidlist",
          "author_url": "",
          "post_date": "12/23/2024 23:10:02",
          "content": "<p>Yeah, that should work.  Adding 0.5 and then truncating is essentially the same as rounding.  np.rint() has some weird rounding rules, but those almost certainly would have no meaningful effect.</p>",
          "votes": null,
          "replies": []
        }
      ]
    },
    {
      "id": 3079854,
      "author_name": "sakvaua",
      "author_url": "",
      "post_date": "12/24/2024 08:25:49",
      "content": "<p>Good catch, but it shouldn't matter if you are consistent in your training/inference approaches. The model learns such systematic errors without problems.</p>",
      "votes": null,
      "replies": [
        {
          "id": 3079867,
          "author_name": "davidlist",
          "author_url": "",
          "post_date": "12/24/2024 08:49:25",
          "content": "<p>It may matter for labels…well, probably not by much…but it certainly shouldn't hurt.  Honestly, it may only answer the question, why are things a little off when you add all the particles together.  😀</p>",
          "votes": null,
          "replies": []
        },
        {
          "id": 3081940,
          "author_name": "bohdanmahometa",
          "author_url": "",
          "post_date": "12/27/2024 12:44:28",
          "content": "<p>Such errors will no longer be systematic in case of rotation or flip augmentations. So IMO such details may matter especially considering the variability of labeling and that the maximal distance to GT for prediction to be correct is 3-7 pixels depending on particle type.<br>\nIn my case, this is also supported by empirical results in 4 out of 4 comparisons.</p>",
          "votes": null,
          "replies": [
            {
              "id": 3086343,
              "author_name": "sakvaua",
              "author_url": "",
              "post_date": "01/02/2025 08:29:13",
              "content": "<p><a href=\"https://www.kaggle.com/bohdanmahometa\" target=\"_blank\">@bohdanmahometa</a> <br>\nDo you see a difference between masks generated with voxel size 10 and 10.012? I don't see any difference as masks are generated in fp64 and then thresholded to 0-1. This allows for subpixel mask accuracy. I checked for masks created both ways and couldn't find any difference between them. But I didn't dig too deply into it.</p>",
              "votes": null,
              "replies": []
            }
          ]
        }
      ]
    }
  ],
  "raw_markdown_by_id": {
    "3079596": "Pretty minor point, but you can see this if you add all of the images together for a given particle.  If you do, you will see the images are slightly off center by about 1/2 a pixel.  What this means is the correct transformation to get from the x,y,z coordinate grid to the i,j,k pixel grid is actually:\n\ni = int(x/10.012 + 0.5)\n\nand not\n\ni = int(x/10.012)\n\nThe latter works when the origin is the corner of the first pixel instead of the center.  (Obviously replace i and x for the other dimensions.)\n\nHere is Apo-Ferritin without the correction:\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F10704200%2F958e1f592da9e12b52487d337303748e%2FUncorrected.png?generation=1734991531448658&alt=media)\n\nAnd here is the corrected version:\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F10704200%2Fe2bcd60a8a5b33af5e9d8639089b776a%2FCorrected.png?generation=1734991554870650&alt=media)\n\nNote that the outer circle is there to prove that the issue isn't with the circle graphic.",
    "3079618": "Hi. What about `i = np.rint(x/10.012)`?",
    "3079625": "Yeah, that should work.  Adding 0.5 and then truncating is essentially the same as rounding.  np.rint() has some weird rounding rules, but those almost certainly would have no meaningful effect.",
    "3079854": "Good catch, but it shouldn't matter if you are consistent in your training/inference approaches. The model learns such systematic errors without problems.",
    "3079867": "It may matter for labels...well, probably not by much...but it certainly shouldn't hurt.  Honestly, it may only answer the question, why are things a little off when you add all the particles together.  😀",
    "3081940": "Such errors will no longer be systematic in case of rotation or flip augmentations. So IMO such details may matter especially considering the variability of labeling and that the maximal distance to GT for prediction to be correct is 3-7 pixels depending on particle type.\nIn my case, this is also supported by empirical results in 4 out of 4 comparisons.",
    "3086343": "bohdanmahometa \nDo you see a difference between masks generated with voxel size 10 and 10.012? I don't see any difference as masks are generated in fp64 and then thresholded to 0-1. This allows for subpixel mask accuracy. I checked for masks created both ways and couldn't find any difference between them. But I didn't dig too deply into it."
  },
  "source": "meta"
}