"""
Other utilities.
"""
from __future__ import division
import numpy as np
import cv2 as cv
[docs]def standardize_brightness(I, percentile=95):
"""
Standardize brightness.
:param I: Image uint8 RGB.
:return: Image uint8 RGB with standardized brightness.
"""
assert is_uint8_image(I)
I_LAB = cv.cvtColor(I, cv.COLOR_RGB2LAB)
L = I_LAB[:, :, 0]
p = np.percentile(L, percentile)
I_LAB[:, :, 0] = np.clip(255. * L / p, 0, 255).astype(np.uint8) # 255. float seems to be important...
I = cv.cvtColor(I_LAB, cv.COLOR_LAB2RGB)
return I
[docs]def remove_zeros(I):
"""
Remove zeros in an image, replace with 1's.
:param I: An Array.
:return: New array where 0's have been replaced with 1's.
"""
mask = (I == 0)
I[mask] = 1
return I
[docs]def RGB_to_OD(I):
"""
Convert from RGB to optical density (OD_RGB) space.
RGB = 255 * exp(-1*OD_RGB).
:param I: Image RGB uint8.
:return: Optical denisty RGB image.
"""
I = remove_zeros(I) # we don't want to take the log of zero..
return -1 * np.log(I / 255)
[docs]def OD_to_RGB(OD):
"""
Convert from optical density (OD_RGB) to RGB
RGB = 255 * exp(-1*OD_RGB)
:param OD: Optical denisty RGB image.
:return: Image RGB uint8.
"""
assert OD.min() >= 0, 'Negative optical density'
return (255 * np.exp(-1 * OD)).astype(np.uint8)
[docs]def normalize_rows(A):
"""
Normalize the rows of an array.
:param A: An array.
:return: Array with rows normalized.
"""
return A / np.linalg.norm(A, axis=1)[:, None]
[docs]def notwhite_mask(I, thresh=0.8):
"""
Get a binary mask where true denotes 'not white'.
Specifically, a pixel is not white if its luminance (in LAB color space) is less than the specified threshold.
:param I: RGB uint 8 image.
:param thresh: Luminosity threshold.
:return: Binary mask where true denotes 'not white'.
"""
assert is_uint8_image(I)
I_LAB = cv.cvtColor(I, cv.COLOR_RGB2LAB)
L = I_LAB[:, :, 0] / 255.0
return (L < thresh)
[docs]def sign(x):
"""
Returns the sign of x.
:param x: A scalar x.
:return: The sign of x \in (+1, -1, 0).
"""
if x > 0:
return +1
elif x < 0:
return -1
elif x == 0:
return 0
### Checks
[docs]def array_equal(A, B, eps=1e-9):
"""
Are arrays A and B equal?
:param A: Array.
:param B: Array.
:param eps: Tolerance.
:return: True/False.
"""
if A.ndim != B.ndim:
return False
if A.shape != B.shape:
return False
if np.mean(A - B) > eps:
return False
return True
[docs]def is_image(x):
"""
Is x an image?
i.e. numpy array of 2 or 3 dimensions.
:param x: Input.
:return: True/False.
"""
if not isinstance(x, np.ndarray):
return False
if x.ndim not in [2, 3]:
return False
return True
[docs]def is_gray_image(x):
"""
Is x a gray image?
:param x: Input.
:return: True/False.
"""
if not is_image(x):
return False
squeezed = x.squeeze()
if not squeezed.ndim == 2:
return False
return True
[docs]def is_uint8_image(x):
"""
Is x a uint8 image?
:param x: Input.
:return: True/False.
"""
if not is_image(x):
return False
if x.dtype != np.uint8:
return False
return True
[docs]def check_image(x):
"""
Check if is an image.
If gray make sure it is 'squeezed' correctly.
:param x: Input.
:return: True/False.
"""
assert is_image(x)
if is_gray_image(x):
x = x.squeeze()
return x