The transform applies Gibbs noise to 2D/3D MRI images. Gibbs artifacts are one of the common type of type artifacts appearing in MRI scans. The transform is applied to all the channels in the data. For general information on Gibbs artifacts, please refer to: `An Image-based A
| 1924 | |
| 1925 | |
| 1926 | class GibbsNoise(Transform, Fourier): |
| 1927 | """ |
| 1928 | The transform applies Gibbs noise to 2D/3D MRI images. Gibbs artifacts |
| 1929 | are one of the common type of type artifacts appearing in MRI scans. |
| 1930 | |
| 1931 | The transform is applied to all the channels in the data. |
| 1932 | |
| 1933 | For general information on Gibbs artifacts, please refer to: |
| 1934 | |
| 1935 | `An Image-based Approach to Understanding the Physics of MR Artifacts |
| 1936 | <https://pubs.rsna.org/doi/full/10.1148/rg.313105115>`_. |
| 1937 | |
| 1938 | `The AAPM/RSNA Physics Tutorial for Residents |
| 1939 | <https://pubs.rsna.org/doi/full/10.1148/radiographics.22.4.g02jl14949>`_ |
| 1940 | |
| 1941 | Args: |
| 1942 | alpha: Parametrizes the intensity of the Gibbs noise filter applied. Takes |
| 1943 | values in the interval [0,1] with alpha = 0 acting as the identity mapping. |
| 1944 | """ |
| 1945 | |
| 1946 | backend = [TransformBackends.TORCH, TransformBackends.NUMPY] |
| 1947 | |
| 1948 | def __init__(self, alpha: float = 0.1) -> None: |
| 1949 | if alpha > 1 or alpha < 0: |
| 1950 | raise ValueError("alpha must take values in the interval [0, 1].") |
| 1951 | self.alpha = alpha |
| 1952 | |
| 1953 | def __call__(self, img: NdarrayOrTensor) -> NdarrayOrTensor: |
| 1954 | img = convert_to_tensor(img, track_meta=get_track_meta()) |
| 1955 | img_t = convert_to_tensor(img, track_meta=False) |
| 1956 | n_dims = len(img_t.shape[1:]) |
| 1957 | |
| 1958 | # FT |
| 1959 | k = self.shift_fourier(img_t, n_dims) |
| 1960 | # build and apply mask |
| 1961 | k = self._apply_mask(k) |
| 1962 | # map back |
| 1963 | out = self.inv_shift_fourier(k, n_dims) |
| 1964 | img, *_ = convert_to_dst_type(out, dst=img, dtype=out.dtype) |
| 1965 | |
| 1966 | return img |
| 1967 | |
| 1968 | def _apply_mask(self, k: NdarrayOrTensor) -> NdarrayOrTensor: |
| 1969 | """Builds and applies a mask on the spatial dimensions. |
| 1970 | |
| 1971 | Args: |
| 1972 | k: k-space version of the image. |
| 1973 | Returns: |
| 1974 | masked version of the k-space image. |
| 1975 | """ |
| 1976 | shape = k.shape[1:] |
| 1977 | |
| 1978 | # compute masking radius and center |
| 1979 | r = (1 - self.alpha) * np.max(shape) * np.sqrt(2) / 2.0 |
| 1980 | center = (np.array(shape) - 1) / 2 |
| 1981 | |
| 1982 | # gives list w/ len==self.dim. Each dim gives coordinate in that dimension |
| 1983 | coords = np.ogrid[tuple(slice(0, i) for i in shape)] |
no outgoing calls
searching dependent graphs…