Metadata-Version: 2.1
Name: glcmbin5
Version: 0.1.0b0
Summary: Binned Cython 5 Feature GLCM
Home-page: https://github.com/Eve-ning/glcm
Author: evening
Author-email: dev_evening@hotmail.com
License: UNKNOWN
Description: # Binned Cython 5 Feature GLCM
        
        ![Result](result.jpg)
        
        [**Photo by Flo Maderebner from Pexels**](https://www.pexels.com/@fmaderebner)
        
        800 Times faster, the above image takes 5.7 Days to process, compared to 9.8 Minutes with `glcmbin5`
        
        *Performance will vary with devices*
        
        ```
        pip install glcmbin5
        ```
        
        ## Motivation
        
        There are 2 main improvements, speed and memory size
        
        ### Speed
        
        This is >800 times faster than using ``skimage.feature.graycomatrix`` and ``graycoprops``
        because this is Cython optimized.
        
        With a *2000x1000x3* image, it takes around 2 minutes.
        Compared to a **33 hours** with ``skimage``
        
        ```
        GLCM Progress: 100%|â–ˆâ–ˆâ–ˆâ–ˆâ–ˆâ–ˆâ–ˆâ–ˆâ–ˆâ–ˆ| 12/12 [02:27<00:00, 12.30s/it]
        ```
        
        ### Memory Size
        
        If you don't *bin* the array before calculating GLCM, you'll end up with an extremely
        large GLCM.
        
        With this algorithm, I omit generating the whole GLCM, instead, it's integrated in
        the GLCM feature calculation. Memory used is freed asap.
        
        Plus, decreasing the GLCM size improves performance significantly.
        
        ## Example
        
        You can also see an example in [`/examples`](https://github.com/Eve-ning/glcm/tree/master/examples)
        
        ```python
        from glcm.glcm import CyGLCM
        import numpy as np
        ar = ...
        glcm = CyGLCM(ar.astype(np.float32),
                      radius=3,
                      bins=8,
                      pairs=('H', 'V', 'SE', 'NE')
                      ).create_glcm()
        ```
        
        ## Arguments
        
        - **radius**: The radius of the GLCM window
        - **bins**: The number of bins to use
        - **pairs**:
          - **H**: Horizontal Pair
          - **V**: Vertical Pair
          - **SE**: South-East Diagonal Pair
          - **NE**: North-East Diagonal Pair
        
        ## I/O
        
        **Input**:
        - `ndim = 3`
        - `shape=(in_dim0, in_dim1, channel)`
        
        **Output**:
        - `ndim = 4`
        - `shape=(in_dim0, in_dim1, channel, features)`
        - Methods:
          - Contrast 
          - Correlation
          - Angular Second Moment
          - GLCM Mean
          - GLCM Variance
        
        ## Progress Bar
        
        The progress bar value is the current pair calculated.
        
        ## Gotchas
        
        ### GLCM Shrink
        
        The resulting GLCM array will be smaller than the original.
        
        *GLCM Dimension = Dimension - (2 * radius + 1) = Dimension - Diameter*
        
        The + 1 comes from the pairing.
        
        ### Data Type `float32`
        
        Arrays **MUST BE** in ``np.float32``, you need to cast it.
        ```
        ar.astype(np.float32)
        ```
        
        ## Features
        
        Based on [GLCM Texture: A Tutorial v. 3.0 March 2017](https://prism.ucalgary.ca/handle/1880/51900).
        
        For an effective segmentation, we just need 5 features as selected here.
        
        Many features are not significantly orthogonal, hence more will introduce redundancy.
        
        Chosen methods are for simplicity and efficiency in coding. 
        
        ## Binning
        
        Arrays are **Binned** before going through GLCM.
        
        All arrays will be processed to integer values `[0,bin-1]` band-independently.
        
        # Custom Cython Build
        
        Run this command with the `c_setup.py` here
        ```
        python c_setup.py build_ext --inplace
        ```
        
        # What's the magic?
        
        There are several optimizations
        
        1) It's written mainly in Cython (with little required Python calls)
        2) Binning before running the GLCM decreases required GLCM calls
        
        # Citation
        
        If you have used or referenced any of the code in the repository,
        please kindly cite
        
        ```
        @misc{glcmbin5,
          author = {John Chang},
          title = {Binned Cython 5 Feature GLCM},
          year = {2021},
          publisher = {GitHub},
          journal = {GitHub Repository},
          howpublished = {\url{https://github.com/Eve-ning/glcm}},
        }
        ```
        
        # Acknowledgements
        
        - [Dr. Ji-Jon Sit](https://dr.ntu.edu.sg/cris/rp/rp00175) for hosting the parent project [`Eve-ning/FRModel`](https://github.com/Eve-ning/FRModel) which lead to this algorithm
        - [Wang Ji Fei](https://fass.nus.edu.sg/geog/people/wang-jifei/) for discovering GLCM Binning optimization.
        - [GLCM Texture: A Tutorial v. 3.0 March 2017](https://prism.ucalgary.ca/handle/1880/51900) for providing a
        simple tutorial to guide this implementation.
        
        
        # Annex
        
        ## Speed Benchmark with `skimage.feature.greycomatrix`
        
        ```python
        
        import time
        
        import PIL.Image
        import numpy as np
        from matplotlib import pyplot as plt
        from skimage.feature import greycomatrix, greycoprops
        #%%
        
        image = np.asarray(PIL.Image.open("sample.jpg"))[::2,::2,0]
        
        s = time.time()
        for i in range(10000):
            glcm = greycomatrix(np.random.randint(0, 192, [5, 5]).astype(np.uint8), [1], [0])
            g = greycoprops(glcm, 'contrast')
            g = greycoprops(glcm, 'dissimilarity')
            g = greycoprops(glcm, 'energy')
            g = greycoprops(glcm, 'ASM')
            g = greycoprops(glcm, 'correlation')
        
        e = time.time()
        
        # / 10000 for each window
        # 1116 * 1991 because the image has that many windows
        # 3 for 3 channels
        # /147 for 2m27s of my current timing
        # ~ 832.0464063705289
        print(((e-s) * 8 / 10000 * 1116 * 1991 * 3)/147)
        ```
        
Platform: UNKNOWN
Classifier: Development Status :: 3 - Alpha
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.7
Description-Content-Type: text/markdown
