Siyun He commited on
Commit
a1ee05b
·
1 Parent(s): 2cb8d59
Files changed (6) hide show
  1. .DS_Store +0 -0
  2. app.py +23 -0
  3. classification.py +242 -0
  4. clf_glcm.pkl +3 -0
  5. clf_lbp.pkl +3 -0
  6. requirements.txt +7 -0
.DS_Store ADDED
Binary file (18.4 kB). View file
 
app.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from classification import classify_image
3
+ import pickle
4
+
5
+ # Load the pre-trained classifiers
6
+ clf_glcm = pickle.load(open('clf_glcm.pkl', 'rb'))
7
+ clf_lbp = pickle.load(open('clf_lbp.pkl', 'rb'))
8
+
9
+
10
+ # Create a Gradio interface with a dropdown menu for algorithm selection
11
+ iface = gr.Interface(
12
+ fn=classify_image,
13
+ inputs=[
14
+ gr.Image(type='numpy', label="Upload an Image"),
15
+ gr.Dropdown(choices=['GLCM', 'LBP'], label="Algorithm", value='GLCM')
16
+ ],
17
+ outputs='text',
18
+ title='Texture Classification',
19
+ description='Upload an image and choose an algorithm (GLCM or LBP) for texture classification.'
20
+ )
21
+
22
+ # Launch the interface
23
+ iface.launch(share=True)
classification.py ADDED
@@ -0,0 +1,242 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # save the resized image to ./grass_resized/ folder
2
+ import os
3
+ import cv2
4
+ import numpy as np
5
+
6
+ # Resize the image to 128x128
7
+ def resize_image(image_path, save_path):
8
+ img = cv2.imread(image_path)
9
+ img = cv2.resize(img, (128, 128))
10
+ cv2.imwrite(save_path, img)
11
+
12
+ # read image data from ./grass/ folder
13
+ if not os.path.exists('./grass_resized/'):
14
+ os.makedirs('./grass_resized/')
15
+
16
+ # rename the image file to 1.jpg, 2.jpg, 3.jpg, ...
17
+ count = 1
18
+ for file in os.listdir('./grass/'):
19
+ if file.endswith('.jpg') or file.endswith('.jpeg') or file.endswith('.png'):
20
+ resize_image('./grass/' + file, './grass_resized/' + str(count) + '.jpg')
21
+ count += 1
22
+
23
+ print('Done!')
24
+
25
+ # save the resized image to ./wood_resized/ folder
26
+ if not os.path.exists('./wood_resized/'):
27
+ os.makedirs('./wood_resized/')
28
+
29
+ # rename the image file to 1.jpg, 2.jpg, 3.jpg, ...
30
+ count = 1
31
+ for file in os.listdir('./wood/'):
32
+ if file.endswith('.jpg') or file.endswith('.jpeg') or file.endswith('.png'):
33
+ resize_image('./wood/' + file, './wood_resized/' + str(count) + '.jpg')
34
+ count += 1
35
+
36
+ print('Done!')
37
+
38
+ # Divide the data into training and testing data: 70% training, 30% testing
39
+ # Merge grass and wood data into training and testing data
40
+ # Save the training data to ./train/ folder
41
+ # Save the testing data to ./test/ folder
42
+ import shutil
43
+
44
+ if not os.path.exists('./train/'):
45
+ os.makedirs('./train/')
46
+ if not os.path.exists('./test/'):
47
+ os.makedirs('./test/')
48
+
49
+ # Rename files so that they do not overwrite each other
50
+ for i in range(1, 36):
51
+ shutil.copy('./grass_resized/' + str(i) + '.jpg', './train/' + str(i) + '.jpg')
52
+ for i in range(36, 51):
53
+ shutil.copy('./grass_resized/' +
54
+ str(i) + '.jpg', './test/' + str(i - 35) + '.jpg')
55
+ for i in range(1, 36):
56
+ shutil.copy('./wood_resized/' + str(i) + '.jpg', './train/' + str(i + 35) + '.jpg')
57
+ for i in range(36, 51):
58
+ shutil.copy('./wood_resized/' +
59
+ str(i) + '.jpg', './test/' + str(i - 20) + '.jpg')
60
+
61
+ # Do data augmentation by flipping the images horizontally on train data
62
+ # Save the augmented data to the same folders
63
+ def augment_image(image_path, save_path):
64
+ img = cv2.imread(image_path)
65
+ #flip with 50% probability
66
+ if np.random.rand() > 0.5:
67
+ img = cv2.flip(img, 1)
68
+ #rotate by 90 degrees with 50% probability
69
+ if np.random.rand() > 0.5:
70
+ img = cv2.rotate(img, cv2.ROTATE_90_CLOCKWISE)
71
+ cv2.imwrite(save_path, img)
72
+
73
+ for i in range(1, 36):
74
+ augment_image('./train/' + str(i) + '.jpg', './train/' + str(i + 70) + '.jpg')
75
+ for i in range(36, 51):
76
+ augment_image('./train/' + str(i) + '.jpg', './train/' + str(i + 70) + '.jpg')
77
+
78
+
79
+
80
+ # Compute the GLCM for each image.
81
+ # Extract features like contrast, correlaton, energy, and homogeneity.
82
+ # Save the features to a CSV file.
83
+ # Label each feature vector with the correct class (grass or wood).
84
+ import pandas as pd
85
+ from skimage.feature import graycomatrix, graycoprops
86
+
87
+ def compute_glcm(image_path, ispath=True):
88
+ '''Compute GLCM features for an image.'''
89
+ if ispath:
90
+ img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
91
+ else:
92
+ img = image_path
93
+ # compute the GLCM properties. Distance = 2, and 4 angles: 0, 45, 90, 135
94
+ glcm = graycomatrix(img, [3], [0, np.pi/4, np.pi/2, 3*np.pi/4], 256, symmetric=True, normed=True)
95
+ # extract the properties
96
+ contrast = graycoprops(glcm, 'contrast')
97
+ correlation = graycoprops(glcm, 'correlation')
98
+ energy = graycoprops(glcm, 'energy')
99
+ homogeneity = graycoprops(glcm, 'homogeneity')
100
+ # return the feature vector
101
+ # return [contrast[0][0], correlation[0][0], energy[0][0], homogeneity[0][0]]
102
+ # Flatten the arrays first
103
+ contrast_flat = contrast.flatten()
104
+ correlation_flat = correlation.flatten()
105
+ energy_flat = energy.flatten()
106
+ homogeneity_flat = homogeneity.flatten()
107
+
108
+ # Calculate the mean for each GLCM feature category
109
+ mean_contrast = np.mean(contrast_flat)
110
+ mean_correlation = np.mean(correlation_flat)
111
+ mean_energy = np.mean(energy_flat)
112
+ mean_homogeneity = np.mean(homogeneity_flat)
113
+ return [mean_contrast, mean_correlation, mean_energy, mean_homogeneity]
114
+
115
+ # Compute the GLCM for each image in the training data
116
+ data = []
117
+ for i in range(1, 71):
118
+ data.append(compute_glcm('./train/' + str(i) + '.jpg'))
119
+ df = pd.DataFrame(data, columns=['contrast', 'correlation', 'energy', 'homogeneity'])
120
+ df['class'] = ['grass']*35 + ['wood']*35
121
+ df.to_csv('train_glcm.csv', index=False)
122
+
123
+ # Compute the GLCM for each image in the testing data
124
+ data = []
125
+ for i in range(1, 31):
126
+ data.append(compute_glcm('./test/' + str(i) + '.jpg'))
127
+ df = pd.DataFrame(data, columns=['contrast', 'correlation', 'energy', 'homogeneity'])
128
+ df['class'] = ['grass']*15 + ['wood']*15
129
+ df.to_csv('test_glcm.csv', index=False)
130
+
131
+ # Apply the LBP operator to each image.
132
+ # Generate histograms of LBP codes to create feature vectors.
133
+ # Save the features to a CSV file.
134
+ # Label each feature vector with the correct class (grass or wood).
135
+ from skimage.feature import local_binary_pattern
136
+
137
+ def compute_lbp(image_path, ispath=True):
138
+ if ispath:
139
+ img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
140
+ else:
141
+ img = image_path
142
+ lbp = local_binary_pattern(img, 8, 1, 'uniform')
143
+ hist, _ = np.histogram(lbp, bins=np.arange(0, 11), density=True)
144
+ return hist
145
+
146
+ # Compute the LBP for each image in the training data
147
+ data = []
148
+ for i in range(1, 71):
149
+ data.append(compute_lbp('./train/' + str(i) + '.jpg'))
150
+ df = pd.DataFrame(data, columns=['lbp_' + str(i) for i in range(10)])
151
+ df['class'] = ['grass']*35 + ['wood']*35
152
+ df.to_csv('train_lbp.csv', index=False)
153
+
154
+ # Compute the LBP for each image in the testing data
155
+ data = []
156
+ for i in range(1, 31):
157
+ data.append(compute_lbp('./test/' + str(i) + '.jpg'))
158
+ df = pd.DataFrame(data, columns=['lbp_' + str(i) for i in range(10)])
159
+ df['class'] = ['grass']*15 + ['wood']*15
160
+ df.to_csv('test_lbp.csv', index=False)
161
+
162
+ # Select Support Vector Machines (SVM) as the classifier.
163
+ # Train the classifier using the training data.
164
+ # Test the classifier using the testing data.
165
+ from sklearn.svm import SVC
166
+ from sklearn.metrics import accuracy_score
167
+ from sklearn.metrics import precision_score
168
+ import pandas as pd
169
+
170
+ train_glcm = pd.read_csv('train_glcm.csv')
171
+ test_glcm = pd.read_csv('test_glcm.csv')
172
+ train_lbp = pd.read_csv('train_lbp.csv')
173
+ test_lbp = pd.read_csv('test_lbp.csv')
174
+
175
+ X_train_glcm = train_glcm.drop('class', axis=1)
176
+ y_train_glcm = train_glcm['class']
177
+ X_test_glcm = test_glcm.drop('class', axis=1)
178
+ y_test_glcm = test_glcm['class']
179
+
180
+ X_train_lbp = train_lbp.drop('class', axis=1)
181
+ y_train_lbp = train_lbp['class']
182
+ X_test_lbp = test_lbp.drop('class', axis=1)
183
+ y_test_lbp = test_lbp['class']
184
+
185
+ clf_glcm = SVC()
186
+ clf_glcm.fit(X_train_glcm, y_train_glcm)
187
+ y_pred_glcm = clf_glcm.predict(X_test_glcm)
188
+ print('Accuracy for GLCM features:', accuracy_score(y_test_glcm, y_pred_glcm))
189
+ # calculate the precsion
190
+ precision = precision_score(y_test_glcm, y_pred_glcm, average='weighted')
191
+ print('Precision for GLCM features:', precision)
192
+
193
+ clf_lbp = SVC()
194
+ clf_lbp.fit(X_train_lbp, y_train_lbp)
195
+ y_pred_lbp = clf_lbp.predict(X_test_lbp)
196
+ print('Accuracy for LBP features:', accuracy_score(y_test_lbp, y_pred_lbp))
197
+ # calculate the precsion
198
+ precision = precision_score(y_test_lbp, y_pred_lbp, average='weighted')
199
+ print('Precision for LBP features:', precision)
200
+
201
+ # Evaluate each classifier on the tesing set.
202
+ # Compare the results.
203
+ # Save the results to a CSV file.
204
+ results = pd.DataFrame({'GLCM': [accuracy_score(y_test_glcm, y_pred_glcm)], 'LBP': [accuracy_score(y_test_lbp, y_pred_lbp)]})
205
+ # Add the precision to the results
206
+ results['GLCM_precision'] = precision_score(y_test_glcm, y_pred_glcm, average='weighted')
207
+ results['LBP_precision'] = precision_score(y_test_lbp, y_pred_lbp, average='weighted')
208
+ results.to_csv('results.csv', index=False)
209
+
210
+ import pickle
211
+ # save clf_glcm and clf_lbp as pickle files
212
+ with open('clf_glcm.pkl', 'wb') as f:
213
+ pickle.dump(clf_glcm, f)
214
+ with open('clf_lbp.pkl', 'wb') as f:
215
+ pickle.dump(clf_lbp, f)
216
+
217
+ import warnings
218
+ def classify_image(image, algorithm):
219
+ # Suppress the warning about feature names
220
+ warnings.filterwarnings("ignore", message="X does not have valid feature names")
221
+
222
+ # If the image is a NumPy array, it's already loaded
223
+ if isinstance(image, np.ndarray):
224
+ img = cv2.resize(image, (128, 128))
225
+ img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
226
+
227
+ # Perform classification based on the selected algorithm
228
+ if algorithm == 'GLCM':
229
+ features = compute_glcm(img_gray, ispath=False)
230
+ else:
231
+ features = compute_lbp(img_gray, ispath=False)
232
+
233
+ # Convert features to a DataFrame to match the format used in training
234
+ features_df = pd.DataFrame([features])
235
+
236
+ # Make predictions using the pre-trained classifiers
237
+ if algorithm == 'GLCM':
238
+ prediction = clf_glcm.predict(features_df)[0]
239
+ else:
240
+ prediction = clf_lbp.predict(features_df)[0]
241
+
242
+ return prediction
clf_glcm.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:dae47a92e34746a8ada666bda3481e425b71b3cfc38fadb9bebdbb736bd7e8f5
3
+ size 1838
clf_lbp.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2cf77958648f5267635cdda0bb7b5d82b84443a7e9abc8b8dd421faa96d8b0e7
3
+ size 3250
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ opencv-python
2
+ pandas
3
+ matplotlib
4
+ seaborn
5
+ numpy
6
+ scikit-image
7
+ gradio