-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Expand file tree
/
Copy path200_image_classification_using_GLCM.py
More file actions
249 lines (202 loc) · 9.54 KB
/
Copy path200_image_classification_using_GLCM.py
File metadata and controls
249 lines (202 loc) · 9.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
# https://youtu.be/5x-CIHRmMNY
"""
@author: Sreenivas Bhattiprolu
skimage.feature.greycomatrix(image, distances, angles, levels=None, symmetric=False, normed=False)
distances - List of pixel pair distance offsets.
angles - List of pixel pair angles in radians.
skimage.feature.greycoprops(P, prop)
prop: The property of the GLCM to compute.
{‘contrast’, ‘dissimilarity’, ‘homogeneity’, ‘energy’, ‘correlation’, ‘ASM’}
"""
import numpy as np
import matplotlib.pyplot as plt
import glob
import cv2
import os
import seaborn as sns
import pandas as pd
from skimage.filters import sobel
from skimage.feature import greycomatrix, greycoprops
from skimage.measure import shannon_entropy
print(os.listdir("images/natural/"))
#Resize images to
SIZE = 128
#Capture images and labels into arrays.
#Start by creating empty lists.
train_images = []
train_labels = []
#for directory_path in glob.glob("cell_images/train/*"):
for directory_path in glob.glob("images/natural/train/*"):
label = directory_path.split("\\")[-1]
print(label)
for img_path in glob.glob(os.path.join(directory_path, "*.jpg")):
print(img_path)
img = cv2.imread(img_path, 0) #Reading color images
img = cv2.resize(img, (SIZE, SIZE)) #Resize images
train_images.append(img)
train_labels.append(label)
train_images = np.array(train_images)
train_labels = np.array(train_labels)
#Do exactly the same for test/validation images
# test
test_images = []
test_labels = []
#for directory_path in glob.glob("cell_images/test/*"):
for directory_path in glob.glob("images/natural/validation/*"):
fruit_label = directory_path.split("\\")[-1]
for img_path in glob.glob(os.path.join(directory_path, "*.jpg")):
img = cv2.imread(img_path, 0)
img = cv2.resize(img, (SIZE, SIZE))
test_images.append(img)
test_labels.append(fruit_label)
test_images = np.array(test_images)
test_labels = np.array(test_labels)
#Encode labels from text (folder names) to integers.
from sklearn import preprocessing
le = preprocessing.LabelEncoder()
le.fit(test_labels)
test_labels_encoded = le.transform(test_labels)
train_labels_encoded = le.transform(train_labels)
#Split data into test and train datasets (already split but assigning to meaningful convention)
#If you only have one dataset then split here
x_train, y_train, x_test, y_test = train_images, train_labels_encoded, test_images, test_labels_encoded
# Normalize pixel values to between 0 and 1
#x_train, x_test = x_train / 255.0, x_test / 255.0
###################################################################
# FEATURE EXTRACTOR function
# input shape is (n, x, y, c) - number of images, x, y, and channels
def feature_extractor(dataset):
image_dataset = pd.DataFrame()
for image in range(dataset.shape[0]): #iterate through each file
#print(image)
df = pd.DataFrame() #Temporary data frame to capture information for each loop.
#Reset dataframe to blank after each loop.
img = dataset[image, :,:]
################################################################
#START ADDING DATA TO THE DATAFRAME
#Full image
#GLCM = greycomatrix(img, [1], [0, np.pi/4, np.pi/2, 3*np.pi/4])
GLCM = greycomatrix(img, [1], [0])
GLCM_Energy = greycoprops(GLCM, 'energy')[0]
df['Energy'] = GLCM_Energy
GLCM_corr = greycoprops(GLCM, 'correlation')[0]
df['Corr'] = GLCM_corr
GLCM_diss = greycoprops(GLCM, 'dissimilarity')[0]
df['Diss_sim'] = GLCM_diss
GLCM_hom = greycoprops(GLCM, 'homogeneity')[0]
df['Homogen'] = GLCM_hom
GLCM_contr = greycoprops(GLCM, 'contrast')[0]
df['Contrast'] = GLCM_contr
GLCM2 = greycomatrix(img, [3], [0])
GLCM_Energy2 = greycoprops(GLCM2, 'energy')[0]
df['Energy2'] = GLCM_Energy2
GLCM_corr2 = greycoprops(GLCM2, 'correlation')[0]
df['Corr2'] = GLCM_corr2
GLCM_diss2 = greycoprops(GLCM2, 'dissimilarity')[0]
df['Diss_sim2'] = GLCM_diss2
GLCM_hom2 = greycoprops(GLCM2, 'homogeneity')[0]
df['Homogen2'] = GLCM_hom2
GLCM_contr2 = greycoprops(GLCM2, 'contrast')[0]
df['Contrast2'] = GLCM_contr2
GLCM3 = greycomatrix(img, [5], [0])
GLCM_Energy3 = greycoprops(GLCM3, 'energy')[0]
df['Energy3'] = GLCM_Energy3
GLCM_corr3 = greycoprops(GLCM3, 'correlation')[0]
df['Corr3'] = GLCM_corr3
GLCM_diss3 = greycoprops(GLCM3, 'dissimilarity')[0]
df['Diss_sim3'] = GLCM_diss3
GLCM_hom3 = greycoprops(GLCM3, 'homogeneity')[0]
df['Homogen3'] = GLCM_hom3
GLCM_contr3 = greycoprops(GLCM3, 'contrast')[0]
df['Contrast3'] = GLCM_contr3
GLCM4 = greycomatrix(img, [0], [np.pi/4])
GLCM_Energy4 = greycoprops(GLCM4, 'energy')[0]
df['Energy4'] = GLCM_Energy4
GLCM_corr4 = greycoprops(GLCM4, 'correlation')[0]
df['Corr4'] = GLCM_corr4
GLCM_diss4 = greycoprops(GLCM4, 'dissimilarity')[0]
df['Diss_sim4'] = GLCM_diss4
GLCM_hom4 = greycoprops(GLCM4, 'homogeneity')[0]
df['Homogen4'] = GLCM_hom4
GLCM_contr4 = greycoprops(GLCM4, 'contrast')[0]
df['Contrast4'] = GLCM_contr4
GLCM5 = greycomatrix(img, [0], [np.pi/2])
GLCM_Energy5 = greycoprops(GLCM5, 'energy')[0]
df['Energy5'] = GLCM_Energy5
GLCM_corr5 = greycoprops(GLCM5, 'correlation')[0]
df['Corr5'] = GLCM_corr5
GLCM_diss5 = greycoprops(GLCM5, 'dissimilarity')[0]
df['Diss_sim5'] = GLCM_diss5
GLCM_hom5 = greycoprops(GLCM5, 'homogeneity')[0]
df['Homogen5'] = GLCM_hom5
GLCM_contr5 = greycoprops(GLCM5, 'contrast')[0]
df['Contrast5'] = GLCM_contr5
#Add more filters as needed
#entropy = shannon_entropy(img)
#df['Entropy'] = entropy
#Append features from current image to the dataset
image_dataset = image_dataset.append(df)
return image_dataset
####################################################################
#Extract features from training images
image_features = feature_extractor(x_train)
X_for_ML =image_features
#Reshape to a vector for Random Forest / SVM training
#n_features = image_features.shape[1]
#image_features = np.expand_dims(image_features, axis=0)
#X_for_ML = np.reshape(image_features, (x_train.shape[0], -1)) #Reshape to #images, features
#Define the classifier
# from sklearn.ensemble import RandomForestClassifier
# RF_model = RandomForestClassifier(n_estimators = 50, random_state = 42)
#Can also use SVM but RF is faster and may be more accurate.
#from sklearn import svm
#SVM_model = svm.SVC(decision_function_shape='ovo') #For multiclass classification
#SVM_model.fit(X_for_ML, y_train)
# Fit the model on training data
# RF_model.fit(X_for_ML, y_train) #For sklearn no one hot encoding
import lightgbm as lgb
#Class names for LGBM start at 0 so reassigning labels from 1,2,3,4 to 0,1,2,3
d_train = lgb.Dataset(X_for_ML, label=y_train)
# https://lightgbm.readthedocs.io/en/latest/Parameters.html
lgbm_params = {'learning_rate':0.05, 'boosting_type':'dart',
'objective':'multiclass',
'metric': 'multi_logloss',
'num_leaves':100,
'max_depth':10,
'num_class':4} #no.of unique values in the target class not inclusive of the end value
lgb_model = lgb.train(lgbm_params, d_train, 100) #50 iterations. Increase iterations for small learning rates
#Predict on Test data
#Extract features from test data and reshape, just like training data
test_features = feature_extractor(x_test)
test_features = np.expand_dims(test_features, axis=0)
test_for_RF = np.reshape(test_features, (x_test.shape[0], -1))
#Predict on test
test_prediction = lgb_model.predict(test_for_RF)
test_prediction=np.argmax(test_prediction, axis=1)
#Inverse le transform to get original label back.
test_prediction = le.inverse_transform(test_prediction)
#Print overall accuracy
from sklearn import metrics
print ("Accuracy = ", metrics.accuracy_score(test_labels, test_prediction))
#Print confusion matrix
from sklearn.metrics import confusion_matrix
cm = confusion_matrix(test_labels, test_prediction)
fig, ax = plt.subplots(figsize=(6,6)) # Sample figsize in inches
sns.set(font_scale=1.6)
sns.heatmap(cm, annot=True, linewidths=.5, ax=ax)
#Check results on a few random images
import random
n=random.randint(0, x_test.shape[0]-1) #Select the index of image to be loaded for testing
img = x_test[n]
plt.imshow(img)
#Extract features and reshape to right dimensions
input_img = np.expand_dims(img, axis=0) #Expand dims so the input is (num images, x, y, c)
input_img_features=feature_extractor(input_img)
input_img_features = np.expand_dims(input_img_features, axis=0)
input_img_for_RF = np.reshape(input_img_features, (input_img.shape[0], -1))
#Predict
img_prediction = lgb_model.predict(input_img_for_RF)
img_prediction=np.argmax(img_prediction, axis=1)
img_prediction = le.inverse_transform([img_prediction]) #Reverse the label encoder to original name
print("The prediction for this image is: ", img_prediction)
print("The actual label for this image is: ", test_labels[n])