<reponame>sebastianffx/stainlib<filename>extraction/vahadane_stain_extractor.py
"""
Stain normalization inspired by method of:

<NAME>., ‘Structure-Preserving Color Normalization and Sparse Stain Separation for Histological Images’, IEEE Transactions on Medical Imaging, vol. 35, no. 8, pp. 1962–1971, Aug. 2016.

Uses the spams package:

http://spams-devel.gforge.inria.fr/index.html

Use with python via e.g https://anaconda.org/conda-forge/python-spams
"""
import spams
from stainlib.utils.stain_utils import ABCStainExtractor, is_uint8_image
from stainlib.utils.stain_utils import normalize_matrix_rows, convert_RGB_to_OD, LuminosityThresholdTissueLocator

class VahadaneStainExtractor(ABCStainExtractor):

    @staticmethod
    def get_stain_matrix(I, luminosity_threshold=0.8, regularizer=0.1):
        """
        Stain matrix estimation via method of:
        <NAME>. 'Structure-Preserving Color Normalization and Sparse Stain Separation for Histological Images'
        :param I: Image RGB uint8.
        :param luminosity_threshold:
        :param regularizer:
        :return:
        """
        assert is_uint8_image(I), "Image should be RGB uint8."
        # convert to OD and ignore background
        tissue_mask = LuminosityThresholdTissueLocator.get_tissue_mask(I, luminosity_threshold=luminosity_threshold).reshape((-1,))
        OD = convert_RGB_to_OD(I).reshape((-1, 3))
        OD = OD[tissue_mask]

        # do the dictionary learning
        dictionary = spams.trainDL(X=OD.T, K=2, lambda1=regularizer, mode=2,
                                   modeD=0, posAlpha=True, posD=True, verbose=False).T

        # order H and E.
        # H on first row.
        if dictionary[0, 0] < dictionary[1, 0]:
            dictionary = dictionary[[1, 0], :]

        return normalize_matrix_rows(dictionary)

"""
Stain normalization inspired by method of:

<NAME>., ‘Structure-Preserving Color Normalization and Sparse Stain Separation for Histological Images’, IEEE Transactions on Medical Imaging, vol. 35, no. 8, pp. 1962–1971, Aug. 2016.

Uses the spams package:

http://spams-devel.gforge.inria.fr/index.html

Use with python via e.g https://anaconda.org/conda-forge/python-spams
"""
import spams
from stainlib.utils.stain_utils import ABCStainExtractor, is_uint8_image
from stainlib.utils.stain_utils import normalize_matrix_rows, convert_RGB_to_OD, LuminosityThresholdTissueLocator

class VahadaneStainExtractor(ABCStainExtractor):

    @staticmethod
    def get_stain_matrix(I, luminosity_threshold=0.8, regularizer=0.1):
        """
        Stain matrix estimation via method of:
        <NAME>. 'Structure-Preserving Color Normalization and Sparse Stain Separation for Histological Images'
        :param I: Image RGB uint8.
        :param luminosity_threshold:
        :param regularizer:
        :return:
        """
        assert is_uint8_image(I), "Image should be RGB uint8."
        # convert to OD and ignore background
        tissue_mask = LuminosityThresholdTissueLocator.get_tissue_mask(I, luminosity_threshold=luminosity_threshold).reshape((-1,))
        OD = convert_RGB_to_OD(I).reshape((-1, 3))
        OD = OD[tissue_mask]

        # do the dictionary learning
        dictionary = spams.trainDL(X=OD.T, K=2, lambda1=regularizer, mode=2,
                                   modeD=0, posAlpha=True, posD=True, verbose=False).T

        # order H and E.
        # H on first row.
        if dictionary[0, 0] < dictionary[1, 0]:
            dictionary = dictionary[[1, 0], :]

        return normalize_matrix_rows(dictionary)
Stain normalization inspired by method of:  <NAME>., ‘Structure-Preserving Color Normalization and Sparse Stain Separation for Histological Images’, IEEE Transactions on Medical Imaging, vol. 35, no. 8, pp. 1962–1971, Aug. 2016.  Uses the spams package:  http://spams-devel.gforge.inria.fr/index.html  Use with python via e.g https://anaconda.org/conda-forge/python-spams Stain matrix estimation via method of:         <NAME>. 'Structure-Preserving Color Normalization and Sparse Stain Separation for Histological Images'         :param I: Image RGB uint8.         :param luminosity_threshold:         :param regularizer:         :return: # convert to OD and ignore background # do the dictionary learning # order H and E. # H on first row.