Interpolate/Resize 3D array

前端 未结 3 633
面向向阳花
面向向阳花 2021-02-15 16:37

I have a 3D array holding voxels from a mri dataset. The model could be stretched along one or more directions. E.g. the voxel size (x,y,z) could be 0.5x0.5x2 mm. Now I want to

3条回答
  •  猫巷女王i
    2021-02-15 17:18

    You can also use PyTorch + TorchIO. The following is the resampling of a 3D array with gaussian interpolation (the zoom function is adapted from the code that my supervisor wrote for me):

    def zoom(
        label_stack: Sequence[Sequence[SupportsFloat]],
        spacing: Sequence[Union[SupportsInt, SupportsFloat]],
    ) -> np.ndarray:
        spacing = np.asanyarray(spacing)
        target = tuple(1 / spacing)
    
        # Resample the array with respect to spacing parameters
        arr4d = np.expand_dims(label_stack, 0)
        transform = tio.Resample(target, image_interpolation="gaussian")
        transformed = transform(arr4d)
        result = np.squeeze(transformed)
    
        # Perform an arbitrary gaussian to smoothen the surface.
        # Achieves a more smooth surface
        sigma = (round(spacing[0] * 0.25), 7, 7)
        gaussian_3d = gaussian_filter(result, sigma=sigma)
    
        # Binary thresholding
        highpass_threshold = np.median(gaussian_3d[gaussian_3d > 0.09])
        thresh = threshold_array(gaussian_3d, highpass=highpass_threshold)
    
        return thresh
    
    
    def threshold_array(
        array: np.ndarray,
        lowpass: Union[Union[SupportsInt, SupportsFloat], None] = None,
        highpass: Union[Union[SupportsInt, SupportsFloat], None] = None,
    ) -> np.ndarray:
        if lowpass and highpass:
            msg = "Defition of both lowpass and highpass is illogical"
            raise ValueError(msg)
    
        if not lowpass and not highpass:
            msg = "Either lowpass or highpass has to be defined"
            raise ValueError(msg)
    
        array = np.asanyarray(array)
        filtered = np.zeros_like(array, dtype=np.int8)
    
        if lowpass:
            filtered[array < lowpass] = 1
        if highpass:
            filtered[array > highpass] = 1
    
        return filtered
    

    The images array is z-x-y, and zoom has been designed accordingly.

    Spacing is defined by the user. Spacing has to be a sequence that has the same length as the shape of the image numpy array. The interpolated image will have the shape as spacing * "old shape".

    I wish there was cubic method for the interpolation in the Resample function. I tried with gaussian + thresholding, but haven't gotten any great results. Better than whatever I could muster with SciPy though.

    Please credit when used.

提交回复
热议问题