3

image of cat used

source: https://www.petfinder.com/cats/cat-grooming/

I am trying to receive in Python the exact same results of the functions graycomatrix and graycoprops as in MATLAB. But the results differ and I am not able to write the code which will repeat the results from MATLAB.

I need GLCM features like contrast, correlation, energy and homogeneity.

Any advice is very appreciated.

Example code in MATLAB:

% GLCM feature extraction

offset_GLCM = [0 1; -1 1; -1 0; -1 -1];
offset = [1*offset_GLCM ; 2*offset_GLCM; 3*offset_GLCM];

img = rgb2gray(imread('cat.jpg'));
Grauwertmatrix = graycomatrix(img,'NumLevels', 12, 'GrayLimits', [], 'Offset',offset);
GrauwertStats = graycoprops(Grauwertmatrix);
GLCMFeatureVector = [mean(GrauwertStats.Contrast) mean(GrauwertStats.Correlation) mean(GrauwertStats.Energy) mean(GrauwertStats.Homogeneity)];

disp(GLCMFeatureVector);

and the code above returns:

1.6212    0.8862    0.0607    0.7546

Now I want to receive exactly the same results in Python. I use Python code:

# GLCM feature extraction

import numpy as np
from skimage import feature, io
from sklearn import preprocessing

img = io.imread("cat.jpg", as_grey=True)

S = preprocessing.MinMaxScaler((0,11)).fit_transform(img).astype(int)
Grauwertmatrix = feature.greycomatrix(S, [1,2,3], [0, np.pi/4, np.pi/2, 3*np.pi/4], levels=12, symmetric=False, normed=True)

ContrastStats = feature.greycoprops(Grauwertmatrix, 'contrast')
CorrelationtStats = feature.greycoprops(Grauwertmatrix, 'correlation')
HomogeneityStats = feature.greycoprops(Grauwertmatrix, 'homogeneity')
ASMStats = feature.greycoprops(Grauwertmatrix, 'ASM')

print([np.mean(ContrastStats), np.mean(CorrelationtStats),\
np.mean(ASMStats), np.mean(HomogeneityStats)])

But I get the result:

[1.7607, 0.8844, 0.0429, 0.7085]

Another example. Different results on original image. Reason is that MATLAB by default processes image and Python does not. How to get in Python same result as in MATLAB?:

MATLAB:

>> img = rgb2gray(imread('cat.png'));
>> [Grauwertmatrix, S] = graycomatrix(img,'NumLevels',12,'GrayLimits',[0,12],'Offset',[0,1]);
>> Grauwertmatrix(1:5,1:5)

ans =

     4     7     4     8     0
     9    33    22    13    10
     5    18    16    10    10
     2    16    11    22    13
     4    12    11    14    14

Python:

>>> from skimage import io, feature
>>> img = io.imread("cat.png", as_grey=True)
>>> Grauwertmatrix = feature.greycomatrix(img, distances=[1], angles=[0], levels=12, symmetric=False, normed=False)
>>> Grauwertmatrix[0:5, 0:5, 0, 0]
array([[299720,      2,      0,      0,      0],
       [     2,      1,      0,      0,      0],
       [     0,      0,      0,      0,      0],
       [     0,      0,      0,      0,      0],
       [     0,      0,      0,      0,      0]], dtype=uint32)
Sofiia
  • 51
  • 1
  • 6

1 Answers1

2

The GLCM features computed with Matlab and Python are different because the result of preprocessing the original image (namely conversion to grayscale, scaling and requantization) with your Matlab code differs from the result yielded by your Python code (i.e. array S). The following snippets make it apparent:

Matlab

>> offset_GLCM = [0 1; -1 1; -1 0; -1 -1];
>> offset = [1*offset_GLCM ; 2*offset_GLCM; 3*offset_GLCM];
>> img = rgb2gray(imread('cat.png'));
>> [Grauwertmatrix, S] = graycomatrix(img,'NumLevels', 12, 'GrayLimits', [], 'Offset',offset);

>> S(100:105, 100:105)

ans =

     4     5     7     8     8     6
     5     5     6     7     8     7
     4     4     4     6     7     7
     4     4     5     6     8     8
     5     6     6     7     8     8
     4     5     6     6     7     8

Python

In [36]: from skimage import io

In [37]: from sklearn import preprocessing

In [38]: img = io.imread("cat.png", as_grey=True)

In [39]: S = preprocessing.MinMaxScaler((0,11)).fit_transform(img).astype(int)

In [40]: S[99:105, 99:105]
Out[40]: 
array([[2, 4, 6, 7, 5, 5],
       [2, 3, 4, 5, 6, 5],
       [2, 1, 1, 3, 5, 6],
       [2, 2, 2, 4, 6, 7],
       [3, 4, 4, 5, 6, 7],
       [2, 3, 4, 4, 5, 7]])

As a final remark, I would recommend that you use a lossless image format (such as BMP or PNG) to avoid potential discrepancies due to JPG-decompression.

WORKAROUND

In order to obtain the same results through Matlab and Python you should use the same preprocessed image in both cases. Such image can be generated for example like so:

from skimage import io
from sklearn import preprocessing
img = io.imread("cat.png", as_grey=True)
S = preprocessing.MinMaxScaler((0,11)).fit_transform(img).astype(int)
io.imsave('cat_preprocessed.png', S)

Notice that the resulting image has very low contrast as the intensity values range from 0 to 11.

In order for Matlab's graycomatrix to correctly scale this image you need to pass 'NumLevels',12 and 'GrayLimits',[0,12] (rather than [0,11]):

>> img = imread('cat_preprocessed.png');
>> [Grauwertmatrix, S] = graycomatrix(img,'NumLevels',12,'GrayLimits',[0,12],'Offset',[0,1]);
>> Grauwertmatrix(1:5,1:5)

ans =

       21258        3250         452         186          91
        3208       20119        5268         827         267
         532        5242       40541        8508        1203
         208         848        8616       26436        6324
         102         285        1192        6216       14101

>> graycoprops(Grauwertmatrix,{'contrast'})

ans = 

    Contrast: 0.9681

Python returns the same results:

In [86]: from skimage import io, feature

In [87]: img = io.imread("cat_preprocessed.png")

In [88]: Grauwertmatrix = feature.greycomatrix(img, distances=[1], angles=[0], levels=12, symmetric=False, normed=False)

In [89]: Grauwertmatrix[0:5, 0:5, 0, 0]
Out[89]:
array([[21258,  3250,   452,   186,    91],
       [ 3208, 20119,  5268,   827,   267],
       [  532,  5242, 40541,  8508,  1203],
       [  208,   848,  8616, 26436,  6324],
       [  102,   285,  1192,  6216, 14101]], dtype=uint32)

In [90]: feature.greycoprops(Grauwertmatrix, 'contrast')
Out[90]: array([[ 0.96812745]])

Edit

In reply to your comment, I don't think it's possible to obtain the same results from the original RGB image through Matlab and Python since the conversion to grayscale is performed differently. This is clearly stated in the documentation:

Matlab's rgb2gray:

rgb2gray converts RGB values to grayscale values by forming a weighted sum of the R, G, and B components:

    0.2989 * R + 0.5870 * G + 0.1140 * B

scikit-image's rgb2gray:

The weights used in this conversion are calibrated for contemporary CRT phosphors:

Y = 0.2125 R + 0.7154 G + 0.0721 B
Tonechas
  • 13,398
  • 16
  • 46
  • 80
  • Thank you for the answer! How should I process my image in Python that I get the same results as in MATLAB? Also, I am working with .tiff images. Cat image is just the example. – Sofiia May 18 '17 at 09:53
  • @Sofiia: I've just edited my answer to show you a possible way to obtain the same results through Matlab and Python. – Tonechas May 18 '17 at 11:33
  • Thank you so much for such an open answer! I am happy to finally see that it is possible to get the same results in Python and Matlab. However, what if we work with original image? My problem is that I worked in Matlab with original image and it scaled it in some way. As you showed, when the image is scaled, it gives same results. But when it is not scaled, I cannot get the same results. (I edited my answer with example) – Sofiia May 19 '17 at 06:48