Skip to content

Instantly share code, notes, and snippets.

@Pro
Last active November 30, 2019 10:27
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Pro/5896825 to your computer and use it in GitHub Desktop.
Save Pro/5896825 to your computer and use it in GitHub Desktop.
Normalize Image using Lab channel
__author__ = 'Stefan'
__docformat__ = 'restructedtext en'
import numpy as np
import scipy.misc
import skimage.color
import skimage.exposure
def histBounds(histogram, margin=0.005):
"""
Detect lower and upper boundary of histogram. This is used to stretch it afterwards to get better contrast.
:param histogram: list containing the number of members for each index
:param margin: count value lower than max(histogram)*margin will be considered as zero
:return: (lowerMargin, upperMargin) indices in histogram array.
"""
# cut off full black and full white pixels and ignore them
lowCut = int(len(histogram) * 0.12)
highCut = int(len(histogram) * 0.95)
histCut = histogram[lowCut:highCut]
logMargin = np.max(histCut) * margin
#now search for minimum and maximum color
nonzero = np.where(histCut > logMargin)
# return the first and last index where the count is non zero
return lowCut + np.min(nonzero), lowCut + np.max(nonzero)
def normalizeChannel(channel, maxVal=255.):
"""
Normalizes the histogram of given 2D array (which is one cannel of a color image or grayscale).
:param channel: the image data
:param maxVal: maximum value which may occur in array
"""
arr = channel.astype(float)
hist, bounds = np.histogram(arr, maxVal)
min, max = histBounds(hist)
arr = (float(maxVal) / float(max - min)) * (arr - min)
return np.clip(arr, 0, maxVal).astype(channel.dtype)
def normalizeLab(arr):
"""
Normalizes (stretches) the histogram of given image data by the following steps:
1. converting the image to Lab color system
2. using the histogram of L channel to detect lower and upper bound
3. stretch L channel to increase contrast
4. convert data back to RGB image
:param arr: image data returned from e.g. scipy.misc.fromimage
:return: normalized image data
"""
lab = skimage.color.rgb2lab(arr / 255.)
lab[..., 0] = normalizeChannel(lab[..., 0], 100)
rgb = skimage.color.lab2rgb(lab)
rgb = (rgb * 255).astype(int)
return rgb
def normalizeImage(img):
"""
Normalizes the given PIL image
:param img: an instance of PIL image
:return: normalized PIL image
"""
bytes = scipy.misc.fromimage(img)
bytes = normalizeLab(bytes)
return scipy.misc.toimage(bytes)
def normalizeImageChannel(img):
"""
Normalizes the given PIL image
:param img: an instance of PIL image
:return: normalized PIL image
"""
bytes = scipy.misc.fromimage(img)
for i in xrange(3):
bytes[..., i] = normalizeChannel(bytes[..., i], 255)
return scipy.misc.toimage(bytes)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment