Spaces:
Sleeping
Sleeping
import gradio as gr | |
import os | |
# Paths for images | |
yolov5_result = os.path.join(os.getcwd(), "data/xai/yolov5.png") | |
yolov8_result = os.path.join(os.getcwd(), "data/xai/yolov8.png") | |
yolov5_dff = os.path.join(os.getcwd(), "data/xai/yolov5_dff.png") | |
yolov8_dff = os.path.join(os.getcwd(), "data/xai/yolov8_dff.png") | |
description_yolov5 = """ | |
### Feature Focus Comparison | |
| Feature | <span style="color: maroon;"><strong>Dogs</strong></span> | <span style="color: maroon;"><strong>Cats</strong></span> | | |
|-------------------|-----------------------------------|-------------------------------| | |
| **Face & Snout** | Eyes, nose, and mouth for recognition | Sharp eyes, whiskers | | |
| **Ears** | Pointed or floppy shapes | Pointed for identification | | |
| **Body Shape** | Legs, tail, and contour | Compact, sitting posture | | |
| **Fur Texture** | Curly (poodles), smooth (corgis) | N/A | | |
| **Tail & Paws** | N/A | Often highlighted | | |
### Common Errors | |
| Issue | Description | | |
|-------------------|-----------------------------------| | |
| **Background** | Irrelevant areas confused with key features | | |
| **Shared Features**| Overlapping fur or body shapes causing errors | | |
### Insights: | |
- Visualizations help identify key traits and potential classification biases. | |
""" | |
description_yolov8 = """ | |
### Feature Focus Comparison | |
| Feature | **Dogs** | **Cats** | | |
|---------------------|---------------------------------------|-----------------------------------| | |
| **Facial Features** | Eyes, nose, mouth for species ID | Sharp focus on eyes and whiskers | | |
| **Ears & Fur Texture**| Fluffy/smooth fur, pointed/floppy ears | N/A | | |
| **Body & Legs** | Focus on contour, legs, and tails | Emphasizes compact size and tail | | |
| **Paws & Posture** | N/A | Sitting posture, paw structures | | |
### Common Errors | |
| Issue | Description | | |
|---------------------|---------------------------------------| | |
| **Background Focus**| Attention to irrelevant background regions | | |
| **Shared Features** | Overlapping features between dogs and cats | | |
| **Edge Effects** | Bias from emphasis on image borders during training | | |
### Insights: | |
- Attention-based mechanisms can improve focus on key features and reduce misclassification. | |
""" | |
# Netron HTML templates | |
def get_netron_html(model_url): | |
return f""" | |
<div style="background-color: black; padding: 1px; border: 0.5px solid white;"> | |
<iframe | |
src="{model_url}" | |
width="100%" | |
height="800" | |
frameborder="0"> | |
</iframe> | |
</div> | |
""" | |
# URLs for Netron visualizations | |
yolov5_url = "https://netron.app/?url=https://huggingface.co/FFusion/FFusionXL-BASE/blob/main/vae_encoder/model.onnx" | |
yolov8_url = "https://netron.app/?url=https://huggingface.co/spaces/BhumikaMak/NeuralVista/resolve/main/weight_files/yolov8s.pt" | |
custom_css = """ | |
body { | |
background-color: white; | |
background-size: 1800px 1800px; | |
height: 100%; | |
color-scheme: light !important; | |
margin: 0; | |
overflow-y: auto; | |
} | |
#neural-vista-title { | |
color: #800000 !important; | |
font-size: 32px; | |
font-weight: bold; | |
text-align: center; | |
} | |
#neural-vista-text { | |
color: #800000 !important; | |
font-size: 18px; | |
font-weight: bold; | |
text-align: center; | |
} | |
#highlighted-text { | |
font-weight: bold; | |
color: #1976d2; | |
} | |
.custom-row { | |
display: flex; | |
justify-content: center; /* Align horizontally */ | |
align-items: center; /* Align vertically */ | |
padding: 10px; /* Adjust as needed for spacing */ | |
} | |
.custom-button { | |
background-color: #800000; | |
color: white; | |
font-size: 12px; /* Small font size */ | |
width: 100px !important; /* Fixed width */ | |
height: 35px !important; /* Fixed height */ | |
border-radius: 6px; /* Slightly rounded corners */ | |
padding: 0 !important; /* Remove extra padding */ | |
cursor: pointer; | |
text-align: center; | |
margin: 0 auto; /* Center within its container */ | |
box-sizing: border-box; /* Ensure consistent sizing */ | |
} | |
#run-button { | |
background-color: #800000 !important; | |
color: white !important; | |
font-size: 12px !important; /* Small font size */ | |
width: 100px !important; /* Fixed width */ | |
height: 35px !important; /* Fixed height */ | |
border-radius: 6px !important; | |
padding: 0 !important; | |
text-align: center !important; | |
display: block !important; /* Ensure block-level alignment */ | |
margin: 0 auto !important; /* Center horizontally */ | |
box-sizing: border-box !important; | |
} | |
/* Custom border styles for all Gradio components */ | |
.gradio-container, .gradio-row, .gradio-column, .gradio-input, .gradio-image, .gradio-checkgroup, .gradio-button, .gradio-markdown { | |
border: 3px #800000 !important; /* Border width and color */ | |
border-radius: 8px !important; /* Rounded corners */ | |
} | |
/* Additional customizations for images to enhance visibility of the border */ | |
.gradio-image img { | |
border-radius: 8px !important; | |
border: 3px solid black !important; /* Border for image */ | |
} | |
/* Custom Row for images and buttons */ | |
.custom-row img { | |
border-radius: 10px; | |
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); | |
} | |
#highlighted-text { | |
font-weight: bold; | |
color: #1976d2; | |
} | |
.gradio-block { | |
max-height: 100vh; /* Allow scrolling within the Gradio blocks */ | |
overflow-y: auto; /* Enable scrolling for the content if it overflows */ | |
} | |
#neural-vista-title { | |
color: #800000 !important; /* Purple color for the title */ | |
font-size: 32px; /* Adjust font size as needed */ | |
font-weight: bold; | |
text-align: center; | |
} | |
#neural-vista-text { | |
color: #800000 !important; /* Purple color for the title */ | |
font-size: 18px; /* Adjust font size as needed */ | |
font-weight: bold; | |
text-align: center; | |
} | |
""" | |
import netron | |
import threading | |
import gradio as gr | |
import os | |
from PIL import Image | |
import cv2 | |
import numpy as np | |
from yolov5 import xai_yolov5 | |
from yolov8 import xai_yolov8s | |
# Sample images directory | |
sample_images = { | |
"Sample 1": os.path.join(os.getcwd(), "data/xai/sample1.jpeg"), | |
"Sample 2": os.path.join(os.getcwd(), "data/xai/sample2.jpg"), | |
} | |
def load_sample_image(sample_name): | |
"""Load a sample image based on user selection.""" | |
image_path = sample_images.get(sample_name) | |
if image_path and os.path.exists(image_path): | |
return Image.open(image_path) | |
return None | |
def process_image(sample_choice, uploaded_image, yolo_versions, target_lyr = -5, n_components = 8): | |
"""Process the image using selected YOLO models.""" | |
# Load sample or uploaded image | |
if uploaded_image is not None: | |
image = uploaded_image | |
else: | |
image = load_sample_image(sample_choice) | |
# Preprocess image | |
image = np.array(image) | |
image = cv2.resize(image, (640, 640)) | |
result_images = [] | |
# Apply selected models | |
for yolo_version in yolo_versions: | |
if yolo_version == "yolov5": | |
result_images.append(xai_yolov5(image, target_lyr = -5, n_components = 8)) | |
elif yolo_version == "yolov8s": | |
result_images.append(xai_yolov8s(image)) | |
else: | |
result_images.append((Image.fromarray(image), f"{yolo_version} not implemented.")) | |
return result_images | |
def view_model(selected_models): | |
"""Generate Netron visualization for the selected models.""" | |
netron_html = "" | |
for model in selected_models: | |
if model=="yolov8s": | |
netron_html = f""" | |
<iframe | |
src="https://netron.app/?url=https://huggingface.co/spaces/BhumikaMak/NeuralVista/resolve/main/weight_files/yolov8s.pt" | |
width="100%" | |
height="800" | |
frameborder="0"> | |
</iframe> | |
""" | |
if model == "yolov5": | |
netron_html = f""" | |
<iframe | |
src="https://netron.app/?url=https://huggingface.co/FFusion/FFusionXL-BASE/blob/main/vae_encoder/model.onnx" | |
width="100%" | |
height="800" | |
frameborder="0"> | |
</iframe> | |
""" | |
return netron_html if netron_html else "<p>No valid models selected for visualization.</p>" | |
with gr.Blocks(css=custom_css, theme="default") as demo: | |
gr.HTML(""" | |
<div style="border: 2px solid #a05252; padding: 20px; border-radius: 8px;"> | |
<span style="color: #800000; font-family: 'Papyrus', cursive; font-weight: bold; font-size: 32px;">NeuralVista</span><br><br> | |
<span style="color: black; font-family: 'Papyrus', cursive; font-size: 18px;">A harmonious framework of tools <span style="color: red; font-family: 'Papyrus', cursive; font-size: 18px;">☼</span> designed to illuminate the inner workings of AI.</span> | |
</div> | |
""") | |
with gr.Row(): | |
with gr.Column(): | |
gr.Markdown(""" ## Yolov5 """) | |
html_content1 = """ | |
<div style="display: flex; gap: 10px;"> | |
<a href="https://github.com/ultralytics/yolov5/actions" target="_blank"> | |
<img src="https://img.shields.io/badge/YOLOv5%20CI-passing-brightgreen" alt="YOLOv5 CI"> | |
</a> | |
<a href="https://doi.org/10.5281/zenodo.7347926" target="_blank"> | |
<img src="https://img.shields.io/badge/DOI-10.5281%2Fzenodo.7347926-blue" alt="DOI"> | |
</a> | |
<a href="https://hub.docker.com/r/ultralytics/yolov5" target="_blank"> | |
<img src="https://img.shields.io/badge/docker%20pulls-361k-blue" alt="Docker Pulls"> | |
</a> | |
</div> | |
""" | |
gr.HTML(html_content1) | |
# gr.HTML(get_netron_html(yolov5_url)) | |
gr.Image(yolov5_result, label="Detections & Interpretability Map") | |
gr.Markdown(description_yolov5) | |
gr.Image(yolov5_dff, label="Feature Factorization & discovered concept") | |
with gr.Column(): | |
gr.Markdown(""" ## Yolov8s """) | |
html_content2 = """ | |
<div style="display: flex; gap: 10px;"> | |
<a href="https://github.com/ultralytics/ultralytics/actions" target="_blank"> | |
<img src="https://img.shields.io/badge/YOLOv8%20CI-passing-brightgreen" alt="YOLOv8 CI"> | |
</a> | |
<a href="https://zenodo.org/records/10443804" target="_blank"> | |
<img src="https://img.shields.io/badge/DOI-10.5281%2Fzenodo.7347926-blue" alt="DOI"> | |
</a> | |
<a href="https://hub.docker.com/r/ultralytics/ultralytics" target="_blank"> | |
<img src="https://img.shields.io/badge/docker%20pulls-500k-blue" alt="Docker Pulls"> | |
</a> | |
</div> | |
""" | |
gr.HTML(html_content2) | |
# gr.HTML(get_netron_html(yolov8_url)) | |
gr.Image(yolov8_result, label="Detections & Interpretability Map") | |
gr.Markdown(description_yolov8) | |
gr.Image(yolov8_dff, label="Feature Factorization & discovered concept") | |
gr.HTML( | |
""" | |
<div style="text-align: center; border: 3px solid maroon; padding: 10px; border-radius: 10px; background-color: #f8f8f8;"> | |
<h3>Want to try yourself? 🚀</h3> | |
<p><b>Upload an image below to discover <span style="color: #ff6347;">☼</span> the concepts</b></p> | |
</div> | |
""" | |
) | |
default_sample = "Sample 1" | |
with gr.Row(): | |
# Left side: Sample selection and image upload | |
with gr.Column(): | |
sample_selection = gr.Radio( | |
choices=list(sample_images.keys()), | |
label="Select a Sample Image", | |
value=default_sample, | |
) | |
upload_image = gr.Image( | |
label="Upload an Image", | |
type="pil", | |
) | |
selected_models = gr.CheckboxGroup( | |
choices=["yolov5", "yolov8s"], # Only the models that can be selected | |
value=["yolov5"], | |
label="Select Model(s)", | |
) | |
run_button = gr.Button("Run", elem_id="run-button") | |
with gr.Column(): | |
sample_display = gr.Image( | |
value=load_sample_image(default_sample), | |
label="Selected Sample Image", | |
) | |
# Results and visualization | |
with gr.Row(elem_classes="custom-row"): | |
result_gallery = gr.Gallery( | |
label="Results", | |
rows=1, | |
height="auto", # Adjust height automatically based on content | |
columns=1 , | |
object_fit="contain" | |
) | |
netron_display = gr.HTML(label="Netron Visualization") | |
# Update sample image | |
sample_selection.change( | |
fn=load_sample_image, | |
inputs=sample_selection, | |
outputs=sample_display, | |
) | |
gr.Markdown(""" #### Feature Factorization & discovered concepts. """) | |
with gr.Row(elem_classes="custom-row"): | |
dff_gallery = gr.Gallery( | |
label="Feature Factorization & discovered concept", | |
rows=2, # 8 rows | |
columns=4, # 1 image per row | |
object_fit="fit", | |
height="auto" # Adjust as needed | |
) | |
# Multi-threaded processing | |
def run_both(sample_choice, uploaded_image, selected_models): | |
results = [] | |
netron_html = "" | |
# Thread to process the image | |
def process_thread(): | |
nonlocal results | |
target_lyr = -5 | |
n_components = 8 | |
results = process_image(sample_choice, uploaded_image, selected_models, target_lyr = -5, n_components = 8) | |
# Thread to generate Netron visualization | |
def netron_thread(): | |
nonlocal netron_html | |
gr.HTML(""" | |
Generated abstract visualizations of model""") | |
netron_html = view_model(selected_models) | |
# Launch threads | |
t1 = threading.Thread(target=process_thread) | |
t2 = threading.Thread(target=netron_thread) | |
t1.start() | |
t2.start() | |
t1.join() | |
t2.join() | |
image1, text, image2 = results[0] | |
if isinstance(image2, list): | |
# Check if image2 contains exactly 8 images | |
if len(image2) == 8: | |
print("image2 contains 8 images.") | |
else: | |
print("Warning: image2 does not contain exactly 8 images.") | |
else: | |
print("Error: image2 is not a list of images.") | |
return [(image1, text)], netron_html, image2 | |
# Run button click | |
run_button.click( | |
fn=run_both, | |
inputs=[sample_selection, upload_image, selected_models], | |
outputs=[result_gallery, netron_display, dff_gallery], | |
) | |
demo.launch() | |