BlueSR commited on
Commit
ce2ce33
·
verified ·
1 Parent(s): 89ab7a4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +117 -78
app.py CHANGED
@@ -6,62 +6,122 @@ import gradio as gr
6
  import numpy as np
7
  from PIL import Image
8
  import joblib
9
- import json
10
- from sklearn.tree import export_text
11
 
12
  # Constants
13
  NUM_CLASSES = 4
14
  DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
15
  CLASS_NAMES = ['Cracked_road', 'Flooded_muddy', 'Good_condition', 'Potholes']
16
 
17
- # Load the CNN model
18
- def load_cnn_model():
19
- # Build model architecture (same as in train_cnn.py)
20
  model = efficientnet_b0(weights=None)
21
 
22
- # Replace classifier
23
  in_features = model.classifier[1].in_features
24
  model.classifier = nn.Sequential(
25
  nn.Linear(in_features, 256),
26
  nn.BatchNorm1d(256),
27
  nn.ReLU(),
28
  nn.Dropout(p=0.2),
29
- nn.Linear(256, NUM_CLASSES)
30
  )
31
 
32
- # Load the saved weights
33
- model.load_state_dict(torch.load("best_cnn_model.pth", map_location=DEVICE))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  model.to(DEVICE)
35
  model.eval()
36
  return model
37
 
38
  # Load the Random Forest model
39
  def load_rf_model():
40
- with open("rf_model.pkl", "rb") as f:
41
- return joblib.load(f)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
 
43
  # Preprocess image for CNN
44
  def preprocess_image_cnn(image):
 
45
  preprocess = transforms.Compose([
46
  transforms.Resize((224, 224)),
 
47
  transforms.ToTensor(),
48
  transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
49
  ])
50
  return preprocess(image).unsqueeze(0)
51
 
52
  # Preprocess image for RF
53
- def preprocess_image_rf(image):
54
- # Convert to numpy, resize, and flatten
55
- image = image.resize((64, 64))
56
- image_array = np.array(image)
57
- # If grayscale, expand to RGB
58
- if len(image_array.shape) == 2:
59
- image_array = np.stack([image_array] * 3, axis=2)
60
- # Flatten the image
61
- return image_array.reshape(1, -1)
62
 
63
  # Prediction function
64
  def predict(img, model_choice, cnn_model, rf_model):
 
65
  if img is None:
66
  return "No image provided", "Please upload an image"
67
 
@@ -85,8 +145,8 @@ def predict(img, model_choice, cnn_model, rf_model):
85
  return CLASS_NAMES[predicted_class], confidence_text
86
 
87
  else: # Random Forest
88
- # Preprocess for RF
89
- img_features = preprocess_image_rf(img)
90
 
91
  # Get prediction
92
  predicted_class = rf_model.predict(img_features)[0]
@@ -102,76 +162,55 @@ def predict(img, model_choice, cnn_model, rf_model):
102
  except Exception as e:
103
  return f"Error: {str(e)}", "An error occurred during prediction."
104
 
105
- # Convert Random Forest to a safer JSON format
106
- def convert_rf_to_safe_format():
107
- """Convert Random Forest to a safer JSON format"""
108
-
109
- # Load the existing model
110
- rf_model = joblib.load("models/rf_model.pkl")
111
-
112
- # Extract model parameters
113
- model_params = {
114
- 'n_estimators': rf_model.n_estimators,
115
- 'max_depth': rf_model.max_depth,
116
- 'min_samples_split': rf_model.min_samples_split,
117
- 'random_state': rf_model.random_state,
118
- 'classes': rf_model.classes_.tolist(),
119
- 'n_features': rf_model.n_features_in_,
120
- 'feature_importances': rf_model.feature_importances_.tolist()
121
- }
122
-
123
- # Save model parameters
124
- with open("rf_model_params.json", "w") as f:
125
- json.dump(model_params, f)
126
-
127
- # Save individual tree parameters (simplified approach)
128
- trees_data = []
129
- for i, tree in enumerate(rf_model.estimators_):
130
- tree_data = {
131
- 'tree_id': i,
132
- 'feature': tree.tree_.feature.tolist(),
133
- 'threshold': tree.tree_.threshold.tolist(),
134
- 'children_left': tree.tree_.children_left.tolist(),
135
- 'children_right': tree.tree_.children_right.tolist(),
136
- 'value': tree.tree_.value.tolist()
137
- }
138
- trees_data.append(tree_data)
139
-
140
- with open("rf_trees_data.json", "w") as f:
141
- json.dump(trees_data, f)
142
-
143
- print("Model converted to safe JSON format")
144
-
145
- # Load models
146
- cnn_model = load_cnn_model()
147
- rf_model = load_rf_model()
148
 
149
  # Create Gradio interface
150
- with gr.Blocks() as demo:
151
- gr.Markdown("## Road Surface Classification")
 
152
 
153
  with gr.Row():
154
  with gr.Column():
155
  image_input = gr.Image(type="pil", label="Upload Road Image")
156
- model_selector = gr.Radio(choices=["CNN", "Random Forest"], value="CNN", label="Select Model")
157
- classify_btn = gr.Button("Classify")
 
 
 
 
 
158
  with gr.Column():
159
- label_output = gr.Textbox(label="Predicted Class")
160
- confidence_output = gr.Textbox(label="Confidence Scores", lines=5)
 
 
 
 
161
 
 
162
  classify_btn.click(
163
  fn=lambda img, model_choice: predict(img, model_choice, cnn_model, rf_model),
164
  inputs=[image_input, model_selector],
165
  outputs=[label_output, confidence_output]
166
  )
167
 
168
- gr.Markdown("### How to use")
169
- gr.Markdown("1. Upload a road image")
170
- gr.Markdown("2. Select either CNN or Random Forest model")
171
- gr.Markdown("3. Click 'Classify' to get the prediction")
 
 
172
 
173
  # Launch the app
174
- demo.launch()
175
-
176
  if __name__ == "__main__":
177
- convert_rf_to_safe_format()
 
6
  import numpy as np
7
  from PIL import Image
8
  import joblib
9
+ import os
 
10
 
11
  # Constants
12
  NUM_CLASSES = 4
13
  DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
14
  CLASS_NAMES = ['Cracked_road', 'Flooded_muddy', 'Good_condition', 'Potholes']
15
 
16
+ # Build CNN model architecture (from train_cnn.py)
17
+ def build_model(num_classes=4):
18
+ """Build EfficientNet-B0 based model for road surface classification"""
19
  model = efficientnet_b0(weights=None)
20
 
21
+ # Replace classifier with custom layers
22
  in_features = model.classifier[1].in_features
23
  model.classifier = nn.Sequential(
24
  nn.Linear(in_features, 256),
25
  nn.BatchNorm1d(256),
26
  nn.ReLU(),
27
  nn.Dropout(p=0.2),
28
+ nn.Linear(256, num_classes)
29
  )
30
 
31
+ return model
32
+
33
+ # Load the CNN model
34
+ def load_cnn_model():
35
+ """Load the trained CNN model"""
36
+ model = build_model(NUM_CLASSES)
37
+
38
+ # Try different possible paths for the model file
39
+ model_paths = [
40
+ "best_cnn_model.pth",
41
+ "models/best_cnn_model.pth",
42
+ "assign2_Latest/models/best_cnn_model.pth"
43
+ ]
44
+
45
+ model_loaded = False
46
+ for path in model_paths:
47
+ if os.path.exists(path):
48
+ try:
49
+ model.load_state_dict(torch.load(path, map_location=DEVICE))
50
+ model_loaded = True
51
+ print(f"CNN model loaded from {path}")
52
+ break
53
+ except Exception as e:
54
+ print(f"Failed to load from {path}: {e}")
55
+ continue
56
+
57
+ if not model_loaded:
58
+ raise FileNotFoundError("Could not find or load CNN model file")
59
+
60
  model.to(DEVICE)
61
  model.eval()
62
  return model
63
 
64
  # Load the Random Forest model
65
  def load_rf_model():
66
+ """Load the trained Random Forest model"""
67
+ rf_paths = [
68
+ "rf_model.pkl",
69
+ "models/rf_model.pkl",
70
+ "assign2_Latest/models/rf_model.pkl"
71
+ ]
72
+
73
+ for path in rf_paths:
74
+ if os.path.exists(path):
75
+ try:
76
+ return joblib.load(path)
77
+ except Exception as e:
78
+ print(f"Failed to load RF model from {path}: {e}")
79
+ continue
80
+
81
+ raise FileNotFoundError("Could not find or load Random Forest model file")
82
+
83
+ # Extract features using CNN for Random Forest
84
+ def extract_features_single(cnn_model, image_tensor):
85
+ """Extract features from a single image using CNN for Random Forest"""
86
+ cnn_model.eval()
87
+ with torch.no_grad():
88
+ # Get features from the layer before final classification
89
+ features = cnn_model.features(image_tensor)
90
+ features = cnn_model.avgpool(features)
91
+ features = torch.flatten(features, 1)
92
+
93
+ # Pass through the first part of classifier (before final layer)
94
+ if hasattr(cnn_model.classifier, '__iter__'):
95
+ for i, layer in enumerate(cnn_model.classifier[:-1]): # Exclude final classification layer
96
+ features = layer(features)
97
+
98
+ return features.cpu().numpy()
99
 
100
  # Preprocess image for CNN
101
  def preprocess_image_cnn(image):
102
+ """Preprocess image for CNN prediction"""
103
  preprocess = transforms.Compose([
104
  transforms.Resize((224, 224)),
105
+ transforms.CenterCrop(224),
106
  transforms.ToTensor(),
107
  transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
108
  ])
109
  return preprocess(image).unsqueeze(0)
110
 
111
  # Preprocess image for RF
112
+ def preprocess_image_rf(image, cnn_model):
113
+ """Preprocess image for Random Forest prediction using CNN features"""
114
+ # First preprocess for CNN
115
+ img_tensor = preprocess_image_cnn(image)
116
+ img_tensor = img_tensor.to(DEVICE)
117
+
118
+ # Extract features using CNN
119
+ features = extract_features_single(cnn_model, img_tensor)
120
+ return features
121
 
122
  # Prediction function
123
  def predict(img, model_choice, cnn_model, rf_model):
124
+ """Make prediction using selected model"""
125
  if img is None:
126
  return "No image provided", "Please upload an image"
127
 
 
145
  return CLASS_NAMES[predicted_class], confidence_text
146
 
147
  else: # Random Forest
148
+ # Preprocess for RF using CNN features
149
+ img_features = preprocess_image_rf(img, cnn_model)
150
 
151
  # Get prediction
152
  predicted_class = rf_model.predict(img_features)[0]
 
162
  except Exception as e:
163
  return f"Error: {str(e)}", "An error occurred during prediction."
164
 
165
+ # Initialize models
166
+ print("Loading models...")
167
+ try:
168
+ cnn_model = load_cnn_model()
169
+ rf_model = load_rf_model()
170
+ print("Models loaded successfully!")
171
+ except Exception as e:
172
+ print(f"Error loading models: {e}")
173
+ # Create dummy models for testing
174
+ cnn_model = None
175
+ rf_model = None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176
 
177
  # Create Gradio interface
178
+ with gr.Blocks(title="Road Surface Classification") as demo:
179
+ gr.Markdown("# Road Surface Classification")
180
+ gr.Markdown("Upload an image of a road surface to classify its condition using either CNN or Random Forest models.")
181
 
182
  with gr.Row():
183
  with gr.Column():
184
  image_input = gr.Image(type="pil", label="Upload Road Image")
185
+ model_selector = gr.Radio(
186
+ choices=["CNN", "Random Forest"],
187
+ value="CNN",
188
+ label="Select Model"
189
+ )
190
+ classify_btn = gr.Button("Classify", variant="primary")
191
+
192
  with gr.Column():
193
+ label_output = gr.Textbox(label="Predicted Class", interactive=False)
194
+ confidence_output = gr.Textbox(
195
+ label="Confidence Scores",
196
+ lines=5,
197
+ interactive=False
198
+ )
199
 
200
+ # Event handler
201
  classify_btn.click(
202
  fn=lambda img, model_choice: predict(img, model_choice, cnn_model, rf_model),
203
  inputs=[image_input, model_selector],
204
  outputs=[label_output, confidence_output]
205
  )
206
 
207
+ # Add information about classes
208
+ gr.Markdown("### Classes")
209
+ gr.Markdown("- **Cracked_road**: Roads with visible cracks")
210
+ gr.Markdown("- **Flooded_muddy**: Roads affected by flooding or mud")
211
+ gr.Markdown("- **Good_condition**: Roads in good condition")
212
+ gr.Markdown("- **Potholes**: Roads with potholes")
213
 
214
  # Launch the app
 
 
215
  if __name__ == "__main__":
216
+ demo.launch()