def test_rgb_to_lab_to_rgb(self):

        np.random.seed(1)

        im_rand = np.random.randint(0, 255, (10, 10, 3))

        np.testing.assert_array_almost_equal(
            np.round(lab_to_rgb(rgb_to_lab(im_rand))), im_rand)
    def test_rgb_to_lab_to_rgb(self):

        np.random.seed(1)

        im_rand = np.random.randint(0, 255, (10, 10, 3))

        np.testing.assert_array_almost_equal(
            np.round(lab_to_rgb(rgb_to_lab(im_rand))),
            im_rand
        )
def reinhard_color_stats(gc, item_id, magnification=1.25):
    """Calculate the Reinhard color stats (mean and standard dev. of each channel in LAB color space) for a DSA image
    item. The color stats are calculated from only the pixels that fall within the tissue, as detected by the
    HistomicsTK function: saliency.tissue_detection.get_tissue_mask(..) with default parameters.

    Parameters
    ----------
    gc : girder_client.GirderClient
        authenticated girder client for private images
    item_id : str
        image item id
    magnification : float (optional)
        magnification of thumbnail used to calculate the color stats

    Returns
    -------
    mu : np.array
        LAB mean for each channel (length of 3)
    sigma : np.array
        LAB standard dev. for each channel (length of 3)

    """
    im_info = gc.get('item/{}/tiles'.format(item_id))

    # get thumbnail as specified magnification
    thumbnail = get_item_image(gc, item_id, 'thumbnail', return_type='Array',
                               width=int(im_info['sizeX']*magnification/im_info['magnification']))

    # get the tissue mask
    tissue_mask = get_tissue_mask(thumbnail)[0] == 0

    # convert image to LAB color space
    im_lab = rgb_to_lab(thumbnail)

    # get the pixels inside mask
    tissue_mask_reshaped = tissue_mask[..., None]
    im_lab = np.ma.masked_array(im_lab, mask=np.tile(tissue_mask_reshaped, (1, 1, 3)))

    # calculate the channel's mean and standard deviation
    mu = [im_lab[..., i].mean() for i in range(3)]
    sigma = [im_lab[..., i].std() for i in range(3)]
    return mu, sigma
    def assign_components_by_thresholding(self):
        """Get components by thresholding in HSI and LAB spaces."""
        # get HSI and LAB images
        self.cdt._print2("%s: -- get HSI and LAB images ..." %
                         self.monitorPrefix)
        tissue_hsi = rgb_to_hsi(self.tissue_rgb)
        tissue_lab = rgb_to_lab(self.tissue_rgb)

        # extract components using HSI/LAB thresholds

        hsi_components = self.cdt.hsi_thresholds.keys()
        lab_components = self.cdt.lab_thresholds.keys()

        for component in self.cdt.ordered_components:

            self.cdt._print2("%s: -- thresholding %s ..." %
                             (self.monitorPrefix, component))

            if component in hsi_components:
                lab, _ = threshold_multichannel(
                    tissue_hsi,
                    channels=['hue', 'saturation', 'intensity'],
                    thresholds=self.cdt.hsi_thresholds[component],
                    just_threshold=False,
                    get_tissue_mask_kwargs=self.cdt.get_tissue_mask_kwargs2)
            elif component in lab_components:
                lab, _ = threshold_multichannel(
                    tissue_lab,
                    channels=['l', 'a', 'b'],
                    thresholds=self.cdt.lab_thresholds[component],
                    just_threshold=True,
                    get_tissue_mask_kwargs=self.cdt.get_tissue_mask_kwargs2)
            else:
                raise ValueError("Unknown component name.")

            lab[self.labeled == 0] = 0  # restrict to tissue mask
            self.labeled[lab > 0] = self.cdt.GTcodes.loc[component, 'GT_code']

        # This deals with holes in tissue
        self.labeled[self.labeled == 0] = self.cdt.GTcodes.loc[
            'outside_tissue', 'GT_code']
def reinhard(im_src,
             target_mu,
             target_sigma,
             src_mu=None,
             src_sigma=None,
             mask_out=None):
    """Perform Reinhard color normalization.

    Transform the color characteristics of an image to a desired standard.
    The standard is defined by the mean and standard deviations of the target
    image in LAB color space defined by Ruderman. The input image is converted
    to Ruderman's LAB space, the LAB channels are each centered and scaled to
    zero-mean unit variance, and then rescaled and shifted to match the target
    image statistics. If the LAB statistics for the input image are provided
    (`src_mu` and `src_sigma`) then these will be used for normalization,
    otherwise they will be derived from the input image `im_src`.

    Parameters
    ----------
    im_src : array_like
        An RGB image

    target_mu : array_like
        A 3-element array containing the means of the target image channels
        in LAB color space.

    target_sigma : array_like
        A 3-element array containing the standard deviations of the target
        image channels in LAB color space.

    src_mu : array_like, optional
        A 3-element array containing the means of the source image channels in
        LAB color space. Used with reinhard_stats for uniform normalization of
        tiles from a slide.

    src_sigma : array, optional
        A 3-element array containing the standard deviations of the source
        image channels in LAB color space. Used with reinhard_stats for
        uniform normalization of tiles tiles from a slide.

    mask_out : array_like, default is None
        if not None, should be (m, n) boolean numpy array.
        This method uses numpy masked array functionality to only use
        non-masked areas in calculations. This is relevant because elements
        like blood, sharpie marker, white space, etc would throw off the
        reinhard normalization by affecting the mean and stdev. Ideally, you
        want to exclude these elements from both the target image (from which
        you calculate target_mu and target_sigma) and from the source image
        to be normalized.

    Returns
    -------
    im_normalized : array_like
        Color Normalized RGB image

    See Also
    --------
    histomicstk.preprocessing.color_conversion.rgb_to_lab,
    histomicstk.preprocessing.color_conversion.lab_to_rgb

    References
    ----------
    .. [#] E. Reinhard, M. Adhikhmin, B. Gooch, P. Shirley, "Color transfer
       between images," in IEEE Computer Graphics and Applications, vol.21,
       no.5,pp.34-41, 2001.
    .. [#] D. Ruderman, T. Cronin, and C. Chiao, "Statistics of cone responses
       to natural images: implications for visual coding," J. Opt. Soc. Am. A
       vol.15, pp.2036-2045, 1998.

    """
    # convert input image to LAB color space
    im_lab = color_conversion.rgb_to_lab(im_src)

    # mask out irrelevant tissue / whitespace / etc
    if mask_out is not None:
        mask_out = mask_out[..., None]
        im_lab = np.ma.masked_array(im_lab, mask=np.tile(mask_out, (1, 1, 3)))

    # calculate src_mu and src_sigma if either is not provided
    if (src_mu is None) or (src_sigma is None):
        src_mu = [im_lab[..., i].mean() for i in range(3)]
        src_sigma = [im_lab[..., i].std() for i in range(3)]

    # scale to unit variance
    for i in range(3):
        im_lab[:, :, i] = (im_lab[:, :, i] - src_mu[i]) / src_sigma[i]

    # rescale and recenter to match target statistics
    for i in range(3):
        im_lab[:, :, i] = im_lab[:, :, i] * target_sigma[i] + target_mu[i]

    # convert back to RGB colorspace
    im_normalized = color_conversion.lab_to_rgb(im_lab)
    im_normalized[im_normalized > 255] = 255
    im_normalized[im_normalized < 0] = 0

    # return masked values and reconstruct unmasked LAB image
    if mask_out is not None:
        im_normalized = im_normalized.data
        for i in range(3):
            original = im_src[:, :, i].copy()
            new = im_normalized[:, :, i].copy()
            original[np.not_equal(mask_out[:, :, 0], True)] = 0
            new[mask_out[:, :, 0]] = 0
            im_normalized[:, :, i] = new + original

    im_normalized = im_normalized.astype(np.uint8)

    return im_normalized
Esempio n. 6
0
def reinhard(im_src, target_mu, target_sigma, src_mu=None, src_sigma=None):
    """Performs Reinhard color normalization to transform the color
    characteristics of an image to a desired standard.

    The standard is defined by the mean and standard deviations of the target
    image in LAB color space defined by Ruderman. The input image is converted
    to Ruderman's LAB space, the LAB channels are each centered and scaled to
    zero-mean unit variance, and then rescaled and shifted to match the target
    image statistics. If the LAB statistics for the input image are provided
    (`src_mu` and `src_sigma`) then these will be used for normalization,
    otherwise they will be derived from the input image `im_src`.

    Parameters
    ----------
    im_src : array_like
        An RGB image

    target_mu : array_like
        A 3-element array containing the means of the target image channels
        in LAB color space.

    target_sigma : array_like
        A 3-element array containing the standard deviations of the target
        image channels in LAB color space.

    src_mu : array_like, optional
        A 3-element array containing the means of the source image channels in
        LAB color space. Used with reinhard_stats for uniform normalization of
        tiles from a slide.

    src_sigma : array, optional
        A 3-element array containing the standard deviations of the source
        image channels in LAB color space. Used with reinhard_stats for
        uniform normalization of tiles tiles from a slide.

    Returns
    -------
    im_normalized : array_like
        Color Normalized RGB image

    See Also
    --------
    histomicstk.preprocessing.color_conversion.rgb_to_lab,
    histomicstk.preprocessing.color_conversion.lab_to_rgb

    References
    ----------
    .. [1] E. Reinhard, M. Adhikhmin, B. Gooch, P. Shirley, "Color transfer
       between images," in IEEE Computer Graphics and Applications, vol.21,
       no.5,pp.34-41, 2001.
    .. [2] D. Ruderman, T. Cronin, and C. Chiao, "Statistics of cone responses
       to natural images: implications for visual coding," J. Opt. Soc. Am. A
       vol.15, pp.2036-2045, 1998.
    """

    # get input image dimensions
    m = im_src.shape[0]
    n = im_src.shape[1]

    # convert input image to LAB color space
    im_lab = color_conversion.rgb_to_lab(im_src)

    # calculate src_mu if not provided
    if src_mu is None:
        src_mu = im_lab.sum(axis=0).sum(axis=0) / (m * n)

    # center to zero-mean
    for i in range(3):
        im_lab[:, :, i] = im_lab[:, :, i] - src_mu[i]

    # calculate src_sigma if not provided
    if src_sigma is None:
        src_sigma = ((im_lab * im_lab).sum(axis=0).sum(axis=0) /
                     (m * n - 1))**0.5

    # scale to unit variance
    for i in range(3):
        im_lab[:, :, i] = im_lab[:, :, i] / src_sigma[i]

    # rescale and recenter to match target statistics
    for i in range(3):
        im_lab[:, :, i] = im_lab[:, :, i] * target_sigma[i] + target_mu[i]

    # convert back to RGB colorspace
    im_normalized = color_conversion.lab_to_rgb(im_lab)
    im_normalized[im_normalized > 255] = 255
    im_normalized[im_normalized < 0] = 0
    im_normalized = im_normalized.astype(np.uint8)

    return im_normalized
def reinhard(im_src, target_mu, target_sigma, src_mu=None, src_sigma=None):
    """Performs Reinhard color normalization to transform the color
    characteristics of an image to a desired standard.

    The standard is defined by the mean and standard deviations of the target
    image in LAB color space defined by Ruderman. The input image is converted
    to Ruderman's LAB space, the LAB channels are each centered and scaled to
    zero-mean unit variance, and then rescaled and shifted to match the target
    image statistics. If the LAB statistics for the input image are provided
    (`src_mu` and `src_sigma`) then these will be used for normalization,
    otherwise they will be derived from the input image `im_src`.

    Parameters
    ----------
    im_src : array_like
        An RGB image

    target_mu : array_like
        A 3-element array containing the means of the target image channels
        in LAB color space.

    target_sigma : array_like
        A 3-element array containing the standard deviations of the target
        image channels in LAB color space.

    src_mu : array_like, optional
        A 3-element array containing the means of the source image channels in
        LAB color space. Used with reinhard_stats for uniform normalization of
        tiles from a slide.

    src_sigma : array, optional
        A 3-element array containing the standard deviations of the source
        image channels in LAB color space. Used with reinhard_stats for
        uniform normalization of tiles tiles from a slide.

    Returns
    -------
    im_normalized : array_like
        Color Normalized RGB image

    See Also
    --------
    histomicstk.preprocessing.color_conversion.rgb_to_lab,
    histomicstk.preprocessing.color_conversion.lab_to_rgb

    References
    ----------
    .. [1] E. Reinhard, M. Adhikhmin, B. Gooch, P. Shirley, "Color transfer
       between images," in IEEE Computer Graphics and Applications, vol.21,
       no.5,pp.34-41, 2001.
    .. [2] D. Ruderman, T. Cronin, and C. Chiao, "Statistics of cone responses
       to natural images: implications for visual coding," J. Opt. Soc. Am. A
       vol.15, pp.2036-2045, 1998.
    """

    # get input image dimensions
    m = im_src.shape[0]
    n = im_src.shape[1]

    # convert input image to LAB color space
    im_lab = color_conversion.rgb_to_lab(im_src)

    # calculate src_mu if not provided
    if src_mu is None:
        src_mu = im_lab.sum(axis=0).sum(axis=0) / (m * n)

    # center to zero-mean
    for i in range(3):
        im_lab[:, :, i] = im_lab[:, :, i] - src_mu[i]

    # calculate src_sigma if not provided
    if src_sigma is None:
        src_sigma = ((im_lab * im_lab).sum(axis=0).sum(axis=0) /
                     (m * n - 1)) ** 0.5

    # scale to unit variance
    for i in range(3):
        im_lab[:, :, i] = im_lab[:, :, i] / src_sigma[i]

    # rescale and recenter to match target statistics
    for i in range(3):
        im_lab[:, :, i] = im_lab[:, :, i] * target_sigma[i] + target_mu[i]

    # convert back to RGB colorspace
    im_normalized = color_conversion.lab_to_rgb(im_lab)
    im_normalized[im_normalized > 255] = 255
    im_normalized[im_normalized < 0] = 0
    im_normalized = im_normalized.astype(np.uint8)

    return im_normalized