|
@@ -9,34 +9,17 @@ from skimage import io, color
|
|
|
|
|
|
import cv2
|
|
import cv2
|
|
|
|
|
|
-def get_image_path(image):
|
|
|
|
- """
|
|
|
|
- @brief Returns file path of PIL Image
|
|
|
|
- @param PIL Image
|
|
|
|
- @return image path
|
|
|
|
-
|
|
|
|
- >>> from PIL import Image
|
|
|
|
- >>> from ipfml import metrics
|
|
|
|
- >>> img = Image.open('./images/test_img.png')
|
|
|
|
- >>> path = metrics.get_image_path(img)
|
|
|
|
- >>> 'images/test_img.png' in path
|
|
|
|
- True
|
|
|
|
- """
|
|
|
|
|
|
|
|
- if hasattr(image, 'filename'):
|
|
|
|
- file_path = image.filename
|
|
|
|
- else:
|
|
|
|
- raise Exception("Image provided is not correct, required filename property...")
|
|
|
|
|
|
+def get_SVD(image):
|
|
|
|
+ """Transforms Image using SVD compression
|
|
|
|
|
|
- return file_path
|
|
|
|
|
|
+ Args:
|
|
|
|
+ image: image to convert into SVD compression
|
|
|
|
|
|
-def get_SVD(image):
|
|
|
|
- """
|
|
|
|
- @brief Transforms Image into SVD
|
|
|
|
- @param image to convert
|
|
|
|
- @return U, s, V image decomposition
|
|
|
|
|
|
+ Return:
|
|
|
|
+ U, s, V obtained from SVD compression
|
|
|
|
|
|
- Usage :
|
|
|
|
|
|
+ Usage:
|
|
|
|
|
|
>>> from PIL import Image
|
|
>>> from PIL import Image
|
|
>>> from ipfml import metrics
|
|
>>> from ipfml import metrics
|
|
@@ -51,13 +34,17 @@ def get_SVD(image):
|
|
"""
|
|
"""
|
|
return svd(image, full_matrices=False)
|
|
return svd(image, full_matrices=False)
|
|
|
|
|
|
|
|
+
|
|
def get_SVD_s(image):
|
|
def get_SVD_s(image):
|
|
- """
|
|
|
|
- @brief Transforms Image into SVD and returns only 's' part
|
|
|
|
- @param image to convert
|
|
|
|
- @return s
|
|
|
|
|
|
+ """Transforms Image into SVD and returns only 's' part
|
|
|
|
|
|
- Usage :
|
|
|
|
|
|
+ Args:
|
|
|
|
+ image: image to convert
|
|
|
|
+
|
|
|
|
+ Returns:
|
|
|
|
+ vector of singular values obtained from SVD compression
|
|
|
|
+
|
|
|
|
+ Usage:
|
|
|
|
|
|
>>> from PIL import Image
|
|
>>> from PIL import Image
|
|
>>> from ipfml import metrics
|
|
>>> from ipfml import metrics
|
|
@@ -69,13 +56,17 @@ def get_SVD_s(image):
|
|
U, s, V = svd(image, full_matrices=False)
|
|
U, s, V = svd(image, full_matrices=False)
|
|
return s
|
|
return s
|
|
|
|
|
|
|
|
+
|
|
def get_SVD_U(image):
|
|
def get_SVD_U(image):
|
|
- """
|
|
|
|
- @brief Transforms Image into SVD and returns only 'U' part
|
|
|
|
- @param image to convert
|
|
|
|
- @return U
|
|
|
|
|
|
+ """Transforms Image into SVD and returns only 'U' part
|
|
|
|
|
|
- Usage :
|
|
|
|
|
|
+ Args:
|
|
|
|
+ image: image to convert
|
|
|
|
+
|
|
|
|
+ Returns:
|
|
|
|
+ U matrix from SVD compression
|
|
|
|
+
|
|
|
|
+ Usage:
|
|
|
|
|
|
>>> from PIL import Image
|
|
>>> from PIL import Image
|
|
>>> from ipfml import metrics
|
|
>>> from ipfml import metrics
|
|
@@ -88,11 +79,15 @@ def get_SVD_U(image):
|
|
U, s, V = svd(image, full_matrices=False)
|
|
U, s, V = svd(image, full_matrices=False)
|
|
return U
|
|
return U
|
|
|
|
|
|
|
|
+
|
|
def get_SVD_V(image):
|
|
def get_SVD_V(image):
|
|
- """
|
|
|
|
- @brief Transforms Image into SVD and returns only 'V' part
|
|
|
|
- @param image to convert
|
|
|
|
- @return V
|
|
|
|
|
|
+ """Transforms Image into SVD and returns only 'V' part
|
|
|
|
+
|
|
|
|
+ Args:
|
|
|
|
+ image: image to convert
|
|
|
|
+
|
|
|
|
+ Returns:
|
|
|
|
+ V matrix obtained from SVD compression
|
|
|
|
|
|
Usage :
|
|
Usage :
|
|
|
|
|
|
@@ -107,13 +102,17 @@ def get_SVD_V(image):
|
|
U, s, V = svd(image, full_matrices=False)
|
|
U, s, V = svd(image, full_matrices=False)
|
|
return V
|
|
return V
|
|
|
|
|
|
|
|
+
|
|
def get_LAB(image):
|
|
def get_LAB(image):
|
|
- """
|
|
|
|
- @brief Transforms PIL RGB Image into LAB
|
|
|
|
- @param image to convert
|
|
|
|
- @return Lab information
|
|
|
|
|
|
+ """Transforms RGB Image into Lab
|
|
|
|
|
|
- Usage :
|
|
|
|
|
|
+ Args:
|
|
|
|
+ image: image to convert
|
|
|
|
+
|
|
|
|
+ Returns:
|
|
|
|
+ Lab information
|
|
|
|
+
|
|
|
|
+ Usage:
|
|
|
|
|
|
>>> from PIL import Image
|
|
>>> from PIL import Image
|
|
>>> from ipfml import metrics
|
|
>>> from ipfml import metrics
|
|
@@ -125,11 +124,15 @@ def get_LAB(image):
|
|
|
|
|
|
return color.rgb2lab(image)
|
|
return color.rgb2lab(image)
|
|
|
|
|
|
|
|
+
|
|
def get_LAB_L(image):
|
|
def get_LAB_L(image):
|
|
- """
|
|
|
|
- @brief Transforms PIL RGB Image into LAB and returns L
|
|
|
|
- @param image to convert
|
|
|
|
- @return Lab information
|
|
|
|
|
|
+ """Transforms RGB Image into Lab and returns L
|
|
|
|
+
|
|
|
|
+ Args:
|
|
|
|
+ image: image to convert
|
|
|
|
+
|
|
|
|
+ Returns:
|
|
|
|
+ The L chanel from Lab information
|
|
|
|
|
|
>>> from PIL import Image
|
|
>>> from PIL import Image
|
|
>>> from ipfml import metrics
|
|
>>> from ipfml import metrics
|
|
@@ -142,51 +145,63 @@ def get_LAB_L(image):
|
|
lab = get_LAB(image)
|
|
lab = get_LAB(image)
|
|
return lab[:, :, 0]
|
|
return lab[:, :, 0]
|
|
|
|
|
|
-def get_LAB_A(image):
|
|
|
|
- """
|
|
|
|
- @brief Transforms PIL RGB Image into LAB and returns A
|
|
|
|
- @param image to convert
|
|
|
|
- @return Lab information
|
|
|
|
|
|
|
|
- Usage :
|
|
|
|
|
|
+def get_LAB_a(image):
|
|
|
|
+ """Transforms RGB Image into LAB and returns a
|
|
|
|
+
|
|
|
|
+ Args:
|
|
|
|
+ image: image to convert
|
|
|
|
+
|
|
|
|
+ Returns:
|
|
|
|
+ The a chanel from Lab information
|
|
|
|
+
|
|
|
|
+ Usage:
|
|
|
|
|
|
>>> from PIL import Image
|
|
>>> from PIL import Image
|
|
>>> from ipfml import metrics
|
|
>>> from ipfml import metrics
|
|
>>> img = Image.open('./images/test_img.png')
|
|
>>> img = Image.open('./images/test_img.png')
|
|
- >>> A = metrics.get_LAB_A(img)
|
|
|
|
- >>> A.shape
|
|
|
|
|
|
+ >>> a = metrics.get_LAB_a(img)
|
|
|
|
+ >>> a.shape
|
|
(200, 200)
|
|
(200, 200)
|
|
"""
|
|
"""
|
|
|
|
|
|
lab = get_LAB(image)
|
|
lab = get_LAB(image)
|
|
return lab[:, :, 1]
|
|
return lab[:, :, 1]
|
|
|
|
|
|
-def get_LAB_B(image):
|
|
|
|
- """
|
|
|
|
- @brief Transforms PIL RGB Image into LAB and returns B
|
|
|
|
- @param image to convert
|
|
|
|
- @return Lab information
|
|
|
|
|
|
+
|
|
|
|
+def get_LAB_b(image):
|
|
|
|
+ """Transforms RGB Image into LAB and returns b
|
|
|
|
+
|
|
|
|
+ Args:
|
|
|
|
+ image: image to convert
|
|
|
|
+
|
|
|
|
+ Returns:
|
|
|
|
+ The b chanel from Lab information
|
|
|
|
|
|
Usage :
|
|
Usage :
|
|
|
|
|
|
>>> from PIL import Image
|
|
>>> from PIL import Image
|
|
>>> from ipfml import metrics
|
|
>>> from ipfml import metrics
|
|
>>> img = Image.open('./images/test_img.png')
|
|
>>> img = Image.open('./images/test_img.png')
|
|
- >>> B = metrics.get_LAB_B(img)
|
|
|
|
- >>> B.shape
|
|
|
|
|
|
+ >>> b = metrics.get_LAB_b(img)
|
|
|
|
+ >>> b.shape
|
|
(200, 200)
|
|
(200, 200)
|
|
"""
|
|
"""
|
|
|
|
|
|
lab = get_LAB(image)
|
|
lab = get_LAB(image)
|
|
return lab[:, :, 2]
|
|
return lab[:, :, 2]
|
|
|
|
|
|
|
|
+
|
|
def get_XYZ(image):
|
|
def get_XYZ(image):
|
|
- """
|
|
|
|
- @brief Transforms PIL RGB Image into XYZ
|
|
|
|
- @param image to convert
|
|
|
|
- @return Lab information
|
|
|
|
|
|
+ """Transforms RGB Image into XYZ
|
|
|
|
|
|
- Usage :
|
|
|
|
|
|
+ Args:
|
|
|
|
+ image: image to convert
|
|
|
|
+
|
|
|
|
+ Returns:
|
|
|
|
+ XYZ information obtained from transformation
|
|
|
|
+
|
|
|
|
+ Usage:
|
|
|
|
|
|
>>> from PIL import Image
|
|
>>> from PIL import Image
|
|
>>> from ipfml import metrics
|
|
>>> from ipfml import metrics
|
|
@@ -197,13 +212,17 @@ def get_XYZ(image):
|
|
|
|
|
|
return color.rgb2xyz(image)
|
|
return color.rgb2xyz(image)
|
|
|
|
|
|
|
|
+
|
|
def get_XYZ_X(image):
|
|
def get_XYZ_X(image):
|
|
- """
|
|
|
|
- @brief Transforms PIL RGB Image into XYZ and returns X
|
|
|
|
- @param image to convert
|
|
|
|
- @return Lab information
|
|
|
|
|
|
+ """Transforms RGB Image into XYZ and returns X
|
|
|
|
|
|
- Usage :
|
|
|
|
|
|
+ Args:
|
|
|
|
+ image: image to convert
|
|
|
|
+
|
|
|
|
+ Returns:
|
|
|
|
+ The X chanel from XYZ information
|
|
|
|
+
|
|
|
|
+ Usage:
|
|
|
|
|
|
>>> from PIL import Image
|
|
>>> from PIL import Image
|
|
>>> from ipfml import metrics
|
|
>>> from ipfml import metrics
|
|
@@ -216,13 +235,17 @@ def get_XYZ_X(image):
|
|
xyz = color.rgb2xyz(image)
|
|
xyz = color.rgb2xyz(image)
|
|
return xyz[:, :, 0]
|
|
return xyz[:, :, 0]
|
|
|
|
|
|
|
|
+
|
|
def get_XYZ_Y(image):
|
|
def get_XYZ_Y(image):
|
|
- """
|
|
|
|
- @brief Transforms PIL RGB Image into XYZ and returns Y
|
|
|
|
- @param image to convert
|
|
|
|
- @return Lab information
|
|
|
|
|
|
+ """Transforms RGB Image into XYZ and returns Y
|
|
|
|
|
|
- Usage :
|
|
|
|
|
|
+ Args:
|
|
|
|
+ image: image to convert
|
|
|
|
+
|
|
|
|
+ Returns:
|
|
|
|
+ The Y chanel from XYZ information
|
|
|
|
+
|
|
|
|
+ Usage:
|
|
|
|
|
|
>>> from PIL import Image
|
|
>>> from PIL import Image
|
|
>>> from ipfml import metrics
|
|
>>> from ipfml import metrics
|
|
@@ -235,13 +258,17 @@ def get_XYZ_Y(image):
|
|
xyz = color.rgb2xyz(image)
|
|
xyz = color.rgb2xyz(image)
|
|
return xyz[:, :, 1]
|
|
return xyz[:, :, 1]
|
|
|
|
|
|
|
|
+
|
|
def get_XYZ_Z(image):
|
|
def get_XYZ_Z(image):
|
|
- """
|
|
|
|
- @brief Transforms PIL RGB Image into XYZ and returns Z
|
|
|
|
- @param image to convert
|
|
|
|
- @return Lab information
|
|
|
|
|
|
+ """Transforms RGB Image into XYZ and returns Z
|
|
|
|
|
|
- Usage :
|
|
|
|
|
|
+ Args:
|
|
|
|
+ image: image to convert
|
|
|
|
+
|
|
|
|
+ Returns:
|
|
|
|
+ The Z chanel from XYZ information
|
|
|
|
+
|
|
|
|
+ Usage:
|
|
|
|
|
|
>>> from PIL import Image
|
|
>>> from PIL import Image
|
|
>>> from ipfml import metrics
|
|
>>> from ipfml import metrics
|
|
@@ -254,35 +281,55 @@ def get_XYZ_Z(image):
|
|
xyz = color.rgb2xyz(image)
|
|
xyz = color.rgb2xyz(image)
|
|
return xyz[:, :, 2]
|
|
return xyz[:, :, 2]
|
|
|
|
|
|
-def get_low_bits_img(image, bind=15):
|
|
|
|
- """
|
|
|
|
- @brief Returns Image or Numpy array with data information reduced using only low bits
|
|
|
|
- @param image to convert
|
|
|
|
- @bind optional : bits to keep using & Bitwise operator
|
|
|
|
- @return Numpy array with reduced values
|
|
|
|
|
|
|
|
- Usage :
|
|
|
|
|
|
+def get_low_bits_img(image, nb_bits=4):
|
|
|
|
+ """Returns Image or Numpy array with data information reduced using only low bits
|
|
|
|
+
|
|
|
|
+ Args:
|
|
|
|
+ image: image to convert
|
|
|
|
+ nb_bits: optional parameter which indicates the number of bits to keep
|
|
|
|
+
|
|
|
|
+ Returns:
|
|
|
|
+ Numpy array with reduced values
|
|
|
|
+
|
|
|
|
+ Usage:
|
|
|
|
|
|
>>> from PIL import Image
|
|
>>> from PIL import Image
|
|
>>> from ipfml import metrics
|
|
>>> from ipfml import metrics
|
|
>>> img = Image.open('./images/test_img.png')
|
|
>>> img = Image.open('./images/test_img.png')
|
|
- >>> low_bits_img = metrics.get_low_bits_img(img)
|
|
|
|
|
|
+ >>> low_bits_img = metrics.get_low_bits_img(img, 5)
|
|
>>> low_bits_img.shape
|
|
>>> low_bits_img.shape
|
|
(200, 200, 3)
|
|
(200, 200, 3)
|
|
"""
|
|
"""
|
|
|
|
|
|
|
|
+ if nb_bits <= 0:
|
|
|
|
+ raise ValueError(
|
|
|
|
+ "unexpected value of number of bits to keep. @nb_bits needs to be positive and greater than 0."
|
|
|
|
+ )
|
|
|
|
+
|
|
|
|
+ if nb_bits > 8:
|
|
|
|
+ raise ValueError(
|
|
|
|
+ "Unexpected value of number of bits to keep. @nb_bits needs to be in interval [1, 8]."
|
|
|
|
+ )
|
|
|
|
+
|
|
img_arr = np.array(image)
|
|
img_arr = np.array(image)
|
|
|
|
|
|
- return img_arr & bind
|
|
|
|
|
|
+ bits_values = sum([pow(2, i - 1) for i in range(1, nb_bits + 1)])
|
|
|
|
+
|
|
|
|
+ return img_arr & bits_values
|
|
|
|
+
|
|
|
|
|
|
def get_bits_img(image, interval):
|
|
def get_bits_img(image, interval):
|
|
- """
|
|
|
|
- @brief Returns only bits specified into the interval
|
|
|
|
- @param image to convert using this interval of bits value to keep
|
|
|
|
- @param interval (begin, end) of bits values
|
|
|
|
- @return Numpy array with reduced values
|
|
|
|
|
|
+ """Returns only bits specified into the interval
|
|
|
|
|
|
- Usage :
|
|
|
|
|
|
+ Args:
|
|
|
|
+ image: image to convert using this interval of bits value to keep
|
|
|
|
+ interval: (begin, end) of bits values
|
|
|
|
+
|
|
|
|
+ Returns:
|
|
|
|
+ Numpy array with reduced values
|
|
|
|
+
|
|
|
|
+ Usage:
|
|
|
|
|
|
>>> from PIL import Image
|
|
>>> from PIL import Image
|
|
>>> from ipfml import metrics
|
|
>>> from ipfml import metrics
|
|
@@ -295,32 +342,50 @@ def get_bits_img(image, interval):
|
|
img_arr = np.array(image)
|
|
img_arr = np.array(image)
|
|
begin, end = interval
|
|
begin, end = interval
|
|
|
|
|
|
|
|
+ if begin < 1:
|
|
|
|
+ raise ValueError(
|
|
|
|
+ "Unexpected value of interval. Interval min value needs to be >= 1."
|
|
|
|
+ )
|
|
|
|
+
|
|
|
|
+ if end > 8:
|
|
|
|
+ raise ValueError(
|
|
|
|
+ "Unexpected value of interval. Interval min value needs to be <= 8."
|
|
|
|
+ )
|
|
|
|
+
|
|
|
|
+ if begin >= end:
|
|
|
|
+ raise ValueError("Unexpected interval values order.")
|
|
|
|
+
|
|
bits_values = sum([pow(2, i - 1) for i in range(begin, end + 1)])
|
|
bits_values = sum([pow(2, i - 1) for i in range(begin, end + 1)])
|
|
|
|
|
|
return img_arr & bits_values
|
|
return img_arr & bits_values
|
|
|
|
|
|
|
|
|
|
def gray_to_mscn(image):
|
|
def gray_to_mscn(image):
|
|
- """
|
|
|
|
- @brief Convert Grayscale Image into Mean Subtracted Contrast Normalized (MSCN)
|
|
|
|
- @param grayscale image numpy array or PIL RGB image
|
|
|
|
|
|
+ """Convert Grayscale Image into Mean Subtracted Contrast Normalized (MSCN)
|
|
|
|
|
|
- Usage :
|
|
|
|
|
|
+ Args:
|
|
|
|
+ image: grayscale image
|
|
|
|
+
|
|
|
|
+ Returns:
|
|
|
|
+ MSCN matrix obtained from transformation
|
|
|
|
+
|
|
|
|
+ Usage:
|
|
|
|
|
|
>>> from PIL import Image
|
|
>>> from PIL import Image
|
|
- >>> from ipfml import image_processing
|
|
|
|
|
|
+ >>> from ipfml import processing
|
|
>>> img = Image.open('./images/test_img.png')
|
|
>>> img = Image.open('./images/test_img.png')
|
|
- >>> img_mscn = image_processing.rgb_to_mscn(img)
|
|
|
|
|
|
+ >>> img_mscn = processing.rgb_to_mscn(img)
|
|
>>> img_mscn.shape
|
|
>>> img_mscn.shape
|
|
(200, 200)
|
|
(200, 200)
|
|
"""
|
|
"""
|
|
|
|
|
|
- s = 7/6
|
|
|
|
- blurred = cv2.GaussianBlur(image, (7, 7), s) # apply gaussian blur to the image
|
|
|
|
|
|
+ s = 7 / 6
|
|
|
|
+ blurred = cv2.GaussianBlur(image, (7, 7),
|
|
|
|
+ s) # apply gaussian blur to the image
|
|
blurred_sq = blurred * blurred
|
|
blurred_sq = blurred * blurred
|
|
sigma = cv2.GaussianBlur(image * image, (7, 7), s)
|
|
sigma = cv2.GaussianBlur(image * image, (7, 7), s)
|
|
- sigma = abs(sigma - blurred_sq) ** 0.5
|
|
|
|
- sigma = sigma + 1.0/255 # avoid DivideByZero Exception
|
|
|
|
- mscn = (image - blurred)/sigma # MSCN(i, j) image
|
|
|
|
|
|
+ sigma = abs(sigma - blurred_sq)**0.5
|
|
|
|
+ sigma = sigma + 1.0 / 255 # avoid DivideByZero Exception
|
|
|
|
+ mscn = (image - blurred) / sigma # MSCN(i, j) image
|
|
|
|
|
|
return mscn
|
|
return mscn
|