Source code for pywsi.normalization.reinhard
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
import numpy as np
from ..io import read_as_lab
from skimage.color import lab2rgb
[docs]class ReinhardNormalization(object):
"""Reinhard Normalization """
def __init__(self):
self.target_l = None
self.target_a = None
self.target_b = None
self.target_mean = (None, None, None)
self.target_std = (None, None, None)
[docs] def fit(self, target_image):
"""Fit target image by storing its mean/std.
Parameters
----------
target_image: array_like
np.uint8 of rgb values
"""
target_image = read_as_lab(target_image)
self.target_l, self.target_a, self.target_b = target_image[:, :,
1], target_image[:, :,
1], target_image[:, :,
2]
self.target_mean, self.target_std = self.get_mean_and_std(target_image)
[docs] def transform(self, source_image):
"""Perform normalization on source image.
Parameters
----------
source_image: array_like
np.uint8 of rgb values
"""
source_image = read_as_lab(source_image)
source_l, source_a, source_b = source_image[:, :,
0], source_image[:, :,
1], source_image[:, :,
2]
source_mean, source_std = self.get_mean_and_std(source_image)
source_l -= source_mean[0]
source_a -= source_mean[1]
source_b -= source_mean[2]
source_l = self.target_std[0] / source_std[0] * source_l
source_a = self.target_std[1] / source_std[1] * source_a
source_b = self.target_std[2] / source_std[2] * source_b
source_l += self.target_mean[0]
source_a += self.target_mean[1]
source_b += self.target_mean[2]
source_l = np.clip(source_l, 0, 255)
source_a = np.clip(source_a, 0, 255)
source_b = np.clip(source_b, 0, 255)
transfer = np.dstack((source_l, source_a, source_b))
transfer = lab2rgb(transfer)
return transfer
[docs] @staticmethod
def get_mean_and_std(image):
"""Get image mean and std for all channels
"""
c1, c2, c3 = image[:, :, 0], image[:, :, 1], image[:, :, 2]
return (c1.mean(), c2.mean(), c3.mean()), (c1.std(), c2.std(),
c3.std())