Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -6,6 +6,7 @@ import certifi
|
|
| 6 |
import numpy as np
|
| 7 |
import gradio as gr
|
| 8 |
import torch.nn as nn
|
|
|
|
| 9 |
from torchvision import models
|
| 10 |
import torch.nn.functional as F
|
| 11 |
import matplotlib.pyplot as plt
|
|
@@ -32,7 +33,7 @@ with urllib.request.urlopen(url) as f:
|
|
| 32 |
cifar10_classes = {int(k): v[1] for k, v in imagenet_classes.items()}
|
| 33 |
|
| 34 |
# Load the pre-trained ResNet model
|
| 35 |
-
model = models.
|
| 36 |
|
| 37 |
# Modify the classifier for 6 classes with an additional hidden layer
|
| 38 |
# model.fc = nn.Sequential(
|
|
@@ -182,83 +183,97 @@ def superimpose_images(base_image, overlay_image, alpha):
|
|
| 182 |
|
| 183 |
return Image.fromarray(blended_array)
|
| 184 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 185 |
# Prediction function
|
| 186 |
-
def predict(image, brightness, contrast, hue, overlay_image, alpha):
|
| 187 |
-
"""
|
| 188 |
if image is None:
|
| 189 |
return None, None, None
|
| 190 |
|
| 191 |
-
# Apply
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 196 |
|
| 197 |
-
|
| 198 |
-
image_tensor = transform_image(final_image)
|
| 199 |
|
| 200 |
-
with torch.no_grad():
|
| 201 |
-
output = model(image_tensor)
|
| 202 |
-
probabilities = F.softmax(output, dim=1).cpu().numpy()[0]
|
| 203 |
-
# pred_class = np.argmax(probabilities)
|
| 204 |
-
# top_5 = torch.topk(probabilities, 5)
|
| 205 |
-
|
| 206 |
-
heatmap, _ = gradcam.generate(image_tensor)
|
| 207 |
-
|
| 208 |
-
# Create GradCAM overlay
|
| 209 |
-
final_np = np.array(final_image)
|
| 210 |
-
heatmap = cv2.resize(heatmap, (final_np.shape[1], final_np.shape[0]))
|
| 211 |
-
heatmap = np.uint8(255 * heatmap)
|
| 212 |
-
heatmap_colored = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET)
|
| 213 |
-
heatmap_rgb = cv2.cvtColor(heatmap_colored, cv2.COLOR_BGR2RGB)
|
| 214 |
-
superimposed = cv2.addWeighted(heatmap_rgb, 0.5, final_np, 0.5, 0)
|
| 215 |
-
gradcam_image = Image.fromarray(superimposed)
|
| 216 |
-
|
| 217 |
-
|
| 218 |
-
# Generate Bar Chart
|
| 219 |
-
with plt.xkcd():
|
| 220 |
-
fig, ax = plt.subplots(figsize=(6, 4))
|
| 221 |
-
top5_indices = np.argsort(probabilities)[-5:][::-1] # Indices of top 5 probabilities
|
| 222 |
-
top5_probs = probabilities[top5_indices]
|
| 223 |
-
top5_labels = [class_labels[i] for i in top5_indices]
|
| 224 |
-
ax.bar(top5_labels, top5_probs, color='skyblue')
|
| 225 |
-
ax.set_ylabel("Probability")
|
| 226 |
-
ax.set_title("Class Probabilities")
|
| 227 |
-
ax.set_ylim([0, 1])
|
| 228 |
-
plt.tight_layout(pad=3)
|
| 229 |
-
ax.set_xticklabels(top5_labels, rotation=45, ha="right", fontsize=8)
|
| 230 |
-
for i, v in enumerate(top5_probs):
|
| 231 |
-
ax.text(i, v + 0.02, f"{v:.2f}", ha='center', fontsize=10)
|
| 232 |
-
|
| 233 |
-
return final_image, gradcam_image, fig
|
| 234 |
|
| 235 |
# Gradio Interface
|
| 236 |
with gr.Blocks() as interface:
|
| 237 |
-
gr.Markdown("<h2 style='text-align: center;'>
|
| 238 |
|
| 239 |
with gr.Row():
|
| 240 |
with gr.Column():
|
| 241 |
-
image_input = gr.Image(type="pil", label="
|
| 242 |
-
overlay_input = gr.Image(type="pil", label="
|
| 243 |
brightness = gr.Slider(0.5, 2.0, value=1.0, label="Brightness")
|
| 244 |
contrast = gr.Slider(0.5, 2.0, value=1.0, label="Contrast")
|
| 245 |
hue = gr.Slider(-0.5, 0.5, value=0.0, label="Hue")
|
| 246 |
-
alpha = gr.Slider(0.0, 1.0, value=0.5, label="Overlay
|
|
|
|
| 247 |
|
| 248 |
with gr.Column():
|
| 249 |
-
processed_image = gr.Image(label="
|
| 250 |
gradcam_output = gr.Image(label="GradCAM Overlay")
|
| 251 |
-
bar_chart = gr.Plot(label="
|
| 252 |
|
| 253 |
-
inputs = [image_input, brightness, contrast, hue, overlay_input, alpha]
|
| 254 |
outputs = [processed_image, gradcam_output, bar_chart]
|
| 255 |
-
|
| 256 |
-
|
| 257 |
-
|
| 258 |
-
overlay_input.change(predict, inputs=inputs, outputs=outputs)
|
| 259 |
-
brightness.change(predict, inputs=inputs, outputs=outputs)
|
| 260 |
-
contrast.change(predict, inputs=inputs, outputs=outputs)
|
| 261 |
-
hue.change(predict, inputs=inputs, outputs=outputs)
|
| 262 |
-
alpha.change(predict, inputs=inputs, outputs=outputs)
|
| 263 |
|
| 264 |
interface.launch()
|
|
|
|
| 6 |
import numpy as np
|
| 7 |
import gradio as gr
|
| 8 |
import torch.nn as nn
|
| 9 |
+
import torch.optim as optim
|
| 10 |
from torchvision import models
|
| 11 |
import torch.nn.functional as F
|
| 12 |
import matplotlib.pyplot as plt
|
|
|
|
| 33 |
cifar10_classes = {int(k): v[1] for k, v in imagenet_classes.items()}
|
| 34 |
|
| 35 |
# Load the pre-trained ResNet model
|
| 36 |
+
model = models.resnet152(pretrained=True)
|
| 37 |
|
| 38 |
# Modify the classifier for 6 classes with an additional hidden layer
|
| 39 |
# model.fc = nn.Sequential(
|
|
|
|
| 183 |
|
| 184 |
return Image.fromarray(blended_array)
|
| 185 |
|
| 186 |
+
def generate_adversarial(input_image, orig_pred, epsilon=12/255, steps=50):
|
| 187 |
+
"""Generate adversarial example"""
|
| 188 |
+
input_image = transform_image(input_image)
|
| 189 |
+
delta = torch.zeros_like(input_image, requires_grad=True)
|
| 190 |
+
opt = optim.SGD([delta], lr=1e-1, momentum=0.9)
|
| 191 |
+
|
| 192 |
+
for _ in range(steps):
|
| 193 |
+
perturbed = torch.clamp(input_image + delta, 0.0, 1.0)
|
| 194 |
+
output = model(perturbed)
|
| 195 |
+
loss = -F.cross_entropy(output, torch.tensor([orig_pred], device=device))
|
| 196 |
+
print(loss.item())
|
| 197 |
+
|
| 198 |
+
opt.zero_grad()
|
| 199 |
+
loss.backward()
|
| 200 |
+
opt.step()
|
| 201 |
+
delta.data.clamp_(-epsilon, epsilon)
|
| 202 |
+
|
| 203 |
+
return torch.clamp(input_image + delta, 0.0, 1.0)
|
| 204 |
+
|
| 205 |
# Prediction function
|
| 206 |
+
def predict(image, brightness, contrast, hue, overlay_image, alpha, adversarial_switch):
|
| 207 |
+
"""Main prediction function"""
|
| 208 |
if image is None:
|
| 209 |
return None, None, None
|
| 210 |
|
| 211 |
+
# Apply preprocessing
|
| 212 |
+
processed = apply_filters(image, brightness, contrast, hue)
|
| 213 |
+
final_image = superimpose_images(processed, overlay_image, alpha)
|
| 214 |
+
|
| 215 |
+
# Convert to tensor
|
| 216 |
+
to_tensor = transforms.Compose([transforms.Resize(32), transforms.ToTensor()])
|
| 217 |
+
# img_tensor_01 = to_tensor(final_image).unsqueeze(0).to(device)
|
| 218 |
+
|
| 219 |
+
# Generate adversarial if enabled
|
| 220 |
+
if adversarial_switch:
|
| 221 |
+
with torch.no_grad():
|
| 222 |
+
orig_out = model(transform_image(final_image))
|
| 223 |
+
orig_pred = torch.argmax(orig_out).item()
|
| 224 |
+
adv_tensor_01 = generate_adversarial(final_image, orig_pred)
|
| 225 |
+
final_display = transforms.ToPILImage()(adv_tensor_01.squeeze().cpu().detach())
|
| 226 |
+
model_input = transform_image(final_display)
|
| 227 |
+
else:
|
| 228 |
+
final_display = final_image
|
| 229 |
+
model_input = transform_image(final_image)
|
| 230 |
+
|
| 231 |
+
# Get predictions
|
| 232 |
+
with torch.no_grad():
|
| 233 |
+
output = model(model_input)
|
| 234 |
+
probs = F.softmax(output, dim=1).cpu().numpy()[0]
|
| 235 |
+
|
| 236 |
+
# Generate Grad-CAM
|
| 237 |
+
heatmap, _ = gradcam.generate(model_input)
|
| 238 |
+
final_np = np.array(final_display)
|
| 239 |
+
heatmap = cv2.resize(heatmap, final_np.shape[:2][::-1])
|
| 240 |
+
heatmap = cv2.applyColorMap(np.uint8(255 * heatmap), cv2.COLORMAP_JET)
|
| 241 |
+
superimposed = cv2.addWeighted(cv2.cvtColor(heatmap, cv2.COLOR_BGR2RGB), 0.5, final_np, 0.5, 0)
|
| 242 |
+
|
| 243 |
+
# Create plot
|
| 244 |
+
fig, ax = plt.subplots(figsize=(6, 4))
|
| 245 |
+
top5_idx = np.argsort(probs)[-5:][::-1]
|
| 246 |
+
ax.bar([class_labels[i] for i in top5_idx], probs[top5_idx], color='skyblue')
|
| 247 |
+
ax.set_ylabel("Probability"), ax.set_title("Class Probabilities")
|
| 248 |
+
plt.xticks(rotation=45, ha='right', fontsize=8)
|
| 249 |
+
plt.tight_layout()
|
| 250 |
|
| 251 |
+
return final_display, Image.fromarray(superimposed), fig
|
|
|
|
| 252 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 253 |
|
| 254 |
# Gradio Interface
|
| 255 |
with gr.Blocks() as interface:
|
| 256 |
+
gr.Markdown("<h2 style='text-align: center;'>CIFAR-10 Classifier with Adversarial Attacks</h2>")
|
| 257 |
|
| 258 |
with gr.Row():
|
| 259 |
with gr.Column():
|
| 260 |
+
image_input = gr.Image(type="pil", label="Input Image")
|
| 261 |
+
overlay_input = gr.Image(type="pil", label="Overlay Image (Optional)")
|
| 262 |
brightness = gr.Slider(0.5, 2.0, value=1.0, label="Brightness")
|
| 263 |
contrast = gr.Slider(0.5, 2.0, value=1.0, label="Contrast")
|
| 264 |
hue = gr.Slider(-0.5, 0.5, value=0.0, label="Hue")
|
| 265 |
+
alpha = gr.Slider(0.0, 1.0, value=0.5, label="Overlay Alpha")
|
| 266 |
+
adversarial_switch = gr.Checkbox(label="Add Adversarial Noise")
|
| 267 |
|
| 268 |
with gr.Column():
|
| 269 |
+
processed_image = gr.Image(label="Processed Image")
|
| 270 |
gradcam_output = gr.Image(label="GradCAM Overlay")
|
| 271 |
+
bar_chart = gr.Plot(label="Predictions")
|
| 272 |
|
| 273 |
+
inputs = [image_input, brightness, contrast, hue, overlay_input, alpha, adversarial_switch]
|
| 274 |
outputs = [processed_image, gradcam_output, bar_chart]
|
| 275 |
+
|
| 276 |
+
for component in [image_input, overlay_input, brightness, contrast, hue, alpha, adversarial_switch]:
|
| 277 |
+
component.change(predict, inputs=inputs, outputs=outputs)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 278 |
|
| 279 |
interface.launch()
|