Generic selectors
Exact matches only
Search in title
Search in content
Post Type Selectors

Fast medical imaging cropping

Efficient cropping of large NIfTI medical images using Python and SimpleITK for model training

Medical imaging cropping here is a SimpleITK how-to: take a large NIfTI, cut it along z into smaller chunks with RegionOfInterest, and write each chunk so spacing, origin, and direction stay honest. It is not a generic preprocessing explainer. It is not a PYCAD product.

If you meant change voxel spacingresampling in medical imaging. If you meant the whole preprocess pipelinewhat is image preprocessing. If you meant intensity scaleimage normalization. If you meant tabular rows (impute / IQR / one-hot)data preprocessing for machine learning. If you meant MONAI Spacingd / CropForegroundd for tumor segpreprocessing 3D volumes in MONAI.

3351 already points at this URL for “crop (same grid, smaller FOV).” The job is the cut, not a new spacing.

Why you chunk a volume

A CT can be 400–600 slices. Training a 3D net on the whole array is often the wrong first move: the z-length is not the same from patient to patient, and a convolution on 500 slices will not fit a single GPU. Cutting along z into fixed-depth chunks is one way to get a batch that actually loads. You keep the original xy and the original spacing. You are not resampling.

sitk.RegionOfInterest copies the metadata. A numpy slice that you write back as a new image will invent an origin unless you set it. That is why this snippet goes through SimpleITK instead of array[z:z+n].

The cut

import os
import SimpleITK as sitk
import matplotlib.pyplot as plt

def load_and_process_image_in_chunks(filepath, chunk_size, output_dir):
    os.makedirs(output_dir, exist_ok=True)
    image = sitk.ReadImage(filepath)
    size = image.GetSize()
    print("direction", image.GetDirection())
    print("spacing", image.GetSpacing())
    print("origin", image.GetOrigin())

    for z in range(0, size[2], chunk_size):
        region_size = [size[0], size[1], min(chunk_size, size[2] - z)]
        region_index = [0, 0, z]
        region = sitk.RegionOfInterest(image, region_size, region_index)
        chunk_filename = os.path.join(output_dir, f"chunk_{z}.nii")
        sitk.WriteImage(region, chunk_filename)
        yield region, chunk_filename

def visualize_image(filepath):
    image = sitk.ReadImage(filepath)
    arr = sitk.GetArrayViewFromImage(image)
    for i in range(arr.shape[0]):
        plt.imshow(arr[i, :, :], cmap="gray")
        plt.title(f"slice {i + 1}/{arr.shape[0]}")
        plt.axis("off")
        plt.show()

filepath = "path_to_large_image.nii"
for chunk, name in load_and_process_image_in_chunks(filepath, 50, "output_chunks"):
    print("saved", name)
visualize_image("output_chunks/chunk_0.nii")

SimpleITK indexes are (x, y, z). The numpy view is (z, y, x). Mix those up and the chunk is a slab in the wrong direction. The last chunk is shorter when size[2] is not a multiple of chunk_size — that is what the min is for.

What the metadata is doing

  • Spacing. Millimetres between voxel centres. Unchanged by this crop. Changing it is resampling.
  • Direction. How the axes sit in the patient. Unchanged.
  • Origin. Physical coordinates of index (0, 0, 0). Each chunk gets a new origin at its first voxel. SimpleITK sets that. A raw array write will not.

Install is pip install SimpleITK matplotlib. This is a 2023 PYCAD Team snippet, not a product.

What this page is not

  • Not resampling, normalisation, or “what is preprocessing.” Those are the 680 keepers linked above.
  • Not MONAI CropForegroundd / Spacingd. That compose is 3050.
  • Not a PYCAD crop app or a “fast cropping” SKU.
  • Not a join-us / YouTube / services footer. Dropped.

If the crop has to run inside a clinic viewer on a DICOM series, that is the imaging piece. Case studies.

We build custom medical imaging platforms — advanced DICOM viewers, AI segmentation, and the clinical systems around them.

Get in Touch

Copyright © 2026 PYCAD. All Rights Reserved.