Package: glcmbin5
Binned Cython 5 Feature GLCMPhoto by Flo Maderebner from Pexels800 Times faster, the above image takes 5.7 Days to process, compared to 9.8 Minutes withglcmbin5Performance will vary with devicespip install glcmbin5MotivationThere are 2 main improvements, speed and memory sizeSpeedThis is >800 times faster than usingskimage.feature.graycomatrixandgraycopropsbecause this is Cython optimized.With a2000x1000x3image, it takes around 2 minutes.
Compared to a33 hourswithskimageGLCM Progress: 100%|â–ˆâ–ˆâ–ˆâ–ˆâ–ˆâ–ˆâ–ˆâ–ˆâ–ˆâ–ˆ| 12/12 [02:27<00:00, 12.30s/it]Memory SizeIf you don'tbinthe 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.ExampleYou can also see an example in/examplesfromglcm.glcmimportCyGLCMimportnumpyasnpar=...glcm=CyGLCM(ar.astype(np.float32),radius=3,bins=8,pairs=('H','V','SE','NE')).create_glcm()Argumentsradius: The radius of the GLCM windowbins: The number of bins to usepairs:H: Horizontal PairV: Vertical PairSE: South-East Diagonal PairNE: North-East Diagonal PairI/OInput:ndim = 3shape=(in_dim0, in_dim1, channel)Output:ndim = 4shape=(in_dim0, in_dim1, channel, features)Methods:ContrastCorrelationAngular Second MomentGLCM MeanGLCM VarianceProgress BarThe progress bar value is the current pair calculated.GotchasGLCM ShrinkThe resulting GLCM array will be smaller than the original.GLCM Dimension = Dimension - (2 * radius + 1) = Dimension - DiameterThe + 1 comes from the pairing.Data Typefloat32ArraysMUST BEinnp.float32, you need to cast it.ar.astype(np.float32)FeaturesBased onGLCM Texture: A Tutorial v. 3.0 March 2017.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.BinningArrays areBinnedbefore going through GLCM.All arrays will be processed to integer values[0,bin-1]band-independently.Custom Cython BuildRun this command with thec_setup.pyherepython c_setup.py build_ext --inplaceWhat's the magic?There are several optimizationsIt's written mainly in Cython (with little required Python calls)Binning before running the GLCM decreases required GLCM callsCitationIf 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}},
}AcknowledgementsDr. Ji-Jon Sitfor hosting the parent projectEve-ning/FRModelwhich lead to this algorithmWang Ji Feifor discovering GLCM Binning optimization.GLCM Texture: A Tutorial v. 3.0 March 2017for providing a
simple tutorial to guide this implementation.AnnexSpeed Benchmark withskimage.feature.greycomatriximporttimeimportPIL.Imageimportnumpyasnpfrommatplotlibimportpyplotaspltfromskimage.featureimportgreycomatrix,greycoprops#%%image=np.asarray(PIL.Image.open("sample.jpg"))[::2,::2,0]s=time.time()foriinrange(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.0464063705289print(((e-s)*8/10000*1116*1991*3)/147)