nnibras commited on
Commit
a3fa85f
·
verified ·
1 Parent(s): 1dc1ab5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +169 -58
app.py CHANGED
@@ -26,6 +26,7 @@ TARGET_SIZE = (30, 30)
26
  distances = [1]
27
  angles = [0]
28
 
 
29
  def load_and_convert_images(directory):
30
  """Load images from a specified directory using glob and convert them to grayscale.
31
 
@@ -36,49 +37,23 @@ def load_and_convert_images(directory):
36
  list: A list of resized grayscale images.
37
  """
38
  dataset = []
39
- # Use glob to find image files in the directory
40
  for img_path in glob.glob(f"{directory}/*.*"):
41
  if img_path.endswith((".jpg", ".png", ".jpeg")):
42
  img = cv2.imread(img_path) # Read the image
43
  if img is not None:
44
  # Convert to grayscale and resize the image
45
  gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
46
- resized_image = cv2.resize(gray_image, TARGET_SIZE, interpolation=cv2.INTER_AREA)
 
 
47
  dataset.append(resized_image)
48
  return dataset
49
 
50
- # Ensure that both datasets contain 2D arrays (grayscale images)
51
- def check_and_reshape(dataset):
52
- """Ensure all images in the dataset are 2D arrays.
53
-
54
- Args:
55
- dataset (list): A list of images.
56
-
57
- Returns:
58
- list: A list of reshaped images to ensure they are all 2D.
59
- """
60
- reshaped_dataset = []
61
- for img in dataset:
62
- if img.ndim == 3: # If the image has 3 dimensions (like RGB), convert it to grayscale
63
- gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
64
- reshaped_dataset.append(gray_img)
65
- elif img.ndim == 2: # If it's already grayscale (2D), just append it
66
- reshaped_dataset.append(img)
67
- else:
68
- raise ValueError("Unexpected image dimension: {}".format(img.ndim))
69
- return reshaped_dataset
70
 
71
  # Load datasets using glob
72
  grass_dataset = load_and_convert_images(grass_dir)
73
  wood_dataset = load_and_convert_images(wood_dir)
74
 
75
- # Apply the reshaping to both datasets
76
- grass_dataset = check_and_reshape(grass_dataset)
77
- wood_dataset = check_and_reshape(wood_dataset)
78
-
79
- # Now concatenate the datasets
80
- X = np.concatenate([grass_dataset, wood_dataset])
81
- y = np.concatenate([np.zeros(len(grass_dataset)), np.ones(len(wood_dataset))]) # Labels: 0 for Grass, 1 for Wood
82
 
83
  def calc_glcm_features(images):
84
  """Calculate GLCM features for a list of images.
@@ -90,48 +65,181 @@ def calc_glcm_features(images):
90
  list: A list of GLCM features for each image.
91
  """
92
  features = []
93
- for image in images:
94
- glcm = graycomatrix(image, distances=distances, angles=angles, symmetric=True, normed=True)
95
- contrast = graycoprops(glcm, 'contrast')[0, 0]
96
- dissimilarity = graycoprops(glcm, 'dissimilarity')[0, 0]
97
- homogeneity = graycoprops(glcm, 'homogeneity')[0, 0]
98
- energy = graycoprops(glcm, 'energy')[0, 0]
99
- correlation = graycoprops(glcm, 'correlation')[0, 0]
 
 
 
100
  features.append([contrast, dissimilarity, homogeneity, energy, correlation])
101
  return features
102
 
 
 
 
 
 
 
103
  def extract_lbp_features(images):
104
- """Extract LBP features for a list of images.
105
 
106
  Args:
107
  images (list): A list of grayscale images.
108
 
109
  Returns:
110
- list: A list of LBP features for each image.
111
  """
112
- features = []
113
  for image in images:
114
  lbp = local_binary_pattern(image, N_POINTS, RADIUS, method="uniform")
115
- lbp_hist, _ = np.histogram(lbp.ravel(), bins=np.arange(0, N_POINTS + 3), range=(0, N_POINTS + 2))
116
- lbp_hist = lbp_hist.astype("float")
117
- lbp_hist /= lbp_hist.sum() # Normalize the histogram
118
- features.append(lbp_hist)
119
- return features
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
 
121
- # Train classifiers (for example purposes, using KNN)
122
- glcm_features = calc_glcm_features(X)
123
- lbp_features = extract_lbp_features(X)
 
 
124
 
125
- # KFold cross-validation
126
- kf = KFold(n_splits=5)
127
 
128
- # Example: KNN classifier for GLCM features
129
- knn_glcm = KNeighborsClassifier(n_neighbors=3)
130
- knn_glcm.fit(glcm_features, y)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
 
132
- # Example: KNN classifier for LBP features
133
- knn_lbp = KNeighborsClassifier(n_neighbors=3)
134
- knn_lbp.fit(lbp_features, y)
135
 
136
  def classify_texture(image, method):
137
  """Classify the texture of the uploaded image as grass or wood using the selected method.
@@ -150,10 +258,10 @@ def classify_texture(image, method):
150
  # Extract features based on the selected method
151
  if method == "GLCM":
152
  feature = calc_glcm_features([resized_image])
153
- prediction = knn_glcm.predict(feature)
154
  elif method == "LBP":
155
  feature = extract_lbp_features([resized_image])
156
- prediction = knn_lbp.predict(feature)
157
  else:
158
  raise ValueError("The method is not recognized")
159
 
@@ -162,7 +270,9 @@ def classify_texture(image, method):
162
 
163
  # Highlight the image based on the classification
164
  if result == "Grass":
165
- highlighted_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # Convert to RGB for displaying
 
 
166
  highlighted_image[:] = [0, 255, 0] # Highlight in green
167
  else:
168
  highlighted_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
@@ -170,6 +280,7 @@ def classify_texture(image, method):
170
 
171
  return result, highlighted_image
172
 
 
173
  # Gradio interface setup with a dropdown for method selection
174
  iface = gr.Interface(
175
  fn=classify_texture,
 
26
  distances = [1]
27
  angles = [0]
28
 
29
+
30
  def load_and_convert_images(directory):
31
  """Load images from a specified directory using glob and convert them to grayscale.
32
 
 
37
  list: A list of resized grayscale images.
38
  """
39
  dataset = []
 
40
  for img_path in glob.glob(f"{directory}/*.*"):
41
  if img_path.endswith((".jpg", ".png", ".jpeg")):
42
  img = cv2.imread(img_path) # Read the image
43
  if img is not None:
44
  # Convert to grayscale and resize the image
45
  gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
46
+ resized_image = cv2.resize(
47
+ gray_image, TARGET_SIZE, interpolation=cv2.INTER_AREA
48
+ )
49
  dataset.append(resized_image)
50
  return dataset
51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
 
53
  # Load datasets using glob
54
  grass_dataset = load_and_convert_images(grass_dir)
55
  wood_dataset = load_and_convert_images(wood_dir)
56
 
 
 
 
 
 
 
 
57
 
58
  def calc_glcm_features(images):
59
  """Calculate GLCM features for a list of images.
 
65
  list: A list of GLCM features for each image.
66
  """
67
  features = []
68
+ for img in images:
69
+ glcm = graycomatrix(img, distances, angles, symmetric=True, normed=True)
70
+
71
+ # Calculate GLCM properties
72
+ contrast = graycoprops(glcm, "contrast")[0, 0]
73
+ dissimilarity = graycoprops(glcm, "dissimilarity")[0, 0]
74
+ homogeneity = graycoprops(glcm, "homogeneity")[0, 0]
75
+ energy = graycoprops(glcm, "energy")[0, 0]
76
+ correlation = graycoprops(glcm, "correlation")[0, 0]
77
+
78
  features.append([contrast, dissimilarity, homogeneity, energy, correlation])
79
  return features
80
 
81
+
82
+ # Calculate GLCM features for grass and wood datasets
83
+ grass_glcm_features = calc_glcm_features(grass_dataset)
84
+ wood_glcm_features = calc_glcm_features(wood_dataset)
85
+
86
+
87
  def extract_lbp_features(images):
88
+ """Extract LBP features from a list of images.
89
 
90
  Args:
91
  images (list): A list of grayscale images.
92
 
93
  Returns:
94
+ list: A list of LBP histograms for each image.
95
  """
96
+ lbp_features = []
97
  for image in images:
98
  lbp = local_binary_pattern(image, N_POINTS, RADIUS, method="uniform")
99
+ n_bins = int(lbp.max() + 1)
100
+ lbp_hist, _ = np.histogram(lbp, bins=n_bins, range=(0, n_bins), density=True)
101
+ lbp_features.append(lbp_hist)
102
+ return lbp_features
103
+
104
+
105
+ # Extract LBP features for grass and wood datasets
106
+ grass_lbp_features = extract_lbp_features(grass_dataset)
107
+ wood_lbp_features = extract_lbp_features(wood_dataset)
108
+
109
+ # Create labels (0 for grass, 1 for wood)
110
+ grass_labels = [0] * len(grass_dataset) # Label all grass images as 0
111
+ wood_labels = [1] * len(wood_dataset) # Label all wood images as 1
112
+
113
+ # Combine features and labels for GLCM classifier
114
+ glcm_features = np.array(grass_glcm_features + wood_glcm_features)
115
+ glcm_labels = grass_labels + wood_labels
116
+
117
+ # Prepare labels and features for LBP classifier
118
+ lbp_features = np.array(grass_lbp_features + wood_lbp_features)
119
+ lbp_labels = grass_labels + wood_labels
120
+
121
+ # Number of images
122
+ num_grass = len(grass_dataset)
123
+ num_wood = len(wood_dataset)
124
+
125
+ # Define labels for classification
126
+ y = np.array([0] * num_grass + [1] * num_wood)
127
+
128
+ # Define KFold cross-validation
129
+ k = 5
130
+ kf = KFold(n_splits=k, shuffle=True, random_state=42)
131
 
132
+ # Store results for GLCM and LBP classifiers
133
+ glcm_metrics = {"accuracy": [], "precision": [], "recall": [], "f1_score": []}
134
+ lbp_metrics = {"accuracy": [], "precision": [], "recall": [], "f1_score": []}
135
+ y_true_glcm, y_true_lbp = [], []
136
+ y_pred_glcm, y_pred_lbp = [], []
137
 
138
+ # Parameter tuning using GridSearchCV for KNN classifier
139
+ param_grid = {"n_neighbors": [3, 5, 7], "p": [1, 2]}
140
 
141
+ # GLCM Classifier Training and Evaluation
142
+ glcm_knn = KNeighborsClassifier()
143
+ glcm_grid_search = GridSearchCV(glcm_knn, param_grid, cv=kf)
144
+ glcm_grid_search.fit(glcm_features, y)
145
+
146
+ # Perform cross-validation and evaluate GLCM classifier
147
+ for train_index, test_index in kf.split(glcm_features):
148
+ x_train, x_test = glcm_features[train_index], glcm_features[test_index]
149
+ y_train, y_test = y[train_index], y[test_index]
150
+
151
+ glcm_classifier = KNeighborsClassifier(
152
+ n_neighbors=glcm_grid_search.best_params_["n_neighbors"]
153
+ )
154
+ glcm_classifier.fit(x_train, y_train)
155
+ y_pred = glcm_classifier.predict(x_test)
156
+
157
+ # Collect true and predicted labels
158
+ y_true_glcm.extend(y_test)
159
+ y_pred_glcm.extend(y_pred)
160
+
161
+ # Calculate and store metrics
162
+ accuracy = accuracy_score(y_test, y_pred)
163
+ precision = precision_score(y_test, y_pred, average="macro")
164
+ recall = recall_score(y_test, y_pred, average="macro")
165
+ f1 = f1_score(y_test, y_pred, average="macro")
166
+
167
+ glcm_metrics["accuracy"].append(accuracy)
168
+ glcm_metrics["precision"].append(precision)
169
+ glcm_metrics["recall"].append(recall)
170
+ glcm_metrics["f1_score"].append(f1)
171
+
172
+ # Print metrics for this fold
173
+ print(
174
+ f"GLCM Fold Metrics: Accuracy={accuracy:.2f}, Precision={precision:.2f}, Recall={recall:.2f}, F1-Score={f1:.2f}"
175
+ )
176
+
177
+ # Print average metrics for GLCM classifier
178
+ print("\nAverage GLCM Classifier Metrics:")
179
+ for metric in glcm_metrics:
180
+ avg_metric = np.mean(glcm_metrics[metric])
181
+ print(f"{metric.capitalize()}: {avg_metric:.2f}")
182
+
183
+ # Confusion Matrix for GLCM
184
+ glcm_conf_matrix = confusion_matrix(y_true_glcm, y_pred_glcm)
185
+ print("\nConfusion Matrix for GLCM Classifier:")
186
+ print(glcm_conf_matrix)
187
+
188
+ # Classification Report for GLCM
189
+ print("\nClassification Report for GLCM Classifier:")
190
+ print(classification_report(y_true_glcm, y_pred_glcm))
191
+
192
+ # LBP Classifier Training and Evaluation
193
+ lbp_knn = KNeighborsClassifier()
194
+ lbp_grid_search = GridSearchCV(lbp_knn, param_grid, cv=kf)
195
+ lbp_grid_search.fit(lbp_features, y)
196
+
197
+ # Perform cross-validation and evaluate LBP classifier
198
+ for train_index, test_index in kf.split(lbp_features):
199
+ x_train, x_test = lbp_features[train_index], lbp_features[test_index]
200
+ y_train, y_test = y[train_index], y[test_index]
201
+
202
+ lbp_classifier = KNeighborsClassifier(
203
+ n_neighbors=lbp_grid_search.best_params_["n_neighbors"]
204
+ )
205
+ lbp_classifier.fit(x_train, y_train)
206
+ y_pred = lbp_classifier.predict(x_test)
207
+
208
+ # Collect true and predicted labels
209
+ y_true_lbp.extend(y_test)
210
+ y_pred_lbp.extend(y_pred)
211
+
212
+ # Calculate and store metrics
213
+ accuracy = accuracy_score(y_test, y_pred)
214
+ precision = precision_score(y_test, y_pred, average="macro")
215
+ recall = recall_score(y_test, y_pred, average="macro")
216
+ f1 = f1_score(y_test, y_pred, average="macro")
217
+
218
+ lbp_metrics["accuracy"].append(accuracy)
219
+ lbp_metrics["precision"].append(precision)
220
+ lbp_metrics["recall"].append(recall)
221
+ lbp_metrics["f1_score"].append(f1)
222
+
223
+ # Print metrics for this fold
224
+ print(
225
+ f"LBP Fold Metrics: Accuracy={accuracy:.2f}, Precision={precision:.2f}, Recall={recall:.2f}, F1-Score={f1:.2f}"
226
+ )
227
+
228
+ # Print average metrics for LBP classifier
229
+ print("\nAverage LBP Classifier Metrics:")
230
+ for metric in lbp_metrics:
231
+ avg_metric = np.mean(lbp_metrics[metric])
232
+ print(f"{metric.capitalize()}: {avg_metric:.2f}")
233
+
234
+ # Confusion Matrix for LBP
235
+ lbp_conf_matrix = confusion_matrix(y_true_lbp, y_pred_lbp)
236
+ print("\nConfusion Matrix for LBP Classifier:")
237
+ print(lbp_conf_matrix)
238
+
239
+ # Classification Report for LBP
240
+ print("\nClassification Report for LBP Classifier:")
241
+ print(classification_report(y_true_lbp, y_pred_lbp))
242
 
 
 
 
243
 
244
  def classify_texture(image, method):
245
  """Classify the texture of the uploaded image as grass or wood using the selected method.
 
258
  # Extract features based on the selected method
259
  if method == "GLCM":
260
  feature = calc_glcm_features([resized_image])
261
+ prediction = glcm_classifier.predict(feature)
262
  elif method == "LBP":
263
  feature = extract_lbp_features([resized_image])
264
+ prediction = lbp_classifier.predict(feature)
265
  else:
266
  raise ValueError("The method is not recognized")
267
 
 
270
 
271
  # Highlight the image based on the classification
272
  if result == "Grass":
273
+ highlighted_image = cv2.cvtColor(
274
+ image, cv2.COLOR_BGR2RGB
275
+ ) # Convert to RGB for displaying
276
  highlighted_image[:] = [0, 255, 0] # Highlight in green
277
  else:
278
  highlighted_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
 
280
 
281
  return result, highlighted_image
282
 
283
+
284
  # Gradio interface setup with a dropdown for method selection
285
  iface = gr.Interface(
286
  fn=classify_texture,