{
  "id": 521135,
  "title": "Do we need to resample the pixels to isomorphic resolution?",
  "url": "/competitions/rsna-2024-lumbar-spine-degenerative-classification/discussion/521135",
  "author_name": "",
  "post_date": "2024-07-19T02:34:39.252144900Z",
  "votes": 8,
  "comment_count": 9,
  "views": 0,
  "content": "<p>I was reading this tutorial about MR images, <a href=\"https://www.kaggle.com/code/gzuidhof/full-preprocessing-tutorial\" target=\"_blank\">https://www.kaggle.com/code/gzuidhof/full-preprocessing-tutorial</a>.</p>\n<p>I found that a step that it recommend doing to resampling the dcm images to 1mm size in real world. I haven't tried this on my experient yet. But I assume it help models' performance. Or simply the change is insignificant?</p>\n<blockquote>\n  <p>Resampling<br>\n  A scan may have a pixel spacing of [2.5, 0.5, 0.5], which means that the distance between slices is 2.5 millimeters. For a different scan this may be [1.5, 0.725, 0.725], this can be problematic for automatic analysis (e.g. using ConvNets)!<br>\n  A common method of dealing with this is resampling the full dataset to a certain isotropic resolution. If we choose to resample everything to 1mm1mm1mm pixels we can use 3D convnets without worrying about learning zoom/slice thickness invariance.<br>\n  Whilst this may seem like a very simple step, it has quite some edge cases due to rounding. Also, it takes quite a while.<br>\n  Below code worked well for us (and deals with the edge cases):</p>\n</blockquote>\n<pre><code> ():\n    \n    spacing = np.array([scan[].SliceThickness] + scan[].PixelSpacing, dtype=np.float32)\n\n    resize_factor = spacing / new_spacing\n    new_real_shape = image.shape * resize_factor\n    new_shape = np.(new_real_shape)\n    real_resize_factor = new_shape / image.shape\n    new_spacing = spacing / real_resize_factor\n\n    image = scipy.ndimage.interpolation.zoom(image, real_resize_factor, mode=)\n\n     image, new_spacing\n</code></pre>",
  "messages": [
    {
      "id": "2928196",
      "postDate": "07/19/2024 02:34:39",
      "content": "<p>I was reading this tutorial about MR images, <a href=\"https://www.kaggle.com/code/gzuidhof/full-preprocessing-tutorial\" target=\"_blank\">https://www.kaggle.com/code/gzuidhof/full-preprocessing-tutorial</a>.</p>\n<p>I found that a step that it recommend doing to resampling the dcm images to 1mm size in real world. I haven't tried this on my experient yet. But I assume it help models' performance. Or simply the change is insignificant?</p>\n<blockquote>\n  <p>Resampling<br>\n  A scan may have a pixel spacing of [2.5, 0.5, 0.5], which means that the distance between slices is 2.5 millimeters. For a different scan this may be [1.5, 0.725, 0.725], this can be problematic for automatic analysis (e.g. using ConvNets)!<br>\n  A common method of dealing with this is resampling the full dataset to a certain isotropic resolution. If we choose to resample everything to 1mm1mm1mm pixels we can use 3D convnets without worrying about learning zoom/slice thickness invariance.<br>\n  Whilst this may seem like a very simple step, it has quite some edge cases due to rounding. Also, it takes quite a while.<br>\n  Below code worked well for us (and deals with the edge cases):</p>\n</blockquote>\n<pre><code> ():\n    \n    spacing = np.array([scan[].SliceThickness] + scan[].PixelSpacing, dtype=np.float32)\n\n    resize_factor = spacing / new_spacing\n    new_real_shape = image.shape * resize_factor\n    new_shape = np.(new_real_shape)\n    real_resize_factor = new_shape / image.shape\n    new_spacing = spacing / real_resize_factor\n\n    image = scipy.ndimage.interpolation.zoom(image, real_resize_factor, mode=)\n\n     image, new_spacing\n</code></pre>",
      "rawMarkdown": "I was reading this tutorial about MR images, https://www.kaggle.com/code/gzuidhof/full-preprocessing-tutorial.\n\nI found that a step that it recommend doing to resampling the dcm images to 1mm size in real world. I haven't tried this on my experient yet. But I assume it help models' performance. Or simply the change is insignificant?\n\n>Resampling\nA scan may have a pixel spacing of [2.5, 0.5, 0.5], which means that the distance between slices is 2.5 millimeters. For a different scan this may be [1.5, 0.725, 0.725], this can be problematic for automatic analysis (e.g. using ConvNets)!\nA common method of dealing with this is resampling the full dataset to a certain isotropic resolution. If we choose to resample everything to 1mm1mm1mm pixels we can use 3D convnets without worrying about learning zoom/slice thickness invariance.\nWhilst this may seem like a very simple step, it has quite some edge cases due to rounding. Also, it takes quite a while.\nBelow code worked well for us (and deals with the edge cases):\n\n```python\ndef resample(image, scan, new_spacing=[1,1,1]):\n    # Determine current pixel spacing\n    spacing = np.array([scan[0].SliceThickness] + scan[0].PixelSpacing, dtype=np.float32)\n\n    resize_factor = spacing / new_spacing\n    new_real_shape = image.shape * resize_factor\n    new_shape = np.round(new_real_shape)\n    real_resize_factor = new_shape / image.shape\n    new_spacing = spacing / real_resize_factor\n    \n    image = scipy.ndimage.interpolation.zoom(image, real_resize_factor, mode='nearest')\n    \n    return image, new_spacing\n```",
      "votes": null
    },
    {
      "id": "2928598",
      "postDate": "07/19/2024 12:08:02",
      "content": "<p>\". Also, it takes quite a while.\"</p>\n<p>another way to resample is to use pytorch F interpolation for batch size = N,C,D,H,W</p>",
      "rawMarkdown": "\". Also, it takes quite a while.\"\n\nanother way to resample is to use pytorch F interpolation for batch size = N,C,D,H,W",
      "votes": null
    },
    {
      "id": "2929129",
      "postDate": "07/19/2024 21:03:05",
      "content": "<p>This will most likely hurt and not help because the slice thickness is much greater than the pixel spacing. </p>\n<p>For example, <code>series_id</code> 108597120 has a pixel spacing of 0.25 x 0.25 mm and a slice thickness of 3.5 mm, meaning each voxel is 0.25 x 0.25 x 3.5 mm. If you resample this to 1 x 1 x 1 mm, you are downsampling the in-plane resolution by 4 and upsampling the out-of-plane resolution by 3.5 (which is only adding redundant information). </p>",
      "rawMarkdown": "This will most likely hurt and not help because the slice thickness is much greater than the pixel spacing. \n\nFor example, `series_id` 108597120 has a pixel spacing of 0.25 x 0.25 mm and a slice thickness of 3.5 mm, meaning each voxel is 0.25 x 0.25 x 3.5 mm. If you resample this to 1 x 1 x 1 mm, you are downsampling the in-plane resolution by 4 and upsampling the out-of-plane resolution by 3.5 (which is only adding redundant information).",
      "votes": null
    },
    {
      "id": "2929441",
      "postDate": "07/20/2024 06:11:45",
      "content": "<p>That is true, but what if we chose the median spacing of all the training image series? That would alleviate some of the downsampling  and upsampling issues mentioned above.<br>\nIf I understand correctly, <a href=\"https://github.com/MIC-DKFZ/nnUNet\" target=\"_blank\">nnU-Net</a>, does something similar to this.</p>",
      "rawMarkdown": "That is true, but what if we chose the median spacing of all the training image series? That would alleviate some of the downsampling  and upsampling issues mentioned above.\nIf I understand correctly, [nnU-Net](https://github.com/MIC-DKFZ/nnUNet), does something similar to this.",
      "votes": null
    },
    {
      "id": "2929713",
      "postDate": "07/20/2024 09:22:32",
      "content": "<p>Can you explain please, how did you figured out a pixel spacing and a slice thickness?</p>",
      "rawMarkdown": "Can you explain please, how did you figured out a pixel spacing and a slice thickness?",
      "votes": null
    },
    {
      "id": "2929723",
      "postDate": "07/20/2024 09:36:45",
      "content": "<p>It's in the dicom metadata</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F15806223%2Ffd9e90f351b3f00e8e653527f7b31df0%2FScreenshot%202024-07-20%20at%2017.36.32.png?generation=1721468204017089&amp;alt=media\" alt=\"\"></p>",
      "rawMarkdown": "It's in the dicom metadata\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F15806223%2Ffd9e90f351b3f00e8e653527f7b31df0%2FScreenshot%202024-07-20%20at%2017.36.32.png?generation=1721468204017089&alt=media)",
      "votes": null
    },
    {
      "id": "2929730",
      "postDate": "07/20/2024 09:52:40",
      "content": "<p>thank you!</p>",
      "rawMarkdown": "thank you!",
      "votes": null
    },
    {
      "id": "2931847",
      "postDate": "07/22/2024 11:49:49",
      "content": "<p>I think resampling all studies to a consistent spacing (e.g., 0.3 x 0.3 x 4 mm) is reasonable. But I still don't think isotropic resampling is the best idea. </p>",
      "rawMarkdown": "I think resampling all studies to a consistent spacing (e.g., 0.3 x 0.3 x 4 mm) is reasonable. But I still don't think isotropic resampling is the best idea.",
      "votes": null
    },
    {
      "id": "2937891",
      "postDate": "07/27/2024 14:45:35",
      "content": "<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F113660%2F3df64bc42e897cd0c8f25fc91778a9ad%2FSelection_198.png?generation=1722091481735297&amp;alt=media\" alt=\"\"></p>\n<p>i note that some axial scans are not cuboid. It could be a parallelepiped.<br>\n(notice that BOTH y and z are changing in the position array)</p>",
      "rawMarkdown": "![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F113660%2F3df64bc42e897cd0c8f25fc91778a9ad%2FSelection_198.png?generation=1722091481735297&alt=media)\n\ni note that some axial scans are not cuboid. It could be a parallelepiped.\n(notice that BOTH y and z are changing in the position array)",
      "votes": null
    },
    {
      "id": "2938014",
      "postDate": "07/27/2024 15:59:28",
      "content": "<p>It says 18x640x640 but is trully that volume? Because there is some axial with double shape along the slices.</p>",
      "rawMarkdown": "It says 18x640x640 but is trully that volume? Because there is some axial with double shape along the slices.",
      "votes": null
    }
  ],
  "comments": [
    {
      "id": 2928598,
      "author_name": "hengck23",
      "author_url": "",
      "post_date": "07/19/2024 12:08:02",
      "content": "<p>\". Also, it takes quite a while.\"</p>\n<p>another way to resample is to use pytorch F interpolation for batch size = N,C,D,H,W</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 2929129,
      "author_name": "vaillant",
      "author_url": "",
      "post_date": "07/19/2024 21:03:05",
      "content": "<p>This will most likely hurt and not help because the slice thickness is much greater than the pixel spacing. </p>\n<p>For example, <code>series_id</code> 108597120 has a pixel spacing of 0.25 x 0.25 mm and a slice thickness of 3.5 mm, meaning each voxel is 0.25 x 0.25 x 3.5 mm. If you resample this to 1 x 1 x 1 mm, you are downsampling the in-plane resolution by 4 and upsampling the out-of-plane resolution by 3.5 (which is only adding redundant information). </p>",
      "votes": null,
      "replies": [
        {
          "id": 2929441,
          "author_name": "coderrkj",
          "author_url": "",
          "post_date": "07/20/2024 06:11:45",
          "content": "<p>That is true, but what if we chose the median spacing of all the training image series? That would alleviate some of the downsampling  and upsampling issues mentioned above.<br>\nIf I understand correctly, <a href=\"https://github.com/MIC-DKFZ/nnUNet\" target=\"_blank\">nnU-Net</a>, does something similar to this.</p>",
          "votes": null,
          "replies": [
            {
              "id": 2931847,
              "author_name": "vaillant",
              "author_url": "",
              "post_date": "07/22/2024 11:49:49",
              "content": "<p>I think resampling all studies to a consistent spacing (e.g., 0.3 x 0.3 x 4 mm) is reasonable. But I still don't think isotropic resampling is the best idea. </p>",
              "votes": null,
              "replies": []
            }
          ]
        },
        {
          "id": 2929713,
          "author_name": "samson8",
          "author_url": "",
          "post_date": "07/20/2024 09:22:32",
          "content": "<p>Can you explain please, how did you figured out a pixel spacing and a slice thickness?</p>",
          "votes": null,
          "replies": [
            {
              "id": 2929723,
              "author_name": "llleeeoooh",
              "author_url": "",
              "post_date": "07/20/2024 09:36:45",
              "content": "<p>It's in the dicom metadata</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F15806223%2Ffd9e90f351b3f00e8e653527f7b31df0%2FScreenshot%202024-07-20%20at%2017.36.32.png?generation=1721468204017089&amp;alt=media\" alt=\"\"></p>",
              "votes": null,
              "replies": [
                {
                  "id": 2929730,
                  "author_name": "samson8",
                  "author_url": "",
                  "post_date": "07/20/2024 09:52:40",
                  "content": "<p>thank you!</p>",
                  "votes": null,
                  "replies": []
                }
              ]
            }
          ]
        }
      ]
    },
    {
      "id": 2937891,
      "author_name": "hengck23",
      "author_url": "",
      "post_date": "07/27/2024 14:45:35",
      "content": "<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F113660%2F3df64bc42e897cd0c8f25fc91778a9ad%2FSelection_198.png?generation=1722091481735297&amp;alt=media\" alt=\"\"></p>\n<p>i note that some axial scans are not cuboid. It could be a parallelepiped.<br>\n(notice that BOTH y and z are changing in the position array)</p>",
      "votes": null,
      "replies": [
        {
          "id": 2938014,
          "author_name": "sacuscreed",
          "author_url": "",
          "post_date": "07/27/2024 15:59:28",
          "content": "<p>It says 18x640x640 but is trully that volume? Because there is some axial with double shape along the slices.</p>",
          "votes": null,
          "replies": []
        }
      ]
    }
  ],
  "raw_markdown_by_id": {
    "2928196": "I was reading this tutorial about MR images, https://www.kaggle.com/code/gzuidhof/full-preprocessing-tutorial.\n\nI found that a step that it recommend doing to resampling the dcm images to 1mm size in real world. I haven't tried this on my experient yet. But I assume it help models' performance. Or simply the change is insignificant?\n\n>Resampling\nA scan may have a pixel spacing of [2.5, 0.5, 0.5], which means that the distance between slices is 2.5 millimeters. For a different scan this may be [1.5, 0.725, 0.725], this can be problematic for automatic analysis (e.g. using ConvNets)!\nA common method of dealing with this is resampling the full dataset to a certain isotropic resolution. If we choose to resample everything to 1mm1mm1mm pixels we can use 3D convnets without worrying about learning zoom/slice thickness invariance.\nWhilst this may seem like a very simple step, it has quite some edge cases due to rounding. Also, it takes quite a while.\nBelow code worked well for us (and deals with the edge cases):\n\n```python\ndef resample(image, scan, new_spacing=[1,1,1]):\n    # Determine current pixel spacing\n    spacing = np.array([scan[0].SliceThickness] + scan[0].PixelSpacing, dtype=np.float32)\n\n    resize_factor = spacing / new_spacing\n    new_real_shape = image.shape * resize_factor\n    new_shape = np.round(new_real_shape)\n    real_resize_factor = new_shape / image.shape\n    new_spacing = spacing / real_resize_factor\n    \n    image = scipy.ndimage.interpolation.zoom(image, real_resize_factor, mode='nearest')\n    \n    return image, new_spacing\n```",
    "2928598": "\". Also, it takes quite a while.\"\n\nanother way to resample is to use pytorch F interpolation for batch size = N,C,D,H,W",
    "2929129": "This will most likely hurt and not help because the slice thickness is much greater than the pixel spacing. \n\nFor example, `series_id` 108597120 has a pixel spacing of 0.25 x 0.25 mm and a slice thickness of 3.5 mm, meaning each voxel is 0.25 x 0.25 x 3.5 mm. If you resample this to 1 x 1 x 1 mm, you are downsampling the in-plane resolution by 4 and upsampling the out-of-plane resolution by 3.5 (which is only adding redundant information).",
    "2929441": "That is true, but what if we chose the median spacing of all the training image series? That would alleviate some of the downsampling  and upsampling issues mentioned above.\nIf I understand correctly, [nnU-Net](https://github.com/MIC-DKFZ/nnUNet), does something similar to this.",
    "2929713": "Can you explain please, how did you figured out a pixel spacing and a slice thickness?",
    "2929723": "It's in the dicom metadata\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F15806223%2Ffd9e90f351b3f00e8e653527f7b31df0%2FScreenshot%202024-07-20%20at%2017.36.32.png?generation=1721468204017089&alt=media)",
    "2929730": "thank you!",
    "2931847": "I think resampling all studies to a consistent spacing (e.g., 0.3 x 0.3 x 4 mm) is reasonable. But I still don't think isotropic resampling is the best idea.",
    "2937891": "![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F113660%2F3df64bc42e897cd0c8f25fc91778a9ad%2FSelection_198.png?generation=1722091481735297&alt=media)\n\ni note that some axial scans are not cuboid. It could be a parallelepiped.\n(notice that BOTH y and z are changing in the position array)",
    "2938014": "It says 18x640x640 but is trully that volume? Because there is some axial with double shape along the slices."
  },
  "source": "meta"
}