Kalhar.Pandya
commited on
Commit
·
abd2768
1
Parent(s):
85c3feb
Added images and model with Git LFS
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- app.py +43 -13
- images_dataset/brick/patch_001.png +0 -0
- images_dataset/brick/patch_002.png +0 -0
- images_dataset/brick/patch_003.png +0 -0
- images_dataset/brick/patch_004.png +0 -0
- images_dataset/brick/patch_005.png +0 -0
- images_dataset/brick/patch_006.png +0 -0
- images_dataset/brick/patch_007.png +0 -0
- images_dataset/brick/patch_008.png +0 -0
- images_dataset/brick/patch_009.png +0 -0
- images_dataset/brick/patch_010.png +0 -0
- images_dataset/brick/patch_011.png +0 -0
- images_dataset/brick/patch_012.png +0 -0
- images_dataset/brick/patch_013.png +0 -0
- images_dataset/brick/patch_014.png +0 -0
- images_dataset/brick/patch_015.png +0 -0
- images_dataset/brick/patch_016.png +0 -0
- images_dataset/brick/patch_017.png +0 -0
- images_dataset/brick/patch_018.png +0 -0
- images_dataset/brick/patch_019.png +0 -0
- images_dataset/brick/patch_020.png +0 -0
- images_dataset/brick/patch_021.png +0 -0
- images_dataset/brick/patch_022.png +0 -0
- images_dataset/brick/patch_023.png +0 -0
- images_dataset/brick/patch_024.png +0 -0
- images_dataset/brick/patch_025.png +0 -0
- images_dataset/brick/patch_026.png +0 -0
- images_dataset/brick/patch_027.png +0 -0
- images_dataset/brick/patch_028.png +0 -0
- images_dataset/brick/patch_029.png +0 -0
- images_dataset/brick/patch_030.png +0 -0
- images_dataset/brick/patch_031.png +0 -0
- images_dataset/brick/patch_032.png +0 -0
- images_dataset/brick/patch_033.png +0 -0
- images_dataset/brick/patch_034.png +0 -0
- images_dataset/brick/patch_035.png +0 -0
- images_dataset/brick/patch_036.png +0 -0
- images_dataset/brick/patch_037.png +0 -0
- images_dataset/brick/patch_038.png +0 -0
- images_dataset/brick/patch_039.png +0 -0
- images_dataset/brick/patch_040.png +0 -0
- images_dataset/brick/patch_041.png +0 -0
- images_dataset/brick/patch_042.png +0 -0
- images_dataset/brick/patch_043.png +0 -0
- images_dataset/brick/patch_044.png +0 -0
- images_dataset/brick/patch_045.png +0 -0
- images_dataset/brick/patch_046.png +0 -0
- images_dataset/brick/patch_047.png +0 -0
- images_dataset/brick/patch_048.png +0 -0
- images_dataset/brick/patch_049.png +0 -0
app.py
CHANGED
|
@@ -34,8 +34,12 @@ def load_model(model_filename):
|
|
| 34 |
def classify_new_image(input_image_path, model_choice):
|
| 35 |
"""
|
| 36 |
Expects input_image_path as a file path and model_choice as one of the keys in models.
|
| 37 |
-
Loads the image, processes it by extracting patches
|
| 38 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
"""
|
| 40 |
global models, training_log, class_names
|
| 41 |
progress_log = training_log + "\nStarting classification...\n"
|
|
@@ -69,13 +73,12 @@ def classify_new_image(input_image_path, model_choice):
|
|
| 69 |
|
| 70 |
# Patch extraction parameters
|
| 71 |
patch_size = (100, 100)
|
| 72 |
-
edge_density_thresh_low = 0.0
|
| 73 |
-
edge_density_thresh_high = 0.5
|
| 74 |
patch_w, patch_h = patch_size
|
| 75 |
img_h, img_w = gray.shape
|
| 76 |
|
| 77 |
valid_patch_count = 0
|
| 78 |
summed_probabilities = None
|
|
|
|
| 79 |
|
| 80 |
# Loop over non-overlapping patches
|
| 81 |
for y in range(0, img_h - patch_h + 1, patch_h):
|
|
@@ -87,12 +90,16 @@ def classify_new_image(input_image_path, model_choice):
|
|
| 87 |
density = num_edge_pixels / total_pixels
|
| 88 |
progress_log += f"Patch at ({x}, {y}) - edge density: {density:.3f}\n"
|
| 89 |
|
| 90 |
-
if
|
| 91 |
valid_patch_count += 1
|
| 92 |
features = extract_features_from_image(patch)
|
| 93 |
feature_vector = features['combined_features'].reshape(1, -1)
|
| 94 |
patch_probabilities = classifier.predict_proba(feature_vector)[0]
|
| 95 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 96 |
|
| 97 |
if summed_probabilities is None:
|
| 98 |
summed_probabilities = patch_probabilities
|
|
@@ -107,10 +114,8 @@ def classify_new_image(input_image_path, model_choice):
|
|
| 107 |
summed_probabilities = classifier.predict_proba(feature_vector)[0]
|
| 108 |
valid_patch_count = 1
|
| 109 |
|
| 110 |
-
# Average the probabilities from all valid patches
|
| 111 |
averaged_probabilities = summed_probabilities / valid_patch_count
|
| 112 |
-
|
| 113 |
-
# Normalize the averaged probabilities so they sum to 1
|
| 114 |
normalized_probabilities = averaged_probabilities / np.sum(averaged_probabilities)
|
| 115 |
|
| 116 |
final_prediction_index = np.argmax(normalized_probabilities)
|
|
@@ -120,7 +125,32 @@ def classify_new_image(input_image_path, model_choice):
|
|
| 120 |
|
| 121 |
print(progress_log)
|
| 122 |
print(prob_dict)
|
| 123 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 124 |
|
| 125 |
# ---------------------------------------------------------------------
|
| 126 |
# Gradio Interface Setup using file paths and model selection
|
|
@@ -130,7 +160,6 @@ if __name__ == "__main__":
|
|
| 130 |
load_model(model_filename)
|
| 131 |
|
| 132 |
# Create a dropdown for model selection.
|
| 133 |
-
# If models dict is not yet populated, we set default choices.
|
| 134 |
model_choices = list(models.keys()) if models else ['svm', 'rf', 'combined']
|
| 135 |
|
| 136 |
iface = gr.Interface(
|
|
@@ -141,11 +170,12 @@ if __name__ == "__main__":
|
|
| 141 |
],
|
| 142 |
outputs=[
|
| 143 |
gr.Label(label="Predicted Class"),
|
| 144 |
-
gr.Label(label="Probabilities")
|
|
|
|
| 145 |
],
|
| 146 |
title="Stone, Wood, Brick Classifier",
|
| 147 |
description=("Upload an image and select a classifier model (svm, rf, combined) to classify it.\n\n"
|
| 148 |
"The image is processed by subdividing it into patches and aggregating the predictions. "
|
| 149 |
-
"Progress logs are printed to the terminal.")
|
| 150 |
)
|
| 151 |
iface.launch(share=True)
|
|
|
|
| 34 |
def classify_new_image(input_image_path, model_choice):
|
| 35 |
"""
|
| 36 |
Expects input_image_path as a file path and model_choice as one of the keys in models.
|
| 37 |
+
Loads the image, processes it by extracting patches, classifies each patch, and aggregates
|
| 38 |
+
patch predictions. Also, draws transparent overlays on each patch according to its predicted label.
|
| 39 |
+
Returns:
|
| 40 |
+
annotated_image_rgb (numpy array): The image with transparent overlays.
|
| 41 |
+
final_prediction (str): The final predicted class.
|
| 42 |
+
prob_dict (dict): Dictionary of class probabilities.
|
| 43 |
"""
|
| 44 |
global models, training_log, class_names
|
| 45 |
progress_log = training_log + "\nStarting classification...\n"
|
|
|
|
| 73 |
|
| 74 |
# Patch extraction parameters
|
| 75 |
patch_size = (100, 100)
|
|
|
|
|
|
|
| 76 |
patch_w, patch_h = patch_size
|
| 77 |
img_h, img_w = gray.shape
|
| 78 |
|
| 79 |
valid_patch_count = 0
|
| 80 |
summed_probabilities = None
|
| 81 |
+
overlays_list = [] # To store (x, y, w, h, predicted_label) for each valid patch
|
| 82 |
|
| 83 |
# Loop over non-overlapping patches
|
| 84 |
for y in range(0, img_h - patch_h + 1, patch_h):
|
|
|
|
| 90 |
density = num_edge_pixels / total_pixels
|
| 91 |
progress_log += f"Patch at ({x}, {y}) - edge density: {density:.3f}\n"
|
| 92 |
|
| 93 |
+
if 0.0 < density < 0.5:
|
| 94 |
valid_patch_count += 1
|
| 95 |
features = extract_features_from_image(patch)
|
| 96 |
feature_vector = features['combined_features'].reshape(1, -1)
|
| 97 |
patch_probabilities = classifier.predict_proba(feature_vector)[0]
|
| 98 |
+
predicted_index = np.argmax(patch_probabilities)
|
| 99 |
+
predicted_label = class_names[predicted_index]
|
| 100 |
+
progress_log += f"Patch at ({x}, {y}) predicted: {predicted_label} with probabilities {patch_probabilities}\n"
|
| 101 |
+
|
| 102 |
+
overlays_list.append((x, y, patch_w, patch_h, predicted_label))
|
| 103 |
|
| 104 |
if summed_probabilities is None:
|
| 105 |
summed_probabilities = patch_probabilities
|
|
|
|
| 114 |
summed_probabilities = classifier.predict_proba(feature_vector)[0]
|
| 115 |
valid_patch_count = 1
|
| 116 |
|
| 117 |
+
# Average the probabilities from all valid patches and normalize them
|
| 118 |
averaged_probabilities = summed_probabilities / valid_patch_count
|
|
|
|
|
|
|
| 119 |
normalized_probabilities = averaged_probabilities / np.sum(averaged_probabilities)
|
| 120 |
|
| 121 |
final_prediction_index = np.argmax(normalized_probabilities)
|
|
|
|
| 125 |
|
| 126 |
print(progress_log)
|
| 127 |
print(prob_dict)
|
| 128 |
+
|
| 129 |
+
# Create an annotated image with transparent overlays
|
| 130 |
+
annotated_image = resized_image.copy()
|
| 131 |
+
overlay = annotated_image.copy()
|
| 132 |
+
alpha = 0.4 # Transparency factor
|
| 133 |
+
|
| 134 |
+
# Define overlay colors in BGR for each class (adjust as desired)
|
| 135 |
+
color_map = {
|
| 136 |
+
'wood': (0, 255, 255), # Yellow (BGR format)
|
| 137 |
+
'brick': (0, 0, 255), # Red (BGR format)
|
| 138 |
+
'stone': (128, 128, 128) # Gray (BGR format)
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
for (x, y, w, h, label) in overlays_list:
|
| 142 |
+
label_lower = label.lower()
|
| 143 |
+
if prob_dict[label] < 0.2:
|
| 144 |
+
continue
|
| 145 |
+
color = color_map.get(label_lower, (0, 255, 0)) # Default to green if unknown
|
| 146 |
+
cv2.rectangle(overlay, (x, y), (x+w, y+h), color, thickness=-1)
|
| 147 |
+
|
| 148 |
+
# Blend the overlay with the original image
|
| 149 |
+
annotated_image = cv2.addWeighted(overlay, alpha, annotated_image, 1 - alpha, 0)
|
| 150 |
+
# Convert annotated image from BGR to RGB for Gradio display
|
| 151 |
+
annotated_image_rgb = cv2.cvtColor(annotated_image, cv2.COLOR_BGR2RGB)
|
| 152 |
+
|
| 153 |
+
return final_prediction, prob_dict, annotated_image_rgb
|
| 154 |
|
| 155 |
# ---------------------------------------------------------------------
|
| 156 |
# Gradio Interface Setup using file paths and model selection
|
|
|
|
| 160 |
load_model(model_filename)
|
| 161 |
|
| 162 |
# Create a dropdown for model selection.
|
|
|
|
| 163 |
model_choices = list(models.keys()) if models else ['svm', 'rf', 'combined']
|
| 164 |
|
| 165 |
iface = gr.Interface(
|
|
|
|
| 170 |
],
|
| 171 |
outputs=[
|
| 172 |
gr.Label(label="Predicted Class"),
|
| 173 |
+
gr.Label(label="Probabilities"),
|
| 174 |
+
gr.Image(label="Annotated Image")
|
| 175 |
],
|
| 176 |
title="Stone, Wood, Brick Classifier",
|
| 177 |
description=("Upload an image and select a classifier model (svm, rf, combined) to classify it.\n\n"
|
| 178 |
"The image is processed by subdividing it into patches and aggregating the predictions. "
|
| 179 |
+
"Transparent overlays are drawn on detected objects. Progress logs are printed to the terminal.")
|
| 180 |
)
|
| 181 |
iface.launch(share=True)
|
images_dataset/brick/patch_001.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_002.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_003.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_004.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_005.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_006.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_007.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_008.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_009.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_010.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_011.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_012.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_013.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_014.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_015.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_016.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_017.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_018.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_019.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_020.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_021.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_022.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_023.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_024.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_025.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_026.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_027.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_028.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_029.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_030.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_031.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_032.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_033.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_034.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_035.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_036.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_037.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_038.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_039.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_040.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_041.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_042.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_043.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_044.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_045.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_046.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_047.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_048.png
CHANGED
|
|
Git LFS Details
|
images_dataset/brick/patch_049.png
CHANGED
|
|
Git LFS Details
|