def test_od_to_rgb(self): np.testing.assert_array_almost_equal( od_to_rgb(np.zeros((3, 3, 3)) + 35.6158), np.zeros((3, 3, 3)) + 116.99987889) # check corner cases np.testing.assert_array_almost_equal(od_to_rgb(np.zeros((3, 3, 3))), np.zeros((3, 3, 3)) + 255.0) np.testing.assert_array_almost_equal( od_to_rgb(np.zeros((3, 3, 3)) + 255.0), np.zeros((3, 3, 3)))
def test_rgb_to_od_to_rgb(self): np.random.seed(1) im_rand = np.random.randint(0, 255, (10, 10, 3)) np.testing.assert_array_almost_equal(od_to_rgb(rgb_to_od(im_rand)), im_rand)
def test_od_to_rgb(self): np.testing.assert_array_almost_equal( od_to_rgb(np.zeros((3, 3, 3)) + 35.6158), np.zeros((3, 3, 3)) + 116.99987889 ) # check corner cases np.testing.assert_array_almost_equal( od_to_rgb(np.zeros((3, 3, 3))), np.zeros((3, 3, 3)) + 255.0 ) np.testing.assert_array_almost_equal( od_to_rgb(np.zeros((3, 3, 3)) + 255.0), np.zeros((3, 3, 3)) )
def test_rgb_to_od_to_rgb(self): np.random.seed(1) im_rand = np.random.randint(0, 255, (10, 10, 3)) np.testing.assert_array_almost_equal( od_to_rgb(rgb_to_od(im_rand)), im_rand )
def color_convolution(im_stains, w): """Performs Color Convolution Reconstructs a color image from the stain matrix `w` and the individual images stored as channels in `im_stains` and generated by ColorDeconvolution. Parameters ---------- im_stains : array_like An RGB image where in each channel contains image of one stain w : array_like A 3x3 matrix containing the stain colors in its columns. In the case of two stains, the third column is zero and will be complemented using cross-product. The matrix should contain a minumum two nonzero columns. Returns ------- im_rgb : array_like Reconstructed RGB image with intensity values ranging from [0, 255], suitable for display. See Also -------- histomicstk.preprocessing.color_deconvolution.complement_stain_matrix, histomicstk.preprocessing.color_deconvolution.color_deconvolution histomicstk.preprocessing.color_conversion.rgb_to_od histomicstk.preprocessing.color_conversion.od_to_rgb """ # transform 3D input stain image to 2D stain matrix format m = im_stains.shape[0] n = im_stains.shape[1] im_stains = np.reshape(im_stains, (m * n, 3)) # transform input stains to optical density values, convolve and # tfm back to stain im_stains = im_stains.astype(dtype=np.float32) ODfwd = color_conversion.rgb_to_od(im_stains) ODdeconv = np.dot(ODfwd, np.transpose(w)) ODinv = color_conversion.od_to_rgb(ODdeconv) # reshape output, transform type im_rgb = np.reshape(ODinv, (m, n, 3)) im_rgb[im_rgb > 255] = 255 im_rgb = im_rgb.astype(np.uint8) return im_rgb
def ColorConvolution(I, W): """Performs Color Convolution Reconstructs a color image from the stain matrix `W` and the individual images stored as channels in `I` and generated by ColorDeconvolution. Parameters ---------- I : array_like An RGB image where in each channel contains image of one stain W : array_like A 3x3 matrix containing the stain colors in its columns. In the case of two stains, the third column is zero and will be complemented using cross-product. The matrix should contain a minumum two nonzero columns. Returns ------- IOut : array_like Reconstructed RGB image with intensity values ranging from [0, 255], suitable for display. See Also -------- histomicstk.preprocessing.color_deconvolution.ComplementStainMatrix, histomicstk.preprocessing.color_deconvolution.ColorDeconvolution histomicstk.preprocessing.color_conversion.rgb_to_od histomicstk.preprocessing.color_conversion.od_to_rgb """ # transform 3D input stain image to 2D stain matrix format m = I.shape[0] n = I.shape[1] I = np.reshape(I, (m * n, 3)) # transform input stains to optical density values, convolve and # tfm back to stain I = I.astype(dtype=np.float32) ODfwd = color_conversion.rgb_to_od(I) ODdeconv = np.dot(ODfwd, np.transpose(W)) ODinv = color_conversion.od_to_rgb(ODdeconv) # reshape output, transform type IOut = np.reshape(ODinv, (m, n, 3)) IOut[IOut > 255] = 255 IOut = IOut.astype(np.uint8) return IOut
def color_deconvolution(im_rgb, w): """Performs color deconvolution. The given RGB Image `I` is first first transformed into optical density space, and then projected onto the stain vectors in the columns of the 3x3 stain matrix `W`. For deconvolving H&E stained image use: `w` = array([[0.650, 0.072, 0], [0.704, 0.990, 0], [0.286, 0.105, 0]]) Parameters ---------- im_rgb : array_like Input RGB Image that needs to be deconvolved. w : array_like A 3x3 matrix containing the color vectors in columns. For two stain images the third column is zero and will be complemented using cross-product. Atleast two of the three columns must be non-zero. Returns ------- Stains : array_like An rgb image where in each channel contains the image of the stain of the corresponding column in the stain matrix `W`. The intensity range of each channel is [0, 255] suitable for displaying. StainsFloat : array_like An intensity image of deconvolved stains that is unbounded, suitable for reconstructing color images of deconvolved stains with color_convolution. wc : array_like A 3x3 complemented stain matrix. Useful for color image reconstruction with color_convolution. See Also -------- histomicstk.preprocessing.color_deconvolution.complement_stain_matrix, histomicstk.preprocessing.color_deconvolution.color_convolution histomicstk.preprocessing.color_conversion.rgb_to_od histomicstk.preprocessing.color_conversion.od_to_rgb """ # complement stain matrix if needed if numpy.linalg.norm(w[:, 2]) <= 1e-16: wc = complement_stain_matrix(w) else: wc = w.copy() # normalize stains to unit-norm for i in range(wc.shape[1]): Norm = numpy.linalg.norm(wc[:, i]) if Norm >= 1e-16: wc[:, i] /= Norm # invert stain matrix Q = numpy.linalg.inv(wc) # transform 3D input image to 2D RGB matrix format m = im_rgb.shape[0] n = im_rgb.shape[1] if im_rgb.shape[2] == 4: im_rgb = im_rgb[:, :, (0, 1, 2)] im_rgb = numpy.reshape(im_rgb, (m * n, 3)) # transform input RGB to optical density values and deconvolve, # tfm back to RGB im_rgb = im_rgb.astype(dtype=numpy.float32) im_rgb[im_rgb == 0] = 1e-16 ODfwd = color_conversion.rgb_to_od(im_rgb) ODdeconv = numpy.dot(ODfwd, numpy.transpose(Q)) ODinv = color_conversion.od_to_rgb(ODdeconv) # reshape output StainsFloat = numpy.reshape(ODinv, (m, n, 3)) # transform type Stains = numpy.copy(StainsFloat) Stains[Stains > 255] = 255 Stains = Stains.astype(numpy.uint8) # return Unmixed = collections.namedtuple('Unmixed', ['Stains', 'StainsFloat', 'Wc']) Output = Unmixed(Stains, StainsFloat, wc) return Output
def ColorDeconvolution(I, W): """Performs color deconvolution. The given RGB Image `I` is first first transformed into optical density space, and then projected onto the stain vectors in the columns of the 3x3 stain matrix `W`. For deconvolving H&E stained image use: `W` = array([[0.650, 0.072, 0], [0.704, 0.990, 0], [0.286, 0.105, 0]]) Parameters ---------- I : array_like Input RGB Image that needs to be deconvolved. W : array_like A 3x3 matrix containing the color vectors in columns. For two stain images the third column is zero and will be complemented using cross-product. Atleast two of the three columns must be non-zero. Returns ------- Stains : array_like An rgb image where in each channel contains the image of the stain of the corresponding column in the stain matrix `W`. The intensity range of each channel is [0, 255] suitable for displaying. StainsFloat : array_like An intensity image of deconvolved stains that is unbounded, suitable for reconstructing color images of deconvolved stains with ColorConvolution. Wc : array_like A 3x3 complemented stain matrix. Useful for color image reconstruction with ColorConvolution. See Also -------- histomicstk.preprocessing.color_deconvolution.ComplementStainMatrix, histomicstk.preprocessing.color_deconvolution.ColorConvolution histomicstk.preprocessing.color_conversion.rgb_to_od histomicstk.preprocessing.color_conversion.od_to_rgb """ # complement stain matrix if needed if numpy.linalg.norm(W[:, 2]) <= 1e-16: Wc = ComplementStainMatrix(W) else: Wc = W.copy() # normalize stains to unit-norm for i in range(Wc.shape[1]): Norm = numpy.linalg.norm(Wc[:, i]) if Norm >= 1e-16: Wc[:, i] /= Norm # invert stain matrix Q = numpy.linalg.inv(Wc) # transform 3D input image to 2D RGB matrix format m = I.shape[0] n = I.shape[1] if I.shape[2] == 4: I = I[:, :, (0, 1, 2)] I = numpy.reshape(I, (m * n, 3)) # transform input RGB to optical density values and deconvolve, # tfm back to RGB I = I.astype(dtype=numpy.float32) I[I == 0] = 1e-16 ODfwd = color_conversion.rgb_to_od(I) ODdeconv = numpy.dot(ODfwd, numpy.transpose(Q)) ODinv = color_conversion.od_to_rgb(ODdeconv) # reshape output StainsFloat = numpy.reshape(ODinv, (m, n, 3)) # transform type Stains = numpy.copy(StainsFloat) Stains[Stains > 255] = 255 Stains = Stains.astype(numpy.uint8) # return Unmixed = collections.namedtuple('Unmixed', ['Stains', 'StainsFloat', 'Wc']) Output = Unmixed(Stains, StainsFloat, Wc) return Output