nnibras commited on
Commit
7b46d95
·
verified ·
1 Parent(s): 28bd053

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +119 -176
app.py CHANGED
@@ -1,218 +1,161 @@
1
- import cv2
2
  import glob
3
- import gradio as gr
4
  import numpy as np
 
5
  import matplotlib.pyplot as plt
6
- from sklearn.model_selection import KFold
7
- from skimage.feature import graycomatrix, graycoprops
8
  from sklearn.neighbors import KNeighborsClassifier
9
- from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
10
- import pandas as pd
11
- from sklearn.model_selection import GridSearchCV
12
- from skimage.feature import local_binary_pattern
13
-
14
-
15
- # Visualize GLCM features for grass and wood
16
- def plot_features(features, title):
17
- plt.figure(figsize=(10, 6))
18
- for i, feature in enumerate(features.T): # Transpose to plot feature by feature
19
- plt.plot(feature)
20
- plt.title(title)
21
- plt.show()
22
-
23
 
24
  # Define directories for grass and wood images
25
  grass_dir = "images/Grass/Train_Grass"
26
  wood_dir = "images/Wood/Train_Wood"
27
 
28
- # Constants for LBP
29
  RADIUS = 1
30
  N_POINTS = 12 * RADIUS
31
  TARGET_SIZE = (30, 30)
32
-
33
- # for GLCM
34
  distances = [1]
35
  angles = [0]
36
 
37
-
38
- # Use glob to load images from the directory
39
  def load_and_convert_images(directory):
40
- """Load images from a directory using glob and convert them to grayscale."""
 
 
 
 
 
 
 
41
  dataset = []
42
- image_paths = glob.glob(f"{directory}/*.jpg") + glob.glob(f"{directory}/*.png") + glob.glob(f"{directory}/*.jpeg")
43
-
44
- for img_path in image_paths:
45
- img = cv2.imread(img_path) # Read the image
46
- if img is not None:
47
- gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # Convert to grayscale
48
- resized_image = cv2.resize(gray_image, TARGET_SIZE, interpolation=cv2.INTER_AREA)
49
- dataset.append(resized_image)
50
- else:
51
- print(f"Warning: Failed to load image {img_path}")
52
-
53
  return dataset
54
 
 
 
 
55
 
56
  def calc_glcm_features(images):
57
- features = []
58
- for img in images:
59
- glcm = graycomatrix(img, distances, angles, symmetric=True, normed=True)
60
 
61
- contrast = graycoprops(glcm, "contrast")[0, 0]
62
- dissimilarity = graycoprops(glcm, "dissimilarity")[0, 0]
63
- homogeneity = graycoprops(glcm, "homogeneity")[0, 0]
64
- energy = graycoprops(glcm, "energy")[0, 0]
65
- correlation = graycoprops(glcm, "correlation")[0, 0]
66
 
 
 
 
 
 
 
 
 
 
 
 
67
  features.append([contrast, dissimilarity, homogeneity, energy, correlation])
68
  return features
69
 
70
-
71
  def extract_lbp_features(images):
72
- """Extract LBP features from a list of images."""
73
- lbp_features = []
74
- for image in images:
75
- lbp = local_binary_pattern(image, N_POINTS, RADIUS, method="uniform")
76
- n_bins = int(lbp.max() + 1)
77
- lbp_hist, _ = np.histogram(lbp, bins=n_bins, range=(0, n_bins), density=True)
78
- lbp_features.append(lbp_hist)
79
- return lbp_features
80
-
81
-
82
- # Load datasets
83
- grass_dataset = load_and_convert_images(grass_dir)
84
- wood_dataset = load_and_convert_images(wood_dir)
85
-
86
- # Create labels (0 for grass, 1 for wood)
87
- grass_labels = [0] * len(grass_dataset)
88
- wood_labels = [1] * len(wood_dataset)
89
-
90
- # Calculate features
91
- grass_glcm_features = calc_glcm_features(grass_dataset)
92
- wood_glcm_features = calc_glcm_features(wood_dataset)
93
-
94
- grass_lbp_features = extract_lbp_features(grass_dataset)
95
- wood_lbp_features = extract_lbp_features(wood_dataset)
96
 
97
- # GLCM features for grass and wood
98
- plot_features(np.array(grass_glcm_features), "GLCM Features for Grass Images")
99
- plot_features(np.array(wood_glcm_features), "GLCM Features for Wood Images")
100
 
101
- # LBP features for grass and wood
102
- plot_features(np.array(grass_lbp_features), "LBP Features for Grass Images")
103
- plot_features(np.array(wood_lbp_features), "LBP Features for Wood Images")
104
-
105
- # Combine labels and features for GLCM classifier
106
- glcm_features = grass_glcm_features + wood_glcm_features
107
- glcm_labels = grass_labels + wood_labels
108
-
109
- # Convert to numpy array
110
- glcm_features = np.array(glcm_features)
111
-
112
- # Prepare labels and features for LBP classifier
113
- lbp_features = grass_lbp_features + wood_lbp_features
114
- lbp_labels = grass_labels + wood_labels
115
-
116
- # Convert to numpy array
117
- lbp_features = np.array(lbp_features)
118
-
119
- num_grass = len(grass_dataset) # Number of grass images
120
- num_wood = len(wood_dataset) # Number of wood images
121
-
122
- # Create the labels: 0 for grass, 1 for wood
123
- y = np.array([0] * num_grass + [1] * num_wood)
124
-
125
- # Define KFold cross-validation
126
- k = 5
127
- kf = KFold(n_splits=k, shuffle=True, random_state=42)
128
-
129
- # Store results for GLCM and LBP classifiers
130
- glcm_accuracy_list = []
131
- lbp_accuracy_list = []
132
-
133
- # Parameter tuning using GridSearchCV for KNN classifier
134
- param_grid = {"n_neighbors": [3, 5, 7], "p": [1, 2]}
135
-
136
- # GLCM Classifier Training and Evaluation
137
- glcm_knn = KNeighborsClassifier()
138
- glcm_grid_search = GridSearchCV(glcm_knn, param_grid, cv=kf)
139
- glcm_grid_search.fit(glcm_features, y)
140
-
141
- print("Best parameters for GLCM KNN:", glcm_grid_search.best_params_)
142
-
143
- # Perform cross-validation and evaluate GLCM classifier
144
- for train_index, test_index in kf.split(glcm_features):
145
- x_train, x_test = glcm_features[train_index], glcm_features[test_index]
146
- y_train, y_test = y[train_index], y[test_index]
147
-
148
- glcm_classifier = KNeighborsClassifier(
149
- n_neighbors=glcm_grid_search.best_params_["n_neighbors"]
150
- )
151
- glcm_classifier.fit(x_train, y_train)
152
- y_pred = glcm_classifier.predict(x_test)
153
-
154
- accuracy = accuracy_score(y_test, y_pred)
155
- glcm_accuracy_list.append(accuracy)
156
-
157
- # Print overall GLCM accuracy
158
- print(f"GLCM Cross-validated accuracy: {np.mean(glcm_accuracy_list) * 100:.2f}%")
159
-
160
- # LBP Classifier Training and Evaluation
161
- lbp_knn = KNeighborsClassifier()
162
- lbp_grid_search = GridSearchCV(lbp_knn, param_grid, cv=kf)
163
- lbp_grid_search.fit(lbp_features, y)
164
-
165
- print("Best parameters for LBP KNN:", lbp_grid_search.best_params_)
166
-
167
- # Perform cross-validation and evaluate LBP classifier
168
- for train_index, test_index in kf.split(lbp_features):
169
- x_train, x_test = lbp_features[train_index], lbp_features[test_index]
170
- y_train, y_test = y[train_index], y[test_index]
171
-
172
- lbp_classifier = KNeighborsClassifier(
173
- n_neighbors=lbp_grid_search.best_params_["n_neighbors"],
174
- p=lbp_grid_search.best_params_["p"]
175
- )
176
- lbp_classifier.fit(x_train, y_train)
177
- y_pred = lbp_classifier.predict(x_test)
178
-
179
- accuracy = accuracy_score(y_test, y_pred)
180
- lbp_accuracy_list.append(accuracy)
181
-
182
- # Print overall LBP accuracy
183
- print(f"LBP Cross-validated accuracy: {np.mean(lbp_accuracy_list) * 100:.2f}%")
184
 
185
- # Preprocess uploaded image for classification
186
- def preprocess_image(image):
187
- gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # Convert to grayscale
188
- resized_image = cv2.resize(gray_image, TARGET_SIZE, interpolation=cv2.INTER_AREA) # Resize to match training size
189
- return resized_image
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
 
191
- # Define the Gradio interface
192
- def classify_uploaded_image(image, algorithm):
193
- image = preprocess_image(np.array(image, dtype=np.uint8)) # Preprocess uploaded image
194
 
195
- if algorithm == "GLCM":
196
- features = calc_glcm_features([image]) # Use parentheses, pass as a list
197
- prediction = glcm_classifier.predict(features)
198
- elif algorithm == "LBP":
199
- features = extract_lbp_features([image])
200
- prediction = lbp_classifier.predict(features)
201
  else:
202
- raise ValueError(f"Algorithm '{algorithm}' is not recognized.")
 
203
 
204
- return "Grass" if prediction[0] == 0 else "Wood"
205
 
206
- # Gradio Interface Setup
207
  iface = gr.Interface(
208
- fn=classify_uploaded_image,
209
  inputs=[
210
- gr.Image(type="numpy", label="Upload an Image"),
211
- gr.Dropdown(choices=["GLCM", "LBP"], label="Algorithm"),
212
  ],
213
- outputs="text",
214
  title="Texture Classification",
 
215
  )
216
 
217
- # Launch the interface
218
  iface.launch()
 
 
1
  import glob
2
+ import cv2
3
  import numpy as np
4
+ import gradio as gr
5
  import matplotlib.pyplot as plt
6
+ from sklearn.model_selection import KFold, GridSearchCV
 
7
  from sklearn.neighbors import KNeighborsClassifier
8
+ from sklearn.metrics import (
9
+ accuracy_score,
10
+ classification_report,
11
+ confusion_matrix,
12
+ precision_score,
13
+ recall_score,
14
+ f1_score,
15
+ )
16
+ from skimage.feature import graycomatrix, graycoprops, local_binary_pattern
 
 
 
 
 
17
 
18
  # Define directories for grass and wood images
19
  grass_dir = "images/Grass/Train_Grass"
20
  wood_dir = "images/Wood/Train_Wood"
21
 
22
+ # Constants for Local Binary Pattern (LBP) and Gray Level Co-occurrence Matrix (GLCM)
23
  RADIUS = 1
24
  N_POINTS = 12 * RADIUS
25
  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
+
32
+ Args:
33
+ directory (str): The path to the image directory.
34
+
35
+ Returns:
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
+ # Load datasets using glob
51
+ grass_dataset = load_and_convert_images(grass_dir)
52
+ wood_dataset = load_and_convert_images(wood_dir)
53
 
54
  def calc_glcm_features(images):
55
+ """Calculate GLCM features for a list of images.
 
 
56
 
57
+ Args:
58
+ images (list): A list of grayscale images.
 
 
 
59
 
60
+ Returns:
61
+ list: A list of GLCM features for each image.
62
+ """
63
+ features = []
64
+ for image in images:
65
+ glcm = graycomatrix(image, distances=distances, angles=angles, symmetric=True, normed=True)
66
+ contrast = graycoprops(glcm, 'contrast')[0, 0]
67
+ dissimilarity = graycoprops(glcm, 'dissimilarity')[0, 0]
68
+ homogeneity = graycoprops(glcm, 'homogeneity')[0, 0]
69
+ energy = graycoprops(glcm, 'energy')[0, 0]
70
+ correlation = graycoprops(glcm, 'correlation')[0, 0]
71
  features.append([contrast, dissimilarity, homogeneity, energy, correlation])
72
  return features
73
 
 
74
  def extract_lbp_features(images):
75
+ """Extract LBP features for a list of images.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
 
77
+ Args:
78
+ images (list): A list of grayscale images.
 
79
 
80
+ Returns:
81
+ list: A list of LBP features for each image.
82
+ """
83
+ features = []
84
+ for image in images:
85
+ lbp = local_binary_pattern(image, N_POINTS, RADIUS, method="uniform")
86
+ lbp_hist, _ = np.histogram(lbp.ravel(), bins=np.arange(0, N_POINTS + 3), range=(0, N_POINTS + 2))
87
+ lbp_hist = lbp_hist.astype("float")
88
+ lbp_hist /= lbp_hist.sum() # Normalize the histogram
89
+ features.append(lbp_hist)
90
+ return features
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
 
92
+ # Train classifiers (for example purposes, using KNN)
93
+ X = np.concatenate([grass_dataset, wood_dataset])
94
+ y = np.concatenate([np.zeros(len(grass_dataset)), np.ones(len(wood_dataset))]) # Labels: 0 for Grass, 1 for Wood
95
+
96
+ # Extract GLCM and LBP features
97
+ glcm_features = calc_glcm_features(X)
98
+ lbp_features = extract_lbp_features(X)
99
+
100
+ # KFold cross-validation
101
+ kf = KFold(n_splits=5)
102
+
103
+ # Example: KNN classifier for GLCM features
104
+ knn_glcm = KNeighborsClassifier(n_neighbors=3)
105
+ knn_glcm.fit(glcm_features, y)
106
+
107
+ # Example: KNN classifier for LBP features
108
+ knn_lbp = KNeighborsClassifier(n_neighbors=3)
109
+ knn_lbp.fit(lbp_features, y)
110
+
111
+ def classify_texture(image, method):
112
+ """Classify the texture of the uploaded image as grass or wood using the selected method.
113
+
114
+ Args:
115
+ image (numpy.ndarray): The uploaded image to classify.
116
+ method (str): The feature extraction method ('GLCM' or 'LBP').
117
+
118
+ Returns:
119
+ Tuple[str, numpy.ndarray]: The classification result ('Grass' or 'Wood') and the highlighted image.
120
+ """
121
+ # Pre-process the image
122
+ gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
123
+ resized_image = cv2.resize(gray_image, TARGET_SIZE, interpolation=cv2.INTER_AREA)
124
+
125
+ # Extract features based on the selected method
126
+ if method == "GLCM":
127
+ feature = calc_glcm_features([resized_image])
128
+ prediction = knn_glcm.predict(feature)
129
+ elif method == "LBP":
130
+ feature = extract_lbp_features([resized_image])
131
+ prediction = knn_lbp.predict(feature)
132
+ else:
133
+ raise ValueError("The method is not recognized")
134
 
135
+ # Classify the prediction
136
+ result = "Grass" if prediction == 0 else "Wood"
 
137
 
138
+ # Highlight the image based on the classification
139
+ if result == "Grass":
140
+ highlighted_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # Convert to RGB for displaying
141
+ highlighted_image[:] = [0, 255, 0] # Highlight in green
 
 
142
  else:
143
+ highlighted_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
144
+ highlighted_image[:] = [165, 42, 42] # Highlight in brown
145
 
146
+ return result, highlighted_image
147
 
148
+ # Gradio interface setup with a dropdown for method selection
149
  iface = gr.Interface(
150
+ fn=classify_texture,
151
  inputs=[
152
+ gr.Image(type="numpy", label="Upload Image"),
153
+ gr.Dropdown(choices=["GLCM", "LBP"], label="Select Feature Extraction Method"),
154
  ],
155
+ outputs=["text", gr.Image(type="numpy", label="Highlighted Image")],
156
  title="Texture Classification",
157
+ description="Upload an image of grass or wood to classify the texture. Select GLCM or LBP as the method.",
158
  )
159
 
160
+ # Launch Gradio interface
161
  iface.launch()