Browse Source

Add of metrics tests

Jerome Buisine 1 year ago
parent
commit
420f833455
5 changed files with 288 additions and 21 deletions
  1. 2 1
      MANIFEST.in
  2. 57 0
      README.md
  3. BIN
      images/test_img.png
  4. 73 12
      ipfml/image_processing.py
  5. 156 8
      ipfml/metrics.py

+ 2 - 1
MANIFEST.in

@@ -1 +1,2 @@
-include README.rst
+include README.rst
+include images/*.png

+ 57 - 0
README.md

@@ -0,0 +1,57 @@
+IPFML
+=====
+
+Image Processing For Machine Learning package.
+
+How to use ?
+------------
+
+To use, simply do::
+
+```python
+from PIL import Image
+from ipfml import image_processing
+img = Image.open('path/to/image.png')
+s = image_processing.get_LAB_L_SVD_s(img)
+```
+
+
+Modules
+-------
+
+This project contains modules.
+
+- **img_processing** : *PIL image processing part*
+    - fig2data(fig): *Convert a Matplotlib figure to a 3D numpy array with RGB channels and return it*
+    - fig2img(fig): *Convert a Matplotlib figure to a PIL Image in RGB format and return it*
+    - get_LAB_L_SVD_U(image): *Returns U SVD from L of LAB Image information*
+    - get_LAB_L_SVD_s(image): *Returns s (Singular values) SVD from L of LAB Image information*
+    - get_LAB_L_SVD_V(image): *Returns V SVD from L of LAB Image information*
+    - divide_in_blocks(image, block_size): Divide image into equal size blocks
+
+- **metrics** : *Metrics computation of PIL image*
+    - get_SVD(image): *Transforms PIL Image into SVD*
+    - get_SVD_U(image): *Transforms PIL Image into SVD and returns only 'U' part*
+    - get_SVD_s(image): *Transforms PIL Image into SVD and returns only 's' part*
+    - get_SVD_V(image): *Transforms PIL Image into SVD and returns only 'V' part*
+
+    - get_LAB(image): *Transforms PIL Image into LAB*
+    - get_LAB_L(image): *Transforms PIL Image into LAB and returns only 'L' part*
+    - get_LAB_A(image): *Transforms PIL Image into LAB and returns only 'A' part*
+    - get_LAB_B(image): *Transforms PIL Image into LAB and returns only 'B' part*
+
+    - get_XYZ(image): *Transforms PIL Image into XYZ*
+    - get_XYZ_X(image): *Transforms PIL Image into XYZ and returns only 'X' part*
+    - get_XYZ_Y(image): *Transforms PIL Image into XYZ and returns only 'Y' part*
+    - get_XYZ_Z(image): *Transforms PIL Image into XYZ and returns only 'Z' part*
+
+- **ts_model_helper** : *contains helpful function to save or display model information and performance of tensorflow model*
+    - save(history, filename): *Function which saves data from neural network model*
+    - show(history, filename): *Function which shows data from neural network model*
+
+All these modules will be enhanced during development of the project
+
+How to contribute
+-----------------
+
+This git project uses [git-flow](https://danielkummer.github.io/git-flow-cheatsheet/) implementation. You are free to contribute to it.

BIN
images/test_img.png


+ 73 - 12
ipfml/image_processing.py

@@ -39,6 +39,19 @@ def get_LAB_L_SVD(image):
     @brief Returns Singular values from LAB L Image information
     @param fig a matplotlib figure
     @return a Python Imaging Library (PIL) image : default size (480,640,3)
+
+    Usage :
+
+    >>> from PIL import Image
+    >>> from ipfml import image_processing
+    >>> img = Image.open('./images/test_img.png')
+    >>> U, s, V = image_processing.get_LAB_L_SVD(img)
+    >>> U.shape
+    (200, 200)
+    >>> len(s)
+    200
+    >>> V.shape
+    (200, 200)
     """
     L = metrics.get_LAB_L(image)
     return metrics.get_SVD(L)
@@ -48,6 +61,15 @@ def get_LAB_L_SVD_s(image):
     @brief Returns s (Singular values) SVD from L of LAB Image information
     @param PIL Image
     @return vector of singular values
+
+    Usage :
+
+    >>> from PIL import Image
+    >>> from ipfml import image_processing
+    >>> img = Image.open('./images/test_img.png')
+    >>> s = image_processing.get_LAB_L_SVD_s(img)
+    >>> len(s)
+    200
     """
     L = metrics.get_LAB_L(image)
     return metrics.get_SVD_s(L)
@@ -57,6 +79,15 @@ def get_LAB_L_SVD_U(image):
     @brief Returns U SVD from L of LAB Image information
     @param PIL Image
     @return vector of singular values
+
+    Usage :
+
+    >>> from PIL import Image
+    >>> from ipfml import image_processing
+    >>> img = Image.open('./images/test_img.png')
+    >>> U = image_processing.get_LAB_L_SVD_U(img)
+    >>> U.shape
+    (200, 200)
     """
     L = metrics.get_LAB_L(image)
     return metrics.get_SVD_U(L)
@@ -66,14 +97,24 @@ def get_LAB_L_SVD_V(image):
     @brief Returns V SVD from L of LAB Image information
     @param PIL Image
     @return vector of singular values
+
+    Usage :
+
+    >>> from PIL import Image
+    >>> from ipfml import image_processing
+    >>> img = Image.open('./images/test_img.png')
+    >>> V = image_processing.get_LAB_L_SVD_V(img)
+    >>> V.shape
+    (200, 200)
     """
+
     L = metrics.get_LAB_L(image)
     return metrics.get_SVD_V(L)
 
 def divide_in_blocks(image, block_size):
     '''
     @brief Divide image into equal size blocks
-    @param img - PIL Image
+    @param img - PIL Image or numpy array
     @param block - tuple (width, height) representing the size of each dimension of the block
     @return list containing all PIL Image block (in RGB)
 
@@ -82,32 +123,52 @@ def divide_in_blocks(image, block_size):
     >>> import numpy as np
     >>> from PIL import Image
     >>> from ipfml import image_processing
+    >>> from ipfml import metrics
     >>> image_values = np.random.randint(255, size=(800, 800, 3))
-    >>> img = Image.fromarray(image_values.astype('uint8'), 'RGB')
-    >>> blocks = divide_in_blocks(img, (20, 20))
+    >>> blocks = divide_in_blocks(image_values, (20, 20))
     >>> len(blocks)
     1600
     >>> blocks[0].width
     20
     >>> blocks[0].height
     20
+    >>> img_l = Image.open('./images/test_img.png')
+    >>> L = metrics.get_LAB_L(img_l)
+    >>> blocks_L = divide_in_blocks(L, (100, 100))
+    >>> len(blocks_L)
+    4
+    >>> blocks_L[0].width
+    100
     '''
 
     blocks = []
-
+    mode = 'RGB'
+
+    # check input type (PIL Image or numpy array)
+    if type(image) is Image:
+        image_array = np.array(image)
+        image_width = image.width
+        image_height = image.height
+    else:
+        image_array = image
+
+        if image.ndim != 3:
+            mode = 'L'
+            image_width, image_height = image.shape
+        else:
+            image_width, image_height, _ = image.shape
+        
     # check size compatibility
     width, height = block_size
 
-    if(image.width % width != 0):
+    if(image_width % width != 0):
         raise "Width size issue, block size not compatible"
     
-    if(image.height % height != 0):
+    if(image_height % height != 0):
         raise "Height size issue, block size not compatible"
 
-    nb_block_width = image.width / width
-    nb_block_height = image.height / height
-
-    image_array = np.array(image)
+    nb_block_width = image_width / width
+    nb_block_height = image_height / height
 
     for i in range(int(nb_block_width)):
 
@@ -117,8 +178,8 @@ def divide_in_blocks(image, block_size):
 
             begin_y = j * height
 
-            # getting subblock information
+            # getting sub block information
             current_block = image_array[begin_x:(begin_x + width), begin_y:(begin_y + height)]
-            blocks.append(Image.fromarray(current_block.astype('uint8'), 'RGB'))
+            blocks.append(Image.fromarray(current_block.astype('uint8'), mode))
 
     return blocks

+ 156 - 8
ipfml/metrics.py

@@ -7,11 +7,45 @@ import numpy as np
 from sklearn import preprocessing
 from skimage import io, color
 
+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...")    
+
+    return file_path
+
 def get_SVD(image):
     """
     @brief Transforms Image into SVD
     @param image to convert
     @return U, s, V image decomposition
+    
+    Usage : 
+
+    >>> from PIL import Image
+    >>> from ipfml import metrics
+    >>> img = Image.open('./images/test_img.png')
+    >>> U, s, V = metrics.get_SVD(img)
+    >>> U.shape
+    (200, 200, 3)
+    >>> len(s)
+    200
+    >>> V.shape
+    (200, 3, 3)
     """
     return svd(image, full_matrices=False)
 
@@ -20,6 +54,15 @@ def get_SVD_s(image):
     @brief Transforms Image into SVD and returns only 's' part
     @param image to convert
     @return s
+
+    Usage : 
+
+    >>> from PIL import Image
+    >>> from ipfml import metrics
+    >>> img = Image.open('./images/test_img.png')
+    >>> s = metrics.get_SVD_s(img)
+    >>> len(s)
+    200
     """
     U, s, V = svd(image, full_matrices=False)
     return s
@@ -29,7 +72,17 @@ def get_SVD_U(image):
     @brief Transforms Image into SVD and returns only 'U' part
     @param image to convert
     @return U
+
+    Usage :
+
+    >>> from PIL import Image
+    >>> from ipfml import metrics
+    >>> img = Image.open('./images/test_img.png')
+    >>> Lab = metrics.get_LAB(img)
+    >>> Lab.shape
+    (200, 200, 3)
     """
+
     U, s, V = svd(image, full_matrices=False)
     return U
 
@@ -38,7 +91,17 @@ def get_SVD_V(image):
     @brief Transforms Image into SVD and returns only 'V' part
     @param image to convert
     @return V
+    
+    Usage : 
+
+    >>> from PIL import Image
+    >>> from ipfml import metrics
+    >>> img = Image.open('./images/test_img.png')
+    >>> V = metrics.get_SVD_V(img)
+    >>> V.shape
+    (200, 3, 3)
     """
+
     U, s, V = svd(image, full_matrices=False)
     return V
 
@@ -47,8 +110,19 @@ def get_LAB(image):
     @brief Transforms PIL RGB Image into LAB 
     @param image to convert
     @return Lab information
+
+    Usage : 
+
+    >>> from PIL import Image
+    >>> from ipfml import metrics
+    >>> img = Image.open('./images/test_img.png')
+    >>> Lab = metrics.get_LAB(img)
+    >>> Lab.shape
+    (200, 200, 3)
     """
-    rgb = io.imread(image.filename)
+
+    file_path = get_image_path(image)
+    rgb = io.imread(file_path)
     return color.rgb2lab(rgb)
 
 def get_LAB_L(image):
@@ -56,8 +130,17 @@ def get_LAB_L(image):
     @brief Transforms PIL RGB Image into LAB and returns L
     @param image to convert
     @return Lab information
+    
+    >>> from PIL import Image
+    >>> from ipfml import metrics
+    >>> img = Image.open('./images/test_img.png')
+    >>> L = metrics.get_LAB_L(img)
+    >>> L.shape
+    (200, 200)
     """
-    rgb = io.imread(image.filename)
+    
+    file_path = get_image_path(image)
+    rgb = io.imread(file_path)
     lab = color.rgb2lab(rgb)
     return lab[:, :, 0]
 
@@ -66,8 +149,19 @@ def get_LAB_A(image):
     @brief Transforms PIL RGB Image into LAB and returns A
     @param image to convert
     @return Lab information
+    
+    Usage : 
+
+    >>> from PIL import Image
+    >>> from ipfml import metrics
+    >>> img = Image.open('./images/test_img.png')
+    >>> A = metrics.get_LAB_A(img)
+    >>> A.shape
+    (200, 200)
     """
-    rgb = io.imread(image.filename)
+
+    file_path = get_image_path(image)
+    rgb = io.imread(file_path)
     lab = color.rgb2lab(rgb)
     return lab[:, :, 1]
 
@@ -76,8 +170,19 @@ def get_LAB_B(image):
     @brief Transforms PIL RGB Image into LAB and returns B
     @param image to convert
     @return Lab information
+    
+    Usage : 
+
+    >>> from PIL import Image
+    >>> from ipfml import metrics
+    >>> img = Image.open('./images/test_img.png')
+    >>> B = metrics.get_LAB_B(img)
+    >>> B.shape
+    (200, 200)
     """
-    rgb = io.imread(image.filename)
+   
+    file_path = get_image_path(image)
+    rgb = io.imread(file_path)
     lab = color.rgb2lab(rgb)
     return lab[:, :, 2]
 
@@ -86,8 +191,18 @@ def get_XYZ(image):
     @brief Transforms PIL RGB Image into XYZ
     @param image to convert
     @return Lab information
+    
+    Usage : 
+
+    >>> from PIL import Image
+    >>> from ipfml import metrics
+    >>> img = Image.open('./images/test_img.png')
+    >>> metrics.get_XYZ(img).shape
+    (200, 200, 3)
     """
-    rgb = io.imread(image.filename)
+
+    file_path = get_image_path(image)
+    rgb = io.imread(file_path)
     return color.rgb2xyz(rgb)
 
 def get_XYZ_X(image):
@@ -95,8 +210,19 @@ def get_XYZ_X(image):
     @brief Transforms PIL RGB Image into XYZ and returns X
     @param image to convert
     @return Lab information
+
+    Usage : 
+
+    >>> from PIL import Image
+    >>> from ipfml import metrics
+    >>> img = Image.open('./images/test_img.png')
+    >>> x = metrics.get_XYZ_X(img)
+    >>> x.shape
+    (200, 200)
     """
-    rgb = io.imread(image.filename)
+
+    file_path = get_image_path(image)
+    rgb = io.imread(file_path)
     xyz = color.rgb2xyz(rgb)
     return xyz[:, :, 0]
 
@@ -105,8 +231,19 @@ def get_XYZ_Y(image):
     @brief Transforms PIL RGB Image into XYZ and returns Y
     @param image to convert
     @return Lab information
+
+    Usage :
+
+    >>> from PIL import Image
+    >>> from ipfml import metrics
+    >>> img = Image.open('./images/test_img.png')
+    >>> y = metrics.get_XYZ_Y(img)
+    >>> y.shape
+    (200, 200)
     """
-    rgb = io.imread(image.filename)
+
+    file_path = get_image_path(image)
+    rgb = io.imread(file_path)
     xyz = color.rgb2xyz(rgb)
     return xyz[:, :, 1]
 
@@ -115,7 +252,18 @@ def get_XYZ_Z(image):
     @brief Transforms PIL RGB Image into XYZ and returns Z
     @param image to convert
     @return Lab information
+
+    Usage : 
+
+    >>> from PIL import Image
+    >>> from ipfml import metrics
+    >>> img = Image.open('./images/test_img.png')
+    >>> z = metrics.get_XYZ_Z(img)
+    >>> z.shape
+    (200, 200)
     """
-    rgb = io.imread(image.filename)
+
+    file_path = get_image_path(image)
+    rgb = io.imread(file_path)
     xyz = color.rgb2xyz(rgb)
     return xyz[:, :, 2]