Source code for pymerlin.iq

# -*- coding: utf-8 -*-
"""
Tools for investigating image quality
"""

import numpy as np
from skimage.feature import canny
from skimage.filters import sobel
from skimage.metrics import structural_similarity


[docs]def ssim(img1, img2, kw=11, sigma=0): """Calculate the Structural Similarity Index Measure Wang, Z., Bovik, A. C., Sheikh, H. R., & Simoncelli, E. P. (2004). Image quality assessment: From error visibility to structural similarity. IEEE Transactions on Image Processing, 13(4), 600–612. https://doi.org/10.1109/TIP.2003.819861 Args: img1 (np.array): Reference Image img2 (np.array): Comparison image kw (int, optional): Kernel width. Defaults to 11. sigma (int, optional): Gaussian window sigma. Defaults to 0. Returns: float, np.array: Mean SSIM, SSIM image """ img1 /= np.quantile(img1[...], 0.99) img2 /= np.quantile(img2[...], 0.99) gauss_window = False use_sample_covariance = True if sigma: gauss_window = True use_sample_covariance = False mssim, S = structural_similarity( img1, img2, win_size=kw, data_range=1, gradient=False, multichannel=False, gaussian_weights=gauss_window, full=True, use_sample_covariance=use_sample_covariance, sigma=sigma) return mssim, S
[docs]def aes(img, mask=None, canny_edges=None, canny_sigma=2): """Calculate the Average Edge Strength Reference: Aksoy, M., Forman, C., Straka, M., Çukur, T., Hornegger, J., & Bammer, R. (2012). Hybrid prospective and retrospective head motion correction to mitigate cross-calibration errors. Magnetic Resonance in Medicine, 67(5), 1237–1251. https://doi.org/10.1002/mrm.23101 Args: img (np.array): Image mask (np.array, optional): Brain mask. Defaults to None. canny_edges (np.array, optional): Edges to use for calculation, calculates if `None`. Defaults to None. canny_sigma (int, optional): Sigma for canny edge detection filter. Defaults to 2. Returns: float, np.array, np.array: aes, edges, canny edge mask """ imax = np.quantile(img[mask == 1], 0.99) if canny_edges is None: canny_edges = np.zeros_like(img) for z in range(img.shape[2]): canny_edges[:, :, z] = canny( img[:, :, z], sigma=canny_sigma) canny_edges *= mask img_edges = sobel(img/imax) * canny_edges aes = np.mean(img_edges[canny_edges == 1]) return aes, img_edges, canny_edges
[docs]def nrmse(img_ref, img_comp, mask): """Calculates the Normalised root mean squared error Args: img_ref (np.array): Reference image img_comp (np.array): Comparison image mask (np.array): Brain mask Returns: np.array: nrmse """ yrange = np.max(img_ref[mask == 1]) - np.min(img_ref[mask == 1]) return np.sqrt(np.sum((img_comp[mask == 1] - img_ref[mask == 1])**2) / np.sum(mask)) / yrange
[docs]def gradient_entropy(img): """Calculates gradient entropy of image Reference: McGee, K.P., Manduca, A., Felmlee, J.P., Riederer, S.J. and Ehman, R.L. (2000), Image metric‐based correction (Autocorrection) of motion effects: Analysis of image metrics. J. Magn. Reson. Imaging, 11: 174-181. https://doi.org/10.1002/(SICI)1522-2586(200002)11:2<174::AID-JMRI15>3.0.CO;2-3 Args: img (np.array): Image Returns: float: gradient entropy """ """ Calculates gradient entropy of ND image """ h = img/np.sum(img**2) GE = -np.sum(h*np.log2(h)) return GE